AlmaLinux 9.4にKubernetes環境を構築する

前回、minikubeを使ったシングルノードのKubernetes環境を作成しました。

https://qiita.com/44dayo/items/3d131784fc44eb42d130

今回は実際にマスターノード(control plane/control node)とワーカーノードを用意し、Kubernetesクラスタ環境を構築したいと思います。
なお、ネットワークについて192.168.1.0/24で、GWとDNSは192.168.1.1になっています。

### ノード構成
| ROLE          | OS          | HOSTNAME | CPU   | MEMORY | IP            |
|---------------|-------------|---------|-------|--------|---------------|
| マスターノード  | AlmaLinux9.4 | mk8s     | 2Core | 4096MB | 192.168.1.80  |
| ワーカーノード1 | AlmaLinux9.4 | w1k8s    | 2Core | 2048MB | 192.168.1.81  |
| ワーカーノード2 | AlmaLinux9.4 | w2k8s    | 2Core | 2048MB | 192.168.1.82  |
| ワーカーノード3 | AlmaLinux9.4 | w3k8s    | 2Core | 2048MB | 192.168.1.83  |

### 入れたバージョン
- kubernetes:v1.31.1
- calico:v3.26.1

コマンドはなるべくコピペで行けるようにしてみました。


## 1. 事前準備

事前に全ノードで以下を実施しておきます。

1. **ホスト名設定**:
   AlmaLinuxインストール時に忘れた場合は以下コマンドで設定します。
   ```bash
   sudo hostnamectl set-hostname <ホスト名>
   ```
2. **IP設定**:
   AlmaLinuxインストール時に忘れた場合はnmtuiなどで設定をしておきます。
3. **swapメモリの無効化**:
   ```bash
   sudo swapoff -a
   sudo sed -i '/swap/d' /etc/fstab
   ```
4. **一般(管理)ユーザの作成**:
   wheelグループに追加した一般(管理)ユーザ(今回はyoyo)を作成します。
   ```bash
   useradd yoyo
   passwd yoyo
   usermod -aG wheel yoyo
   ```
   bash再読み込みor再ログインを忘れない。
5. **hostsファイルの更新**:
   全ノードのIPアドレスとホスト名を追加します。
   ```bash
   sudo tee -a /etc/hosts <<EOF
   192.168.1.80 mk8s
   192.168.1.81 w1k8s
   192.168.1.82 w2k8s
   192.168.1.83 w3k8s
   EOF
   ```

6. **socatのインストール**:
   ```bash
   sudo dnf install socat -y
   ```

## 2. 全ノード導入手順

### 2.1 カーネルモジュールとパラメータの設定

次に、カーネルモジュールとパラメータを設定します。

#### containerd.confの設定
```bash
sudo tee /etc/modules-load.d/containerd.conf <<EOF
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter
```

#### k8s.confの設定
```bash
sudo tee /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF

sudo sysctl --system
```

### 2.2 containerdのインストールと設定

containerdをインストールし、設定を行います。

```bash
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo dnf install containerd.io -y

containerd config default | sudo tee /etc/containerd/config.toml >/dev/null 2>&1
sudo sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml

sudo systemctl restart containerd
sudo systemctl enable containerd
sudo systemctl status containerd
```

### 2.3 Kubernetesのインストール

Kubernetesをインストールします。

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

#### Kubernetesのインストールとkubeletの設定・開始
```bash
sudo dnf install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
sudo systemctl enable --now kubelet
```

## 3. マスターノード設定

### 3.1 Firewall設定

マスターノードのFirewallを設定します。

```bash
sudo firewall-cmd --permanent --add-port={6443,2379,2380,10250,10251,10252,10257,10259,179}/tcp
sudo firewall-cmd --permanent --add-port=4789/udp
sudo firewall-cmd --reload
```

### 3.2 Kubernetesクラスタの初期化

Kubernetesクラスタを初期化します。

```bash
sudo kubeadm init --control-plane-endpoint=mk8s
```
ここで一番最後に以下のようなコマンドが表示されて、ワーカーノードでそれを実行しろと表示されるので、メモします。

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

