KubeadmでオンプレミスのKubernetesクラスタを構築する【v1.28.2】

こんにちは。先日Kubernetesに入門したので、登竜門としてオンプレミスのクラスタを構築してみました。

今回構築したKubernetesのバージョンは**v1.28.2**です。

## 環境

今回Kubernetesを動かす環境として、Proxmox上にVMを3台用意しました。

コンテナランタイムにはContainerd、CNIにはCiliumを採用しました。

Kubernetesが属するネットワークアドレスは**10.10.10.0/24**です。

| # | value |
|:-|:-|
| OS | Ubuntu 22.04.3 LTS |
| CPU | 4 Core |
| RAM | 8 GB |
| HDD | 32 GB |
| Container Runtime | Containerd |
| CNI | Cilium |

| Hostname | IP Address | Role |
|:-:|:-|:-|
| kcp-1 | 10.10.10.240 | Control Plane |
| kwk-1 | 10.10.10.241 | Worker Node |
| kwk-2 | 10.10.10.242 | Worker Node |


## インストールスクリプトの紹介

自分の環境用ではありますが、自動インストール用にスクリプトを書きました。

セットアップについてはAnsibleなどの利用をオススメします。

<details><summary>自動インストールスクリプト</summary>

https://gist.github.com/rokuosan/cc9a243fb7a2f43ff6bab40b9fc06f98

```bash
#!/bin/bash

# Get Latest release
RELEASE="$(curl -sSL https://dl.k8s.io/release/stable.txt)"
echo "Download Kubernetes tools [Release $RELEASE]"


# Forwarding IPv4 and letting iptables see bridged traffic 
# https://kubernetes.io/docs/setup/production-environment/container-runtimes/#forwarding-ipv4-and-letting-iptables-see-bridged-traffic
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

# sysctl params required by setup, params persist across reboots
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

# Apply sysctl params without reboot
sudo sysctl --system

# Update
sudo apt-get update -y
sudo install -m 0755 -d /etc/apt/keyrings

# Install requirements
sudo apt install -y \
    ca-certificates \
    curl \
    gnupg \
    lsb-release \
    apt-transport-https \
    nfs-common

# Kubernetes Repository
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

# Docker (Containerd) Repository
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Update
sudo apt-get update

# Install Kubernetes and lock the version
sudo apt-get install -y kubectl kubelet kubeadm
sudo apt-mark hold kubelet kubeadm kubectl

# Install containerd
sudo apt-get install containerd.io -y
sudo systemctl start containerd
sudo systemctl enable containerd
sudo mv /etc/containerd/config.toml /etc/containerd/config.toml.orig
containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml

# Install CNI Plugin
CNI_PLUGINS_VERSION="v1.3.0"
ARCH="amd64"
DEST="/opt/cni/bin"
sudo mkdir -p "$DEST"
curl -L "https://github.com/containernetworking/plugins/releases/download/${CNI_PLUGINS_VERSION}/cni-plugins-linux-${ARCH}-${CNI_PLUGINS_VERSION}.tgz" | sudo tar -C "$DEST" -xz

# Install nerdctl
wget https://github.com/containerd/nerdctl/releases/download/v1.6.0/nerdctl-1.6.0-linux-amd64.tar.gz
sudo tar Cxzvf /usr/local/bin nerdctl-1.6.0-linux-amd64.tar.gz

echo "Finished."
```
</details>

## コンテナランタイムのインストール

以下のドキュメントを参考に進めました。

https://kubernetes.io/docs/setup/production-environment/container-runtimes/


### iptablesでのブリッジ設定

以下のコマンドを順番に実行します。

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

$ sudo modprobe overlay
$ sudo 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

$ sudo sysctl --system
```

### APT経由でのContainerdのインストール

前提パッケージをインストールします。

```bash
$ sudo apt-get update -y
$ sudo install -m 0755 -d /etc/apt/keyrings
$ sudo apt install -y \
    ca-certificates \
    curl \
    gnupg \
    lsb-release \
    apt-transport-https \
    nfs-common
