Kubernetesクラスタにノードを追加する

## はじめに
Kubernetsクラスタにノードを追加する。

今までの流れとしては、
- サーバ1台をコントロールプレーンノードとしてKubernetsクラスタをデプロイ
- CNIであるCalicoをデプロイ
である。

上記のようにシンプルなものから確かめていたので、今回サーバをもう一台購入したことを想定して、ノードの追加を行う。

## 参考文献
公式ドキュメントは以下
[Kubernetes Document](https://kubernetes.io/ja/docs/home/)

以下は、私が行ってきたデプロイ
[kubernetes intall](https://qiita.com/haru_yama/items/cdd721fbc48a577aedd0)
[Calico install](https://qiita.com/haru_yama/items/30e96adde58ef197238d)

## 前提条件
過去のデプロイが完了していること。

## Kubernetes公式ドキュメントより、ノードを追加する手順が記載された箇所を探す
まずは、ドキュメントを以下のよう進めていき、「ノードの追加」部分を参照する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680051/03fb5a2d-ee06-240c-73dd-8143d03ce1d2.png)

ここでは、簡単に言うとコントロールプレーンノードから各ワーカノードにSSH接続したうえで、ワーカノード上で1`kubeadm join`を実行する旨が記載されている。

現在は、workerノードも立ちげてないしkubernetesのインストールも行っていないので、そこから実施する。

## workerノードとなるサーバにkubernetsを一式インストールする。

### workerノードの作成
```
[実行コマンド]
hostname

[結果]
kube-worker01
```
workerのIPアドレスを確認する。
```
[実行コマンド]
ip a

[結果]
...
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:77:45:cd brd ff:ff:ff:ff:ff:ff
    inet 192.168.56.107/24 metric 100 brd 192.168.56.255 scope global dynamic enp0s8
...
```
workerのIPアドレスは、`192.168.56.107`である。

### kubernetsのインストール
以下の手順を参考にして、workerにもインストールする
[kubernetes intall](https://qiita.com/haru_yama/items/cdd721fbc48a577aedd0)

### インストール確認

```
[実行コマンド]
kubectl -n kube-system get pod

[結果]
NAME                                    READY   STATUS    RESTARTS   AGE
coredns-7db6d8ff4d-fchgk                0/1     Pending   0          2m
coredns-7db6d8ff4d-zzfvh                0/1     Pending   0          2m
etcd-kube-worker01                      1/1     Running   1          2m7s
kube-apiserver-kube-worker01            1/1     Running   0          2m7s
kube-controller-manager-kube-worker01   1/1     Running   0          2m7s
kube-proxy-mchqh                        1/1     Running   0          2m1s
kube-scheduler-kube-worker01            1/1     Running   0          2m7s
```
インストールされていることを確認できた。

## kubeadm joinを行う

### コントロールノードのトークン情報の確認し、ワーカで実行するkubeadm joinコマンドを作成
```
kubeadm token list
TOKEN                     TTL         EXPIRES                USAGES                   DESCRIPTION                                                EXTRA GROUPS
4rdhz7.kt4gq6ymgkfqkvof   16h         2024-07-29T02:10:40Z   authentication,signing   The default bootstrap token generated by 'kubeadm init'.   system:bootstrappers:kubeadm:default-node-token

```
`--discovery-token-ca-cert-hash`の値を取得する。
これは、Kubernetesの証明書から公開鍵のSHA-256ハッシュを取得するために使用される。
```
[実行コマンド]
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'

[結果]
002491affd90dab73742420b97b2c41bbd890eb6cbedd20befced8d70f4adfae
```
```

kubeadm join 10.0.2.15:6443 --token 4rdhz7.kt4gq6ymgkfqkvof --discovery-token-ca-cert-hash sha256:002491affd90dab73742420b97b2c41bbd890eb6cbedd20befced8d70f4adfae 

```

### コントロールプレーンノードからワーカへSSH接続する
workerのIPアドレスは、`192.168.56.107`である。

```
[実行コマンド]
ssh 192.168.56.107 

[finterprintを聞かれる]
The authenticity of host '192.168.56.107 (192.168.56.107)' can't be established.
ED25519 key fingerprint is SHA256:U+WXeRaHl6BYGLYw1hr1EANnWphqA3T3a7VSBhUH5bY.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])?

[入力内容]
yes

[パスワードを聞かれる]
Warning: Permanently added '192.168.56.107' (ED25519) to the list of known hosts.
mainte@192.168.56.107's password:

[入力内容]
... ←パスワードを入力

[結果]
...
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-113-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
...
mainte@kube-worker01:~$ 

```
となり、コントロールノードからワーカノードへログインできた。
マシンへSSHする

##

できた。今はNotReady状態だが、今後これを起動していく。
ワーカーノードでは`kubeadm init`を実施しなくても良かった。
```
kubectl get node
NAME                STATUS     ROLES           AGE     VERSION
kube-controller01   Ready      control-plane   6m44s   v1.30.2
kube-worker01       NotReady   <none>          10s     v1.30.2
```


## トラブルシュート

### worker のkubeadm init時にエラー

```
sudo kubeadm init
[init] Using Kubernetes version: v1.30.3
[preflight] Running pre-flight checks
error execution phase preflight: [preflight] Some fatal errors occurred:
        [ERROR FileAvailable--etc-kubernetes-manifests-kube-apiserver.yaml]: /etc/kubernetes/manifests/kube-apiserver.yaml already exists
        [ERROR FileAvailable--etc-kubernetes-manifests-kube-controller-manager.yaml]: /etc/kubernetes/manifests/kube-controller-manager.yaml already exists
        [ERROR FileAvailable--etc-kubernetes-manifests-kube-scheduler.yaml]: /etc/kubernetes/manifests/kube-scheduler.yaml already exists
        [ERROR FileAvailable--etc-kubernetes-manifests-etcd.yaml]: /etc/kubernetes/manifests/etcd.yaml already exists
        [ERROR DirAvailable--var-lib-etcd]: /var/lib/etcd is not empty
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher


sudo mv -r /var/lib/etcd /tmp
  123  sudo mv /var/lib/etcd /tmp
  124  sudo kubeadm init
  125  sudo mv /etc/kubernetes/manifests/kube-apiserver.yaml /tmp/
  126  sudo mv /etc/kubernetes/manifests/kube-controller-manager.yaml /tmp/
  127  sudo mv /etc/kubernetes/manifests/kube-scheduler.yaml /tmp/
  128* sudo mv /etc/kubernetes/manifests/etcd.yaml /tm
  
```

エラーの箇所のファイルを`/tmp`に移動した。

### ワーカーにSSH後、kubeadm joinエラー

```

sudo kubeadm join 10.0.2.15:6443 --token 4rdhz7.kt4gq6ymgkfqkvof --discovery-token-ca-cert-hash sha256:002491affd90dab73742420b97b2c41bbd890eb6cbedd20befced8d70f4adfae
[sudo] password for mainte: 
[preflight] Running pre-flight checks
error execution phase preflight: [preflight] Some fatal errors occurred:
        [ERROR FileAvailable--etc-kubernetes-kubelet.conf]: /etc/kubernetes/kubelet.conf already exists
        [ERROR Port-10250]: Port 10250 is in use
        [ERROR FileAvailable--etc-kubernetes-pki-ca.crt]: /etc/kubernetes/pki/ca.crt already exists
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher
```
```
sudo lsof -i :10250
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
kubelet 75194 root   14u  IPv6 390127      0t0  TCP *:10250 (LISTEN)

sudo systemctl stop kubelet
mainte@kube-worker01:~$ sudo lsof -i :10250
無し
```
とまった。
```
mainte@kube-worker01:~$ sudo mv /etc/kubernetes/kubelet.conf /tmp/
mainte@kube-worker01:~$ sudo mv /etc/kubernetes/pki/ca.
ca.crt  ca.key  
mainte@kube-worker01:~$ sudo mv /etc/kubernetes/pki/ca.crt /tmp
```

### エラー2

```
sudo kubeadm join 192.168.56.105:6443 --token 4rdhz7.kt4gq6ymgkfqkvof --discovery-token-ca-cert-hash sha256:002491affd90dab73742420b97b2c41bbd890eb6cbedd20befced8d70f4adfae
[sudo] password for mainte: 
[preflight] Running pre-flight checks
error execution phase preflight: couldn't validate the identity of the API Server: failed to request the cluster-info ConfigMap: client rate limiter Wait returned an error: rate: Wait(n=1) would exceed context deadline
To see the stack trace of this error execute with --v=5 or higher

```

詳しいログをみるために`--v=5`を付けて実行する。

```
sudo kubeadm join 192.168.56.105:6443 --token 4rdhz7.kt4gq6ymgkfqkvof --discovery-token-ca-cert-hash sha256:002491affd90dab73742420b97b2c41bbd890eb6cbedd20befced8d70f4adfae --v=5

I0728 10:14:01.734806   76358 join.go:417] [preflight] found NodeName empty; using OS hostname as NodeName
I0728 10:14:01.737081   76358 initconfiguration.go:122] detected and using CRI socket: unix:///var/run/crio/crio.sock
[preflight] Running pre-flight checks
I0728 10:14:01.738785   76358 preflight.go:93] [preflight] Running general checks
I0728 10:14:01.738973   76358 checks.go:278] validating the existence of file /etc/kubernetes/kubelet.conf
I0728 10:14:01.739374   76358 checks.go:278] validating the existence of file /etc/kubernetes/bootstrap-kubelet.conf
I0728 10:14:01.739384   76358 checks.go:102] validating the container runtime
I0728 10:14:01.770751   76358 checks.go:637] validating whether swap is enabled or not
...

I0728 10:14:01.872790   76358 token.go:117] [discovery] Requesting info from "192.168.56.105:6443" again to validate TLS against the pinned public key
I0728 10:14:01.873392   76358 token.go:210] [discovery] Waiting for the cluster-info ConfigMap to receive a JWS signaturefor token ID "4rdhz7"
I0728 10:14:01.878529   76358 token.go:221] [discovery] Retrying due to error: failed to request the cluster-info ConfigMap: Get "https://192.168.56.105:6443/api/v1/namespaces/kube-public/configmaps/cluster-info?timeout=10s": tls: failed to verify certificate: x509: certificate is valid for 10.96.0.1, 10.0.2.15, not 192.168.56.105
I0728 10:14:06.880347   76358 token.go:221] [discovery] Retrying due to error: failed to request the cluster-info ConfigMap: Get "https://192.168.56.105:6443/api/v1/namespaces/kube-public/configmaps/cluster-info?timeout=10s": tls: failed to verify certificate: x509: certificate is valid for 10.96.0.1, 10.0.2.15, not 192.168.56.105
```
ここでは、

```
ip aで確認
enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:b7:18:9c brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 metric 100 brd 10.0.2.255 scope global dynamic enp0s3
       valid_lft 53740sec preferred_lft 53740sec
    inet6 fe80::a00:27ff:feb7:189c/64 scope link 
       valid_lft forever preferred_lft forever
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:ba:49:07 brd ff:ff:ff:ff:ff:ff
    inet 192.168.56.105/24 metric 100 brd 192.168.56.255 scope global dynamic enp0s8
       valid_lft 432sec preferred_lft 432sec
    inet6 fe80::a00:27ff:feba:4907/64 scope link 
       valid_lft forever preferred_lft forever
```

ここに2つのIPがある
10.0.2.15と192.168.56.105である

```
sudo less /etc/kubernetes/manifests/kube-apiserver.yaml

name: kube-apiserver
    readinessProbe:
      failureThreshold: 3
      httpGet:
        host: 10.0.2.15
        path: /readyz
        port: 6443


 kubectl get endpoints -n default kubernetes
NAME         ENDPOINTS        AGE
kubernetes   10.0.2.15:6443   8h
```

```
sudo kubeadm init --apiserver-advertise-address=192.168.56.105 --pod-network-cidr=192.168.0.0/16
```
これでkubeadmを再起動してみる。

```
sudo kubeadm init --apiserver-advertise-address=192.168.56.105 --pod-network-cidr=192.168.0.0/16
[init] Using Kubernetes version: v1.30.3
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster

kubeadm join 192.168.56.105:6443 --token kiy0eu.2uqx1swkcnrhcvwx \
        --discovery-token-ca-cert-hash sha256:c7747150477bc79a68ff6c16e2c2ebe9150ccc7553800fdc8218d896f9850278 


sudo less /etc/kubernetes/manifests/kube-apiserver.yaml

 name: kube-apiserver
    readinessProbe:
      failureThreshold: 3
      httpGet:
        host: 192.168.56.105
        path: /readyz
        port: 6443
```
IPアドレスが変わっていることが分かった。