kubeadm join 192.168.1.100:6443 --token abcdef.0123456789abcdef --discovery-token-ca-cert-hash sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef
```

### 3.3 kubeconfigの設定（一般ユーザで実行）

コマンドの結果的に前後しますが、一般ユーザで以下のコマンドを実行しろというメッセージが表示されるので、実行します。

```bash
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
```

## 4. ワーカーノード設定

以下はすべてのワーカーノードで実行します。

### 4.1 Firewall設定

ワーカーノードのFirewallを設定します。

```bash
sudo firewall-cmd --permanent --add-port={179,10250,30000-32767}/tcp
sudo firewall-cmd --permanent --add-port=4789/udp
sudo firewall-cmd --reload
```

### 4.2 Kubernetesクラスタへの参加

3.2の手順でメモっておいたコマンドを使ってワーカーノードをKubernetesクラスタに参加させます。

```bash
sudo kubeadm join mk8s:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>
```

:::note info
### Tokenの管理

マスタノードとワーカーノードの構築を同じタイミングでやる場合は特に不要ですが、(私のように)もし別日に分けて作業を行うときは、24時間でtokenの期限が切れてしまうため、せっかく以下の方法でTokenの確認と作成ができます。

```bash
kubeadm token list   # tokenの確認
kubeadm token create # tokenの作成
```
あるいは

```bash
kubeadm token create --print-join-command
#↓のように再作成されて表示される
kubeadm join 192.168.1.100:6443 --token abcdef.0123456789abcdef --discovery-token-ca-cert-hash sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef
```

:::

## 5. ネットワークプラグインのインストール

マスタノードでCalicoをネットワークプラグインとしてインストールします。CalicoはKubernetesクラスタ内のネットワーク通信を管理するためのプラグインで、Pod間の通信を可能にします。Calicoがないとクラスタ内のPod間通信ができず、Kubernetesの恩恵がありません。

```bash
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml
kubectl get pods -n kube-system
```

## 6. 動作確認

ここまでで構築自体はできているはずですが、念のためきちんと動作するか、簡単に動作確認を行います。

### 6.1 デプロイメントの作成

以下のコマンドでデプロイメントを作成し、動作確認を行います。

```bash
kubectl create deployment webap01 --image nginx --replicas 3
kubectl expose deployment webap01 --type NodePort --port 80
kubectl get deployment webap01
kubectl get pods -o wide
kubectl get svc webap01
```

出力例:
```bash
NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/webap01       3/3     3            3           1m

NAME                      READY   STATUS    RESTARTS   AGE    IP               NODE    NOMINATED NODE   READINESS GATES
webap01-8bf88b859-4tx6h   1/1     Running   0          100s   172.16.194.227   w1k8s   <none>           <none>
webap01-8bf88b859-ckwtp   1/1     Running   0          100s   172.16.73.39     w2k8s   <none>           <none>
webap01-8bf88b859-m6ng7   1/1     Running   0          100s   172.16.173.104   w3k8s   <none>           <none>

NAME      TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
webap01   NodePort    10.96.0.1     <none>        80:32066/TCP   1m
```

### 6.2 Webブラウザからのアクセス

以下のURLにアクセスして動作確認を行います。
- http://192.168.1.81:(任意のポート)
- http://192.168.1.82:(任意のポート)
- http://192.168.1.83:(任意のポート)
※任意のポートは今回は32066


すべてのURLで以下のように表示されたら成功です！やったね！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599902/29522d0b-e973-99dd-6c59-6707ce2d513a.png)

:::note warn
※今回の場合だと(大抵の場合は)すべてのノードに1つずつpodができるはずですが、場合によっては1ノードに2つのpodが作成される事があります。その場合はアクセスしても表示されないノードが発生する場合があります。
:::

:::note info
マスタノードから以下のように`curl`コマンドを実行してもOKです。

```bash
# curl http://ノードのIP:任意のポート
# curl http://192.168.1.83:32066
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

```


:::


以上です。