dockerランタイム非推奨時代のkubeadmによるcluster作成

#はじめに
##モチベーション
Dockerランタイムが非推奨になってkubeadmを使ったubuntu上でのクラスタ作成手順が色々変わってたのでメモ。

# インストール
##環境
- 最小構成: 2vCPU/2GB以上のVMまたは物理サーバ２台以上(master 1台 + worker 1台)
- 今回はUbuntu 20.04

## master/worker共通
masterまたはworkerをインストールするノードへ下記手順でkubeadm/kubelet/kubectlをインストール


###手順1: スワップ無効化
kubernetesは原則swapを無効にする必要がある。まずはスワップの有無を確認。下記の例では`/swap.img`というスワップファイルが有効

```
# swapon -s
Filename				Type		Size	Used	Priority
/swap.img                              	file    	1385468	0	-2
```

スワップファイル無効化

```
#swapoff /swap.img
```

再起動してもスワップが有効にならないように/etc/fstabのswap行をコメントアウト

```
#vi /etc/fstab
<省略>
#/swap.img      none    swap    sw      0       0
<省略>
```

###手順2: カーネル設定
ブリッジでのnetfilter有効化、フォワーディング有効化

```
#cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.conf.all.forwarding        = 1       
net.ipv6.conf.all.forwarding        = 1
EOF

#sysctl --system
```

###手順3: カーネルモジュールロード
br_netfilterとoverlayをロード

```
# modprobe br_netfilter
# modprobe overlay
# cat > /etc/modules-load.d/containerd.conf <<EOF
overlay
br_netfilter
EOF
```

###手順4: 必要なパッケージのインストール
必要なパッケージのインストール。最近のDistroはパケットフィルタリングに`nftables`を使うのが今風らしく、iptableコマンドも実態が`nftables`だったりするらしいが、calicoは`nftables`と互換性がないらしいのでレガシーなiptablesを使うように設定。

```
# apt install -y iptables arptables ebtables curl ca-certificates software-properties-common apt-transport-https

# update-alternatives --set iptables /usr/sbin/iptables-legacy
# update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
# update-alternatives --set arptables /usr/sbin/arptables-legacy
# update-alternatives --set ebtables /usr/sbin/ebtables-legacy
```

###手順5: containerd インストール

runtimeとしてのdockerが非推奨になったのでcontainerdをここではインストール

```
# curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
# add-apt-repository \
    "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
    $(lsb_release -cs) \
    stable"
# apt update && apt install -y containerd.io
# mkdir -p /etc/containerd
# containerd config default | sudo tee /etc/containerd/config.toml
```

Cgroupドライバーはcgroupfsとsystemdのに種類があり、1ノード内で統一する必要がある。ここではsystemdに合わせる。最初はまったけど`[plugins."io.containerd.grpc.v1.cri"]`の`systemd_cgroup`の設定変更は不要。無関係なので注意。 

```
# vi  /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
  ...
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
    SystemdCgroup = true #　＜この行を追加　

# systemctl restart containerd
```

###手順6: kubeadm/kubelet/kubectl インストール
focal(ubuntu 20.04)をつかっているので違和感あるが、下記のとおりxenial(ubuntu16.04)版で問題なし

```
# curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
# add-apt-repository \
    "deb [arch=amd64] https://apt.kubernetes.io/ \
    kubernetes-xenial \
    main"

# apt-get update
# apt-get install -y kubelet kubeadm kubectl
# apt-mark hold kubelet kubeadm kubectl
```

kubernetesのCgroupドライバーもsystemdに固定

```
# echo "KUBELET_EXTRA_ARGS=--cgroup-driver=systemd" > /etc/default/kubelet
# systemctl daemon-reload && systemctl restart kubelet
```

## master
### masterインストール
workerノードへログインし、kubeadm initを実行。
数分かかる。ここではCNIでCalicoを使うので、CalicoのデフォルトのPOD CIDRに合わせて192.168.0.0/16を設定。


```
# kubeadm init --pod-network-cidr=192.168.0.0/16
<省略>
Then you can join any number of worker nodes by running the following on each as root:

kubeadm join {masterのIP}:6443 --token xxxxxxxxxxxxxxx \
	--discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```
インストールが成功した場合に表示されるこのkubeadm以下の部分をコピペしてworker node用のVMで実行すればworkerが追加される
`kubeadm join {masterのIP}:6443 --token xxxxxxxxxxxxxxx \
	--discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`

kubectlを設定
まだCRIをインストールしていないのでSTATUSがNotReadyでもOK

```
# mkdir -p $HOME/.kube
# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# sudo chown $(id -u):$(id -g) $HOME/.kube/config
# kubectl get node
NAME     STATUS     ROLES                  AGE     VERSION
master   NotReady   control-plane,master   8m37s   v1.21.0
```

Calicoインストール。

```
# kubectl apply -f https://docs.projectcalico.org/manifests/tigera-operator.yaml
# kubectl apply -f https://docs.projectcalico.org/manifests/custom-resources.yaml

<数分待つ>

# kubectl get node
NAME     STATUS     ROLES                  AGE     VERSION
master   NotReady   control-plane,master   8m37s   v1.21.0
```

### workerインストール
workerノードへログイン。
先程Masterをインストールが成功したときに表示された`kubeadmin join`以下のコマンドをworkerで実行

```
# kubeadm join {masterのIP}:6443 --token xxxxxxxxxxxxxxx \
	--discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

### 確認
masterノードへログインしてworker nodeが追加されていることを確認

```
# kubectl get node
NAME     STATUS   ROLES                  AGE     VERSION
master   Ready    control-plane,master   14m     v1.21.0
node01   Ready    <none>                 6m21s   v1.21.0
```

calicoctlで確認

```
# curl -o calicoctl -O -L  "https://github.com/projectcalico/calicoctl/releases/download/v3.19.0/calicoctl" 
# chmod +x calicoctl
# mv calicoctl /usr/local/bin
# calicoctl get node 
NAME       
master     
worker01   
worker02 
```