EC2(Amazon Linux 2023)にkubeadmでkubernetesクラスターを構築してみる(master node編)

[前回](https://qiita.com/Yoyo-kikuchi/items/b4abbea8e2156b443866)はコントロールプレーンが稼働する予定のmaster-nodeと各種アプリケーションが稼働する予定のworker-nodeを作成しました。
今回はmaster-nodeで**kubeadm**を実行してkubernetesクラスターを立ち上げていきたいと思います。

## 構築手順
1. containerdのインストール
1. runCの設定
1. CNIの設定
1. cgroupの設定
1. カーネルパラメータの設定(br_netfilterの有効化・iptablesの設定変更)
1. swapの無効化
1. kubelet／kubeadm／kubectlのインストール
1. tcコマンドのインストール
1. kubeadmでのkubernetesクラスターの作成
1. Flannelを使用したCNIのセットアップ


## Kubernetes環境構築（master node）
以下の作業はrootユーザーで作業するので`sudo su -`でrootユーザになって下さい。
`sudo`をコマンドの先頭に付けての各ユーザでの実行でも問題ないです。

### 1. containerdのインストール
containerdとは**コンテナイメージ管理などを行う高レベルランタイム**でkubernetesからの指令をrunCなどの低レベルランタイムに指示する為に必要になります。

```bash
$ CONTAINERD_VERSION=1.7.11
$ wget -P /usr/local/src https://github.com/containerd/containerd/releases/download/v${CONTAINERD_VERSION}/containerd-${CONTAINERD_VERSION}-linux-amd64.tar.gz
$ tar -C /usr/local -xf /usr/local/src/containerd-${CONTAINERD_VERSION}-linux-amd64.tar.gz
$ wget -P /etc/systemd/system https://raw.githubusercontent.com/containerd/containerd/main/containerd.service
$ systemctl daemon-reload
$ systemctl enable --now containerd
```

### 2. runCの設定

runCとは**コンテナを実行する低レベルランタイム**でcontainerdからの指令を受けコンテナの起動と動作を管理する為に必要となります。

```bash
$ RUNC_VERSION=1.1.10
$ wget -O /usr/local/sbin/runc https://github.com/opencontainers/runc/releases/download/v${RUNC_VERSION}/runc.amd64
$ chmod +x /usr/local/sbin/runc
```

### 3. CNI(Container Network Interface)の設定
**CNI**とは、コンテナランタイムがネットワークプラグイン(Flannelなど)と通信するためのインターフェースを提供します。

```bash
$ CNI_VERSION=1.4.0
$ wget -P /usr/local/src https://github.com/containernetworking/plugins/releases/download/v${CNI_VERSION}/cni-plugins-linux-amd64-v${CNI_VERSION}.tgz
$ mkdir -p /opt/cni/bin
$ tar -C /opt/cni/bin -xf /usr/local/src/cni-plugins-linux-amd64-v${CNI_VERSION}.tgz
```

### 4. cgroupの設定
**cgroup**とはプロセスをグループ化し、それぞれのグループに対してリソース使用量を制限することができるものです。
たとえば、あるコンテナプロセスがホストのリソースを食い潰し「サーバーダウン」みたいなことが起きないように管理してくれます。

```bash
$ mkdir /etc/containerd
$ containerd config default | sudo tee /etc/containerd/config.toml > /dev/null
$ cp -p /etc/containerd/config.toml /etc/containerd/config.toml_`date +%Y%m%d`
$ sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
$ diff /etc/containerd/config.toml /etc/containerd/config.toml_`date +%Y%m%d`
$ systemctl restart containerd
```

### 5. カーネルパラメータの設定(br_netfilterの有効化・iptablesの設定変更)
各種カーネルモジュールの追加で、ファイルシステムの設定とネットワークブリッジ経由のトラフィックにiptablesの設定を適用されるようにします。
またiptablesにもネットワークブリッジを通過するトラフィックを処理するように設定します。

```bash
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

modprobe overlay
modprobe br_netfilter

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF

sysctl --system
```

### 6. swapの無効化
[公式ドキュメント](https://v1-25.docs.kubernetes.io/ja/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#%E5%A7%8B%E3%82%81%E3%82%8B%E5%89%8D%E3%81%AB)に以下のように記載されている為OFFにします
> kubeletが正常に動作するためにはswapは必ずオフでなければなりません。

```bash
# スワップの使用状況をデバイスごとに表示する
$ swapon -s
# スワップを無効にする
$ swapoff -a
```

### 7. kubelet／kubeadm／kubectlのインストール

```bash
$ cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.27/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.27/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
EOF

$ dnf upgrade -y
$ dnf install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
$ systemctl enable --now kubelet
```

### 8. tcコマンドのインストール

```bash
dnf provides tc
dnf install iproute-tc
```

### 9. kubeadmでのkubernetesクラスターの作成

```bash
$ kubeadm init --pod-network-cidr=10.244.0.0/16
```

処理が正常終了すると以下のような情報が表示され、worker-nodeをクラスターに参加させる場合に必要なので必ず**メモ**しておいて下さい。

```bash
Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

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/

Then you can join any number of worker nodes by running the following on each as root:

# ここから下の部分をメモしておく。
kubeadm join 10.0.0.68:6443 --token fs17bk.dvd2qzb2ojz72z3d \
	--discovery-token-ca-cert-hash sha256:05540afa85c20157edcf334471312a17f315e4eae860b3102252ba27735c5e4c
```

#### kube configの作成
クラスター操作をroot以外で実行したいのec2-userに切り替えて実施します。

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

### 10. Flannelを使用したCNのセットアップ
**Flannel**とは、CNIプラグインの一つで**オーバレイネットワークアプローチ**が特徴的で、kubernetesクラスターの論理ネットワークを構成するのに必要。

※ ここからkubernetesとのやり取りになるので**ec2-user**で実行していきます。

```bash
$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
```

#### 構築後の確認
正常にクラスターが作成され動作しているかを確認します。

```bash
$ kubectl get nodes
NAME          STATUS   ROLES           AGE   VERSION
master-node   Ready    control-plane   67s   v1.27.8
```

```bash
$ kubectl get pods -A
NAMESPACE      NAME                                  READY   STATUS    RESTARTS   AGE
kube-flannel   kube-flannel-ds-p5hdv                 1/1     Running   0          17m
kube-system    coredns-5d78c9869d-ld2s8              1/1     Running   0          17m
kube-system    coredns-5d78c9869d-lpvkb              1/1     Running   0          17m
kube-system    etcd-master-node                      1/1     Running   0          18m
kube-system    kube-apiserver-master-node            1/1     Running   0          17m
kube-system    kube-controller-manager-master-node   1/1     Running   0          18m
kube-system    kube-proxy-j75p9                      1/1     Running   0          17m
kube-system    kube-scheduler-master-node            1/1     Running   0          17m
```

## まとめ
今回はec2(Amazon Linux 2023)にkubernetesクラスターをkubeadmで構築してみました。
各種ミドルウエアの用途を調べながらで大変でしたが、kubernetesの仕組みへの理解が深まり良い勉強になりました。
次回はworker-node用として作成したEC2を設定し今回作成したmaster-nodeに紐付けてみたいと思います。

## 前回記事
https://qiita.com/Yoyo-kikuchi/items/b4abbea8e2156b443866

## 参考リンク
https://qiita.com/1429takahiro/items/642dfbcf8fc90290329f#2-%E5%89%8D%E6%8F%90%E6%83%85%E5%A0%B1

https://qiita.com/rk05231977/items/c545fe848a23a8030a2a

https://v1-25.docs.kubernetes.io/ja/docs/setup/production-environment/tools/kubeadm/install-kubeadm/