K8s on Vagrant, Workerノードの追加と削除


k8sクラスタに、新たなノードを追加、削除、再編入する方法のメモです。 

この記事は、k8s on Vagrant の６回目です。

1. [Kubenetes v1.10 クラスタをVagrantで構築したメモ](https://qiita.com/MahoTakara/items/28cd766d0447140b7ae3)
1. [K8s on Vagrant, Node障害時の振る舞いについての検証記録](https://qiita.com/MahoTakara/items/9b106664492303e1ba01)
1. [K8s on Vagrant, ダッシュボードのセットアップ](https://qiita.com/MahoTakara/items/b9b1d4bdc5a3e0d6ddfb)
1. [K8s on Vagrant, NFS 永続ボリュームの利用メモ](https://qiita.com/MahoTakara/items/c07b1b3418fc9b7130f6)
1. [K8s on Vagrant, NGINX Ingress Controller の利用](https://qiita.com/MahoTakara/items/cdfa379f2280a58fdd6d)


## ワーカノードの追加

### 追加のWorkerノードを起動

ノードのセットアップは、前述の1回目の「[Kubenetes v1.10 クラスタをVagrantで構築したメモ](https://qiita.com/MahoTakara/items/28cd766d0447140b7ae3)」のVagrantfileを変更して、新たなノード k8s4 を作成します。

~~~
$ vagrant up k8s4
~~~

追加したノードにログインして、ネットワークの初期設定のファイルを変更します。

~~~
$ vagrant ssh k8s4
~~~


### ネットワーク設定の変更

次のファイルを編集する。

~~~
$ sudo -s
root@k8s4:~# vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
~~~


--node-ipに、自己ノードのIPアドレスをセット

~~~10-kubeadm.conf
省略
Environment="KUBELET_DNS_ARGS=--cluster-dns=10.244.0.10 --cluster-domain=cluster.local --node-ip=172.42.42.14"
省略
~~~

設定を読み込ませて、kubelet デーモンを再起動

~~~~
root@k8s4:~# systemctl daemon-reload
root@k8s4:~# systemctl restart kubelet
~~~~




### マスターノードでトークンの生成

トークンの有効期限が切れている場合は、マスターノードでトークンを生成します。

~~~
root@k8s1:~# kubeadm token create
9u28t5.5725jznlj67vu2bz
~~~

メモっておいた、マスターノードをセットアップした時の最後のメッセージで、--discovery-token-ca-cert-hashの値を再使用
また、 --token は上記で作成したトークンを利用します。 トークンの有効期限?は、１日程度はあるので、毎回createしなくても良い様です。

~~~memo
Your Kubernetes master has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

You can now join any number of machines by running the following on each node
as root:

  kubeadm join 172.42.42.11:6443 --token 6l3di0.azqz2qvamk24mjuj --discovery-token-ca-cert-hash sha256:f1fa8b0f197792f7b7a97d2798a262573a7d058959aa7aff42e65d3b2a679450
~~~



### ワーカーノードでJOINの実行

前述の情報から kubeadm join のオプションの情報を得て、クラスタへ追加する。

~~~
root@k8s4:~# kubeadm join 172.42.42.11:6443 --token 9u28t5.5725jznlj67vu2bz --discovery-token-ca-cert-hash sha256:f1fa8b0f197792f7b7a97d2798a262573a7d058959aa7aff42e65d3b2a679450
[preflight] Running pre-flight checks.
	[WARNING FileExisting-crictl]: crictl not found in system path
Suggestion: go get github.com/kubernetes-incubator/cri-tools/cmd/crictl
[discovery] Trying to connect to API Server "172.42.42.11:6443"
[discovery] Created cluster-info discovery client, requesting info from "https://172.42.42.11:6443"
[discovery] Requesting info from "https://172.42.42.11:6443" again to validate TLS against the pinned public key
[discovery] Cluster info signature and contents are valid and TLS certificate validates against pinned roots, will use API Server "172.42.42.11:6443"
[discovery] Successfully established connection with API Server "172.42.42.11:6443"

This node has joined the cluster:
* Certificate signing request was sent to master and a response
  was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the master to see this node join the cluster.
~~~


k8s4が追加された

~~~
vagrant@k8s1:~$ kubectl get node
NAME      STATUS    ROLES     AGE       VERSION
k8s1      Ready     master    12d       v1.10.1
k8s2      Ready     node      12d       v1.10.1
k8s3      Ready     node      12d       v1.10.1
k8s4      Ready     <none>    3m        v1.10.1
~~~

ラベルを追加

~~~
vagrant@k8s1:~$ kubectl label node k8s4 node-role.kubernetes.io/node=
node "k8s4" labeled
vagrant@k8s1:~$ kubectl get nodes
NAME      STATUS    ROLES     AGE       VERSION
k8s1      Ready     master    12d       v1.10.1
k8s2      Ready     node      12d       v1.10.1
k8s3      Ready     node      12d       v1.10.1
k8s4      Ready     node      4m        v1.10.1
~~~

さらに、ラベルを追加、デーモンセットで必要なラベルなので、必ず追加する。

~~~
vagrant@k8s1:~$ kubectl label nodes k8s4 type=worker
node "k8s4" labeled
~~~

~~~
vagrant@k8s1:~$ kubectl get nodes -L type
NAME      STATUS    ROLES     AGE       VERSION   TYPE
k8s1      Ready     master    12d       v1.10.1   master
k8s2      Ready     node      12d       v1.10.1   worker
k8s3      Ready     node      12d       v1.10.1   worker
k8s4      Ready     node      16m       v1.10.1   worker
~~~


追加完了!!!



## 追加ノードへのスケジュール

初期状態

~~~
vagrant@k8s1:~$ kubectl get pods -o wide
NAME                        READY     STATUS    RESTARTS   AGE       IP             NODE
echoheaders-4c9r8           1/1       Running   3          2h        10.244.2.186   k8s3
~~~

レプリカ数を増加

~~~
vagrant@k8s1:~$ kubectl scale --replicas=10 replicationcontroller echoheaders
replicationcontroller "echoheaders" scaled
~~~

特に何もしなくても、新しく追加したk8s4にもスケージュールされる

~~~
vagrant@k8s1:~$ kubectl get pods -o wide
NAME                        READY     STATUS    RESTARTS   AGE       IP             NODE
echoheaders-4c9r8           1/1       Running   3          2h        10.244.2.186   k8s3
echoheaders-568hm           1/1       Running   0          43s       10.244.2.196   k8s3
echoheaders-74kx6           1/1       Running   0          43s       10.244.5.5     k8s4
echoheaders-8z9tn           1/1       Running   0          43s       10.244.1.135   k8s2
echoheaders-bm7zn           1/1       Running   0          43s       10.244.5.2     k8s4
echoheaders-jh4bk           1/1       Running   0          43s       10.244.1.134   k8s2
echoheaders-kzzch           1/1       Running   0          43s       10.244.5.3     k8s4
echoheaders-p5sxv           1/1       Running   0          43s       10.244.1.133   k8s2
echoheaders-t9f6v           1/1       Running   0          43s       10.244.2.197   k8s3
echoheaders-tlvzj           1/1       Running   0          43s       10.244.5.4     k8s4
~~~


## ノードの削除の準備

特定ノードへのスケジュールの停止

~~~
vagrant@k8s1:~$ kubectl cordon k8s2
node "k8s2" cordoned
~~~


ポッドの追い出し

~~~
vagrant@k8s1:~$ kubectl drain k8s2 --ignore-daemonsets
node "k8s2" already cordoned
WARNING: Ignoring DaemonSet-managed pods: kube-flannel-ds-5lsd4, kube-proxy-n82vs, kube-keepalived-vip-5xsvq
pod "echoheaders-8z9tn" evicted
pod "echoheaders-p5sxv" evicted
pod "echoheaders-jh4bk" evicted
node "k8s2" drained
~~~
  
追い出し完了状態

~~~
vagrant@k8s1:~$ kubectl get pods -o wide
NAME                        READY     STATUS    RESTARTS   AGE       IP             NODE
echoheaders-4c9r8           1/1       Running   3          2h        10.244.2.186   k8s3
echoheaders-568hm           1/1       Running   0          5m        10.244.2.196   k8s3
echoheaders-74kx6           1/1       Running   0          5m        10.244.5.5     k8s4
echoheaders-7cfbq           1/1       Running   0          43s       10.244.2.198   k8s3
echoheaders-bm7zn           1/1       Running   0          5m        10.244.5.2     k8s4
echoheaders-kzzch           1/1       Running   0          5m        10.244.5.3     k8s4
echoheaders-rlcn6           1/1       Running   0          43s       10.244.5.7     k8s4
echoheaders-t9f6v           1/1       Running   0          5m        10.244.2.197   k8s3
echoheaders-tlvzj           1/1       Running   0          5m        10.244.5.4     k8s4
echoheaders-x68xb           1/1       Running   0          43s       10.244.5.6     k8s4
~~~



## クラスタからのノードの除去

k8s2は、既に削除可能な状態となっている

~~~
vagrant@k8s1:~$ kubectl get node
NAME      STATUS                     ROLES     AGE       VERSION
k8s1      Ready                      master    12d       v1.10.1
k8s2      Ready,SchedulingDisabled   node      12d       v1.10.1
k8s3      Ready                      node      12d       v1.10.1
k8s4      Ready                      node      14m       v1.10.1
~~~

ノードの削除は、delete nodeするだけ

~~~
vagrant@k8s1:~$ kubectl delete node k8s2
node "k8s2" deleted
~~~

削除結果

~~~
vagrant@k8s1:~$ kubectl get node
NAME      STATUS    ROLES     AGE       VERSION
k8s1      Ready     master    12d       v1.10.1
k8s3      Ready     node      12d       v1.10.1
k8s4      Ready     node      14m       v1.10.1
~~~



## 切り離したノードの再編入

これから追加するノードで、設定のリセット、そして、ジョイン

~~~
root@k8s2:~# kubeadm reset

root@k8s2:~# kubeadm join 172.42.42.11:6443 --token 9u28t5.5725jznlj67vu2bz --discovery-token-ca-cert-hash sha256:f1fa8b0f197792f7b7a97d2798a262573a7d058959aa7aff42e65d3b2a679450
~~~

上記実行後

~~~
vagrant@k8s1:~$ kubectl get node
NAME      STATUS    ROLES     AGE       VERSION
k8s1      Ready     master    12d       v1.10.1
k8s2      Ready     <none>    48s       v1.10.1
k8s3      Ready     node      12d       v1.10.1
k8s4      Ready     node      19m       v1.10.1
~~~

ラベルの付与

~~~
vagrant@k8s1:~$ kubectl label node k8s2 node-role.kubernetes.io/node=
node "k8s2" labeled

vagrant@k8s1:~$ kubectl label nodes k8s2 type=worker
node "k8s2" labeled
~~~

ラベル付与の結果です。 これで、ポッドがスケジュールされる様になります。

~~~
vagrant@k8s1:~$ kubectl get nodes -L type
NAME      STATUS    ROLES     AGE       VERSION   TYPE
k8s1      Ready     master    12d       v1.10.1   master
k8s2      Ready     node      2m        v1.10.1   worker
k8s3      Ready     node      12d       v1.10.1   worker
k8s4      Ready     node      20m       v1.10.1   worker
~~~