```

ContainerdのインストールにはDockerインストールで利用するリポジトリを利用します。

```bash
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$ echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```

Containerdをインストールして、Systemdで自動起動するようにします。

```bash
$ sudo apt-get update
$ sudo apt-get install containerd.io -y
$ sudo systemctl start containerd
$ ksudo systemctl enable containerd
```

Cgroup driverをSystemdに変更します。

> 参考: cgroup drivers
> https://kubernetes.io/docs/setup/production-environment/container-runtimes/#cgroup-drivers

```bash
$ sudo mv /etc/containerd/config.toml /etc/containerd/config.toml.orig
$ containerd config default | sudo tee /etc/containerd/config.toml
$ sudo sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml
```

nerdctlもついでにインストールしておきましょう。

```bash
$ wget https://github.com/containerd/nerdctl/releases/download/v1.6.0/nerdctl-1.6.0-linux-amd64.tar.gz
$ sudo tar Cxzvf /usr/local/bin nerdctl-1.6.0-linux-amd64.tar.gz
```

## Kubectl, Kubelet, Kubeadmのインストール

Kubernetesクラスタを構築するために必要なツールをインストールします。

- [Installing kubeadm | Kubernetes](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#installing-kubeadm-kubelet-and-kubectl)

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#installing-kubeadm-kubelet-and-kubectl

まずはリポジトリを追加します。

```bash
$ curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
$ echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
$ sudo apt-get update
```

ツールをインストールして、バージョンを肯定します。

```bash
$ sudo apt-get install -y kubectl kubelet kubeadm
$ sudo apt-mark hold kubelet kubeadm kubectl
```

## CNIプラグインのインストール

CNIプラグインのインストールをします。

今回ダウンロードしたバージョンはv1.3.0です。

```bash
$ sudo mkdir -p /opt/cni/bin
$ curl -L "https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz" | sudo tar -C /opt/cni/bin -xz
```

## クラスタの構築

ここまでの工程をすべてのノードで行いましょう。

### コントロールプレーン

コントロールプレーンでクラスタを起動します。

``--control-plane-endpoint``にはコントロールプレーンのIPアドレスを渡します。

```bash
$ sudo kubeadm init --control-plane-endpoint=10.10.10.240
```

クラスタのコンフィグファイルをコピーします。

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

### ワーカーノード

ワーカーノードではクラスタに参加するために、以下のコマンドを実行します。

このコマンドは、コントロールプレーンでクラスタを立ち上げた際に表示されたコマンドです。

IPアドレス、トークン、ハッシュ値は各自変更してください。

```bash
$ sudo kubeadm join 10.10.10.240:6443 --token lu4wng.331v1crmk77ouua2 \
        --discovery-token-ca-cert-hash sha256:7070922f6dfb288bca91e364e197a06cd641e4cf57b181188624988b3f0e3e43
```

## Ciliumのインストール

Kubernetesでは一部の接続をCNIに委譲しています。そのため、クラスタを構築した直後ではPod間およびNode間の接続を行うことができません。

そこで今回はCiliumというCNIをインストールしました。

[Cilium Quick Installation — Cilium 1.14.2 documentation](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/#cilium-quick-installation)


https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/#cilium-quick-installation


### Cilium CLIのインストール

以下のコマンドを実行します。

```bash
$ CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
$ CLI_ARCH=amd64
$ curl -L https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gz
$ sudo tar xzvfC cilium-linux-${CLI_ARCH}.tar.gz /usr/local/bin
$ rm cilium-linux-${CLI_ARCH}.tar.gz
```

### Cilium CLIからCiliumをインストールする

以下のコマンドを実行します。

```bash
$ cilium install --version 1.14.2
```

### ステータスチェック

Ciliumが正しくインストールされたか検証するために、以下のコマンドを実行します。

先程のインストールコマンド実行後に、数分おいてから実行してください。

```bash
$ cilium status --wait
    /¯¯\
 /¯¯\__/¯¯\    Cilium:             OK
 \__/¯¯\__/    Operator:           OK
 /¯¯\__/¯¯\    Envoy DaemonSet:    disabled (using embedded mode)
 \__/¯¯\__/    Hubble Relay:       OK
    \__/       ClusterMesh:        disabled
```

### Hubble UIを有効化する

CiliumにはHubbleと呼ばれる通信を可視化するコンポーネントが存在します。

このHubbleのWebUIを有効化しておきます。

```bash
$ cilium hubble enable --ui
```

## 環境構築終了

これでクラスタの構築とCNIのインストールが終了しました。

検証もかねてKubernetes上でUbuntuを起動してみましょう。

```bash
$ kubectl run -it ubuntu --image=ubuntu bash

If you don't see a command prompt, try pressing enter.
root@ubuntu:/#
```

アタッチされたあとにcurlをインストールして、Googleにアクセスしてみましょう。

```bash
root@ubuntu:/# apt update -y && apt install -y curl
root@ubuntu:/# curl google.com
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>
```

動いてそうですね。

## おわりに

はじめてのKubernetesで困るところも多かったですが、なんとかインストールすることができました。

晴れて僕もKubernetes入門できました。これから精進していきます。

---

### 参考文献

- [Creating a cluster with kubeadm | Kubernetes](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/)
- [Cilium Quick Installation — Cilium 1.14.2 documentation](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/#k8s-install-quick)
- [Ubuntu 22.04 に Containerd コンテナ ランタイムをインストールする方法](https://ja.linux-console.net/?p=3509#gsc.tab=0)
- [Ubuntu 22.04 に Kubernetes をインストールして自宅クラウド | Rabbit Note](https://rabbit-note.com/2022/08/09/build-kubernetes-home-cluster/)
- [自宅Kubernetesクラスタはじめました – えびサブレ](https://blog.ebiiim.com/posts/homelab-kubernetes/)
- [CNIのCiliumについて調べてみた - フラミナル](https://blog.framinal.life/entry/2021/02/20/222728)
- [kubeadm+containerd+ciliumを用いてk8s構築し、hubbleの動作確認するまで試した - Qiita](https://qiita.com/fruscianteee/items/2b130eaa8418b183d515)