kubespray での kubernetes クラスタ構築メモ

## はじめに
自宅サーバで kubernetes クラスタを構築する際に kubespray を利用した個人的なメモ。
QiitaもMarkdownも慣れてないがとりあえず書いてみた。
kubespray はプロダクション環境/冗長構成にも対応でき、ansibleベースのため採用した。

## kubespray url
詳細情報はこちら。
[github](https://github.com/kubernetes-sigs/kubespray)
[kubespray.io](https://kubespray.io/#/)

## 構成・実行環境・スペック
kubernetes cluster 構成は下記の通り。
 - MasterNode x3
 - WorkerNode x3
 - CalicoRR x2


### 物理/共通
Hardware   : intel nuc x 2 (NUC8i5BEH, NUC8i5BEK) Mem: 32GB/node
Hypervisor : ESXi 6.7.0 Update1
OS         : CentOS 7.7.1908 (Minimal)
Kubespray  : v2.12.0
Kubernetes : v1.16.3
CNI        : Calico

CentOS8 は構築時に kubespray で[サポート](https://github.com/kubernetes-sigs/kubespray#supported-linux-distributions)されていないため、 CentOS7 とした。
Kubernetes は構築時に kubespray でのサポート/デフォルトの Versionとなる。

### MasterNode
CPU : 2vCPUs
Mem : 4GB

[kubesprayのrequirements](https://github.com/kubernetes-sigs/kubespray/blob/master/README.md#requirements)に記載の最小サイズは Memory: 1500 MB

### WorkerNode
CPU : 4vCPUs
Mem : 16GB (3node目はメモリ不足のため8GBにした)

[kubesprayのrequirements](https://github.com/kubernetes-sigs/kubespray/blob/master/README.md#requirements)に記載の最小サイズは Memory: 1024 MB

### CalicoRR
CPU : 2vCPUs
Mem : 2GB

Calicoは各ノードのルーティング交換をBGPで実行し、ルートリフレクタ(RR)を構築しないとフルメッシュとなるため、RRを構築する。

## kubespray download
Git で clone

```git
git clone https://github.com/kubernetes-sigs/kubespray.git
```
ディレクトリへcd

```移動
cd kubespray
```

lsするとこんな感じ。

```
# ls
CNAME            OWNERS             Vagrantfile         contrib          library                    requirements.txt  setup.cfg
CONTRIBUTING.md  OWNERS_ALIASES     _config.yml         docs             logo                       reset.yml         setup.py
Dockerfile       README.md          ansible.cfg         extra_playbooks  mitogen.yaml               roles             test-infra
LICENSE          RELEASE.md         cluster.yml         index.html       recover-control-plane.yml  scale.yml         tests
Makefile         SECURITY_CONTACTS  code-of-conduct.md  inventory        remove-node.yml            scripts           upgrade-cluster.yml
```

この中で今回構築で使用するものを次に説明する。

## kubespray 利用方法
kubesprayはansibleベース。
初期構築で意識する箇所は下記の4つ。
 1. requirements.txt
 2. cluster.yml
 3. roles/
 4. inventory/

### requirements.txt
kubesprayを利用する際に、ansible等の必要なパッケージ等がバージョン指定で記載されている。
指定バージョン以外で実行すると、途中で止まったりしたので、基本はこのバージョンで実行する。(実行コマンドは後述)
### cluster.yml
構築に使用する playbook 。編集不要。(実行方法は後述)
### roles/
ansibleのrole。
実際の挙動を調べたい場合は、各roleのtasksやdefaultsなどを読む。
### inventory/
利用する上でのinventory例が記載されている。
基本編集はこのディレクトリまたは参考にしたinventory作成をしてパラメータ等を設定する。(編集例は後述)
(group_varsなどでパラメータ変更ができるが、これは初期構築時のためデフォルトパラメータを使用し、編集しない.今後検討)

## kubespray 実行に必要なパッケージをインストール
pipでインストールする。

```
sudo pip install -r requirements.txt
```

## kubespray inventory
sampleを編集用にコピーする。

```
cp -rfp inventory/sample inventory/mycluster
```
[README](https://github.com/kubernetes-sigs/kubespray/blob/master/README.md)を読むとinventoryのビルド方法が書いてあるが、使用しなかった。(個人的に他のansibleのinventoryと統合して記載したいため)
下記のように手動でinventoryを記載した。
kubesprayがinventoryのホスト名に実行時に変更するので、仮想マシン側はlocalhostなど適当なホスト名で準備しておいても問題ない。

calicoRRの記載方法は[こちら](https://kubespray.io/#/docs/calico?id=optional-bgp-peering-with-route-reflectors)を参考にした。(cluster_idなどは、リンク先のパラメータ例のままにとりあえずしてます)

inventory例 (192.168.x.*は書き換えること)

```inventory/mycluster/inventory.ini
[all]
k8smaster01 ansible_host=192.168.x.11 ip=192.168.x.11
k8smaster02 ansible_host=192.168.x.21 ip=192.168.x.21
k8smaster03 ansible_host=192.168.x.12 ip=192.168.x.12
k8sworker01 ansible_host=192.168.x.13 ip=192.168.x.13
k8sworker02 ansible_host=192.168.x.22 ip=192.168.x.22
k8sworker03 ansible_host=192.168.x.23 ip=192.168.x.23
k8scalicorr01 ansible_host=192.168.x.14 ip=192.168.x.14
k8scalicorr02 ansible_host=192.168.x.24 ip=192.168.x.24

[kube-master]
k8smaster01
k8smaster02
k8smaster03

[etcd]
k8smaster01
k8smaster02
k8smaster03

[kube-node]
k8sworker01
k8sworker02
k8sworker03

[calico-rr]
k8scalicorr01
k8scalicorr02

[rack0]
k8scalicorr01
k8scalicorr02
k8smaster01
k8smaster02
k8smaster03
k8sworker01
k8sworker02
k8sworker03

[rack0:vars]
cluster_id="1.0.0.1"

[k8s-cluster:children]
kube-master
kube-node
calico-rr
```

### [2020.11.22 追記] inventory 記載方法
上記 INI 形式だとうまくいかないことを[アップグレード時](https://qiita.com/suzuyui/items/e5794e23045c9ae82a1c)に確認した。
上記の [Yaml 形式記載版](https://qiita.com/suzuyui/items/e5794e23045c9ae82a1c#1-hostsyaml-%E3%81%AE%E6%BA%96%E5%82%99)をアップグレード方法の方に記載したのでうまくいかない場合はそちらも参照。

## kubespray 実行前の事前設定
kubesprayの[前提](https://github.com/kubernetes-sigs/kubespray/blob/master/README.md#requirements)を参考に、対処が必要だった下記への対応を実施する。
1. **Your ssh key must be copied** to all the servers part of your inventory. (SSHキーを事前に各ノードへコピーする)
2. The **firewalls are not managed**, you'll need to implement your own rules the way you used to. (firewalldはoffにする)

また、**sshpassがインストールされていないと、kubesprayが途中で止まる**ので、それも入れる。

ここだけ手動もあれなので、事前サーバセットアップ向けにansible role・Playbookを下記のように用意し実行した。
ついでにyum updateとselinuxのoffとリブート、エディタ(emacs)のインストールもしている。

各サーバ事前設定role例(kubesprayとは別)

```/etc/ansible/roles/kubespray-presetup/tasks/main.yaml
---
# tasks file for kubespray-presetup

  - name: Selinux Disabled
    selinux:
      state: disabled
    register: selinux
    become: yes 

  - name: Update yum packages
    yum:
      name: '*'
      state: latest
      update_cache: yes
    become: yes

  - name: install sshpass and emacs
    yum:
      name: "{{ packages }}"
    vars:
      packages:
        - sshpass
        - emacs
      state: present
    become: yes

  - name: stop and disable firewalld
    systemd:
      name: firewalld
      state: stopped
      enabled: false
    become: yes

  - name: copy users ssh key to root authorized key
    authorized_key:
      user: root
      key: "{{ lookup('file', '/root/.ssh/id_rsa.pub') }}"
    become: yes

  - name: reboot
    reboot:
    when: selinux.reboot_required
    become: yes

```
```/etc/ansible/playbook/playbook_preset_kubespray.yml 
--- 
- hosts: k8s-cluster
  become: true
  gather_facts: yes

  roles:
    - kubespray-presetup
```

上記例のplaybookを実行する場合

``` 
ansible-playbook -i inventory/mycluster/inventory.ini /etc/ansible/playbook/playbook_preset_kubespray.yml --vvv -Kk
```

## kubespray 実行
あとは cluster.yml を実行するだけ。

```
ansible-playbook -i inventory/mycluster/inventory.ini cluster.yml -vvv --user root
```

環境にもよるが、10 ~ 40分ほどかかる。

構築完了後、下記のようにノード状態が確認できる。

```
[root@k8smaster01 ~]# kubectl get nodes
NAME            STATUS   ROLES    AGE   VERSION
k8scalicorr01   Ready    <none>   19d   v1.16.3
k8scalicorr02   Ready    <none>   19d   v1.16.3
k8smaster01     Ready    master   22d   v1.16.3
k8smaster02     Ready    master   22d   v1.16.3
k8smaster03     Ready    master   22d   v1.16.3
k8sworker01     Ready    <none>   22d   v1.16.3
k8sworker02     Ready    <none>   22d   v1.16.3
k8sworker03     Ready    <none>   22d   v1.16.3
```

calicoはRRを設置したため、各ノードはRRとのみpeer接続しているのがわかる。

```
[root@k8smaster01 ~]# calicoctl node status
Calico process is running.

IPv4 BGP status
+----------------+---------------+-------+------------+-------------+
|  PEER ADDRESS  |   PEER TYPE   | STATE |   SINCE    |    INFO     |
+----------------+---------------+-------+------------+-------------+
| 192.168.x.14   | node specific | up    | 2019-12-18 | Established |
| 192.168.x.24   | node specific | up    | 2019-12-18 | Established |
+----------------+---------------+-------+------------+-------------+

IPv6 BGP status
No IPv6 peers found.
```


## おわりに
kubesprayでの初期構築(デフォルトパラメータでの構築)時実施内容を記載した。
冗長構成などをansibleベースで構築できるのでよかった。

### 今後
kubespray の group_vars でのパラメータ編集は、calicoの設定、アドレスセグメントの設定、addonの設定など今後実施予定。
istioなども実施したいが、[kubesprayからは外れた](https://github.com/kubernetes-sigs/kubespray/pull/3073) かつ [helmでのインストールは今後削除予定とも注記](https://istio.io/docs/setup/install/helm/)があるでやり方検討中。
dashboardがうまく表示できないが同様な[issue](https://github.com/kubernetes-sigs/kubespray/issues/5347)が出ているので様子見中。

### [2020.11.22 追記] アップグレード
kubespray での kubernetes アップグレード方法を下記URLで記載した

kubespray での Kubernetes クラスタ アップグレード
https://qiita.com/suzuyui/items/e5794e23045c9ae82a1c