【Kubernetes】Ubuntu OS 22.04で高可用性クラスタを作りたい
追記
はじめに
今回はcontrol-planeを3台とした高可用性なクラスタを作りたい時にまとまった資料がなかったので備忘録的な感じで作りました。またこの記事のこだわりとして、右上のコピーのところでコピーしてもらえばそのまま通常ユーザーで実行できるように記載しているのでいい感じに活用してください。ただし一部はお使いの環境に合わせて変更する必要がある場所もございます。
構成
今回はRaspiを12台使っています。そしてこのRaspiはModel4Bの8GBモデルを使用しています。
また、OSはUbuntu OS 22.04.2 LTSを使用しています。一方で、上流のファイヤーウォールやスイッチのほうはあまり気にしないでもらって構いません。
ネットワーク図

IPアドレス割り当て
| 機器名 | IPv4 | 機器名 | IPv4 |
|---|---|---|---|
| node1 | 192.18.100.1 | node2 | 192.168.100.2 |
| node3 | 192.168.100.3 | node4 | 192.168.100.4 |
| node5 | 192.168.100.5 | node6 | 192.168.100.6 |
| node7 | 192.168.100,7 | node8 | 192.168.100.8 |
| node9 | 192.168.100.9 | node10 | 192.168.100.10 |
| node11 | 192.168.100.11 | node12 | 192.168.100.12 |
使用技術
今回は主に以下の3つを使って高可用性クラスタを作っていきます。
kubeadm
kubeadmではKubernetesを高速に作成する方法としてkubeadm initとkubeadm joinというコマンドを使えるようになります。また、セキュアに立てれたりといいことづくしということも言えるそうです。詳しくは、以下のサイトがびっくりするくらいわかりやすく載っているのでどうぞ。
cilium
ciliumはよく聞くCNIのうちの一つで、他に代表的なものでCalicoやflannelがあります。このciliumはeBPFというLinux kernelの仕組みを使ってNode間の通信を担っているらしい。また、カーネルレベルでNW制御を行うことで従来のkube-proxyといったユーザー空間で行う方法と異なり、高速であるみたい。
kube-vip
kube-vipはcontrol-planeをいい感じにロードバランシングするためのものです。また、公式ドキュメントでは
kube-vipは、外部のハードウェアやソフトウェアに依存することなく、コントロールプレーン(可用性の高いクラスタ構築用)とロードバランサータイプのKubernetesサービスの両方に仮想IPとロードバランサをKubernetesクラスタに提供する。
というふうに記載されていました。
今回は、このkube-vipを使用していますが、構築手順としてはStatic PodとDaemon Setの2つがあり今回はStatic Podとしてkube-vipをデプロイして使うことにしました。2つの違いとして、前者は構築が楽ですが、Kubernetesクラスタがkube-vipを管理しているわけではなくあくまで静的にデプロイしていることになります。一方で後者はKubernetesクラスタが自動で全control-planeに対してkube-vipをデプロイ・管理を行ってくれます。そのため、本番環境で運用する際はDaemon Setを使用して運用することが勧められています。
注意事項
kubernetesを立てる際に事前に以下の項目をよく確認した上で立ててください。
- ファイヤーウォールでポートを制限している偉い人は、ポートとプロトコルにアクセスし、それぞれのノードで必要なポートを開放するようにしてください。
- MACアドレスとproduct_uuidが全てのノードで独立している必要があり、以下のところで確認してください。
- ネットワークインターフェースのMACアドレスはip linkもしくはifconfig -aコマンドで取得できます。
- product_uuidはsudo cat /sys/class/dmi/id/product_uuidコマンドで確認できます。
- その他スペック等は公式サイトを参考に用意してください。
構築手順
これから、kubernetesを動かしていくために必要な手順を載せます。左上にAll-nodeとあれば、全ノードで実施していただければと思います。それ以外は、node1のみの実行であればnode1と記載しています。
初設定
- 恒例のアップデート
sudo apt update && sudo apt upgrade -y
- IPv4のフォワーディングを有効化する設定
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
- スワップをオフにする
一時的にスワップをオフにする場合は以下のコマンドでオフにすることができます。
sudo swapoff -a
しかし、上記のコマンドを実行するだけだと再起動後はまた使用する設定なっていて、kubernetesがReadyにならない原因になりますので、fstabからスワップは使用しないようにコメントアウトを行います。
sudo vim /etc/fstab
- /swap.img none swap sw 0 0\
+ #/swap.img none swap sw 0 0
- host名を解決できるようにする
IPアドレスとホスト名はお使いの環境に合わせて設定してください。
cat <<EOF | sudo tee -a /etc/hosts
192.168.100.1 k8s1
192.168.100.2 k8s2
192.168.100.3 k8s3
192.168.100.4 k8s4
192.168.100.5 k8s5
192.168.100.6 k8s6
192.168.100.7 k8s7
192.168.100.8 k8s8
192.168.100.9 k8s9
192.168.100.10 k8s10
192.168.100.11 k8s11
192.168.100.12 k8s12
EOF
コンテナランタイムのインストール
今回は、コンテナランタイムとしてcontainerdを使います。そのためにまずはcontainerdをダウンロードするところから始めます。
sudo apt install -y containerd
次に、containerdをkubernetesで使うための設定をこれからしていきます。
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml
sudo sed -i 's#sandbox_image = "registry.k8s.io/pause:3.6"#sandbox_image = "registry.k8s.io/pause:3.9"#g' /etc/containerd/config.toml
sudo systemctl restart containerd && systemctl status containerd
最後にcontainerdがrunningしていることを確認して次のステップへ進んでください。また、これらの設定はUbuntu 22.04での場合は必須となるみたいです。今回は以下の記事がとても参考になりました。
どうやらUbuntu 22.04ではUbuntu 20.04と比べて、Cgroupのバージョンバージョンがv1からv2に変更になっているため、このような事態が起きているらしいことがわかった。
kubeadmはv1.22以降、何も指定しなければデフォルトでcgroupドライバーとしてsystemd(≒v2?)を使うようになっているようなのでUbuntu 22.04でも問題ないが、どうやらUbuntuの公式リポジトリからインストールしたcontainerdが標準でcgroupドライバーとしてcgroupfs(≒v1?)を使うため、上手く動作しないようだった。
kubeadm,kubectl,kubeletのインストール
次に、kubeadmとkubectl、kubeletといったkubernetesを動かすために必要なパッケージを全ノードで実行してインストールします。
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl gpg
#公開鍵ダウンロード
sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
#kubernetesのリポジトリをaptリポジトリに追加
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
#aptのパッケージを更新後にkubeadm、kubectl、kubeletをインストール
sudo apt update
sudo apt install -y kubelet kubeadm kubectl
# 勝手に更新されないように固定化
sudo apt-mark hold kubeadm kubectl kubelet
kube-vipの導入
ここでは、kube-vipを導入していきます。この章ではrootユーザーに切り替えて作業することをお勧めします。
# ロードバランサーのIPアドレスを指定(セグメントが同じであれば好きなものに)
export VIP=192.168.100.98
# ロードバランサーのトラフィックを流すインターフェイスの指定
export INTERFACE=eth1
# kube-vipの最新バージョンの取得
KVVERSION=$(curl -sL https://api.github.com/repos/kube-vip/kube-vip/releases | jq -r ".[0].name")
# kube-vip用のmanifestの作成
alias kube-vip="ctr image pull ghcr.io/kube-vip/kube-vip:$KVVERSION; ctr run --rm --net-host ghcr.io/kube-vip/kube-vip:$KVVERSION vip /kube-vip"
kube-vip manifest pod \
--interface $INTERFACE \
--address $VIP \
--controlplane \
--services \
--arp \
--leaderElection | tee /etc/kubernetes/manifests/kube-vip.yaml
kubeadmの実行
ここまでの設定を行えたらようやくkubernetesのコントロールプレーンの設定にいけます。
sudo kubeadm init \
--control-plane-endpoint "192.168.100.98:6443" \
--pod-network-cidr=10.1.0.0/16 \
--upload-certs
この時、contro-plane-endpointで指定するのは先ほどkube-vipのところで導入で指定したロードバランサーのIPアドレスを指定してください。 また、ポート番号は6443で構いません。一方で、pod-netwrok-cidrも自由に割り当ててもらって構いません。
次に、kubernetesを操作するために必要な設定をします。以下のコマンドを通常ユーザーで実行してください。
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -gh) $HOME/.kube/config
最後にkubeadm initを実行した際に最後のほうにkubeadm joinというのが2つ出てくるはずです。上の方は引数オプションでcontrol-planeみたいなのがあるので、コントロールプレーンとして参加させたいnodeで実行するべきコマンドです。一方で、下の特に何もない方はWorkerノードとして参加させたい場合に使います。
sudo kubeadm join <IPアドレス:ポート> --token <TOKEN> \
--discovery-token-ca-cert-hash <token-hash> \
--control-plane --certificate-key <certificate-key>
sudo kubeadm join <IPアドレス:ポート> --token <TOKEN> \
--discovery-token-ca-cert-hash <token-hash> \
これをそれぞれのノードで実行させてしばらく待てばkubernetesに参加することができます。
Ciliumのインストール
CNIプラグインであるCiliumのインストールを行っていきます。以下に記述している通り、node1のみで実行してください。これを行うことでkubectl get nodesした時にReadyになります。
# ciliumのコマンドをダウンロード
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
CLI_ARCH=amd64
if [ "$(uname -m)" = "aarch64" ]; then CLI_ARCH=arm64; fi
curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}
sha256sum --check cilium-linux-${CLI_ARCH}.tar.gz.sha256sum
sudo tar xzvfC cilium-linux-${CLI_ARCH}.tar.gz /usr/local/bin
rm cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}
# インストール
cilium install --version 1.14.1
Nodeが参加できているかの確認
ここまでの設定を問題なく行えれれば、以下のコマンドを実行したときにReadyと記されたノードが12個(今回の構築図より)表示されるはずです。
kubectl get nodes
Readyになっていたら大成功です!!おめでとうございます。これでkubernetesでいろいろ遊べます。
さいごに
今回はとあるイベントでkubernetesが必要だったので、リソースがかなりあることから高可用性クラスタを作ってみました。勉強目的でも実際に運用する方でも少しでもご参考になったらうれしいです。また、これからkubernetesを弄る上で便利なものだったり、kubernetesに関連することに関しても投稿できればと思いますのでその時はぜひまた見ていただければと思います。
参考文献
今回の記事を作成するうえで参考になったサイトです。ありがとうございました。
Discussion