ぶていのログでぶログ

思い出したが吉日

kubeadmを使ってUbuntu22.04にkubernetes 1.27.4をデプロイする

📝自分用のメモ

コンテナランタイムを選択する

kubeadmでは以下のコンテナランタイムを選択することができる。

  • Docker
  • containerd
  • cri-o

Dockerが手軽そうだが、Docker内蔵のcontainerdをkubeadmが優先的に選択してしまい、かつ、Docker提供のcontainerdではCRIが無効になっていたり*1CNIがインストールされていなかったりするのでものすごくハマる。 おすすめはcri-oで、手順のとおりにインストールすれば全くはまらないので初kubeadmならおすすめ。

github.com

おすすめと書きながら今回はブログのネタになると思ったのでcontainerdを選択した。

containerdのインストール

「containerd docker install」とかで検索するとDocker社提供のリポジトリからパッケージをインストールしろっと出てくるが、これは罠である。 前述した通り、Docker内蔵のcontainerdにはkubeadmで使う上では問題がありおすすめしない。 containerdの公式リポジトリにインストール手順が載っているのこれを参考にするとよい。

github.com

以下は必要なコマンドのみ抜粋したもの。

CONTAINERD_VERSION=1.7.3
RUNC_VERSION=1.1.8
CNI_VERSION=1.3.0

sudo mkdir -p /usr/local/src

sudo wget -P /usr/local/src https://github.com/containerd/containerd/releases/download/v${CONTAINERD_VERSION}/containerd-${CONTAINERD_VERSION}-linux-amd64.tar.gz
sudo tar -C /usr/local -xf /usr/local/src/containerd-${CONTAINERD_VERSION}-linux-amd64.tar.gz

sudo wget -P /etc/systemd/system https://raw.githubusercontent.com/containerd/containerd/main/containerd.service
sudo systemctl daemon-reload
sudo systemctl enable --now containerd

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

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

次にsystemdバックエンドなcgroupを有効にする(kubeadmではこれがデフォルトになっているので)。

sudo mkdir /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml > /dev/null
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl restart containerd

カーネルモジュールの読み込み

以下を参考にコンテナからのネットワークアクセスを許可するためのカーネルパラメータを設定する。

kubernetes.io

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

swapの無効化

swapの無効化がkubeletでは奨励されているので変更する。

swapon -s
sudo swapoff -a
sudo sed -i '/swap/d' /etc/fstab

kubeadmのインストール

ここまでで事前準備ができたのでkubeadmをインストールする。

kubernetes.io

sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl

curl -fsSL https://dl.k8s.io/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg

echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

kubeletのデプロイ

kubeletをデプロイする。 デフォルトでは何もオプションを指定する必要がないが、今回はpodに使用されるネットワークレンジを172.16.0.0/16に変えたいので--pod-network-ciderを指定する*2

kubeadm init --pod-network-cidr 172.16.0.0/16

コマンドを実行しうまくデプロイされると以下のように表示される。

Your Kubernetes control-plane has initialized successfully!

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

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 XXXXX:6443 --token YYYYYY \
        --discovery-token-ca-cert-hash sha256:ZZZZZ

引き続きCNIのセットアップにkubectlを使う必要があるので、メッセージに従いkubeconfigを設定しておく。

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

kubeadm joinコマンドをメモしておくとワーカーノードを追加するときに利用できるが、kubectl tokenコマンドで再取得できるのでスルーしてもよい。

Calicoを使用したCNIのセットアップ

kubeletをデプロイしただけでばクラスタとしては動作せずCNIをセットアップしなければならない。 CNIとして選択できるミドルウェアはいくつか存在するがここではCalicoを選択する。 Calicoの手順に従いまずはOperatorをインストールする。

kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/tigera-operator.yaml

次にはカスタムリソース定義のマニフェストをダウンロードする。 ダウンロードしたマニフェストをそのまま使うことができるが、今回は前述の手順でpodネットワークを変更しているのでその変更を適用し、kubectlを使いマニフェストを読み込ませる。

curl https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/custom-resources.yaml -O
sed -i 's,192.168.0.0/16,172.16.0.0/16,g' custom-resources.yaml
kubectl apply -f custom-resources.yaml

calico-systemネームスペースのpodがすべてRunningになればセットアップは完了している。

watch -n1 kubectl get pods -n calico-system

ワーカーノードの追加

ワーカーノードの追加手順は、コントロールプレーンの追加とほとんど同じである。 違いはkubeadm initをするかkubeadm joinするかである。

まずはワーカーノードにkubeadmをインストールする手順まで行う。 kubeadmのインストールが終わったら次にワーカーノードをコントロールプレーンにジョインさせる。 ジョインするためのコマンドはコントロールプレーンでkubeadm initを実行した後に表示されていたので、それを貼り付ければよい。 仮にメモしておかなくても以下のコマンドで再度発行することができる。

$ sudo kubeadm token create --print-join-command
kubeadm join XXXXX:6443 --token YYYYY --discovery-token-ca-cert-hash sha256:ZZZZZ

kubeadm join~の部分をコピーしてワーカーノードに張り付ける。

kubeadm join XXXXX:6443 --token YYYYY --discovery-token-ca-cert-hash sha256:ZZZZZ

正常に完了すると以下のように表示される。

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

メッセージにあるとおりコントロールプレーンでkubectl get nodesを実行するとワーカーノードが追加されているのがわかる。 追加した直後はNotReadyだが、少し待つとReadyになると思われる。 なお、CNIのセットアップはコントロールプレーンで行っているので、ワーカーノードが追加されたタイミングで自動でワーカーノードにもCNIがセットアップされる。

$ kubectl get nodes
NAME         STATUS     ROLES           AGE   VERSION
k8s-master   Ready      control-plane   19m   v1.27.4
k8s-worker   NotReady   <none>          8s    v1.27.4

# ↓数分後
$ kubectl get nodes
NAME         STATUS   ROLES           AGE    VERSION
k8s-master   Ready    control-plane   22m    v1.27.4
k8s-worker   Ready    <none>          3m3s   v1.27.4

トラブルシューティング

kubeadm initがこけた

メッセージが出ると思うのでそれに従って対応すれば困ることはないと思う。 それでも直らない場合は公式ドキュメントのトラブルシューティングガイドを読むと良い。

kubernetes.io

CNIの初期化が失敗するなど

とりあえず、kubeletのログを見る。

sudo journalctl -fu kubelet

こけているk8sリソースを見つけてログを見てみる。

kubectl get all -A

calicoのコントローラのログを見る。

kubectl -n calico-system logs -f deployment.apps/calico-kube-controllers

よくわからなればkubeadm resetしてみる。 それでも直らなかった再起動…。

クラスタをリセットする

セットアップをやり直したいとかうまく動かないというときに実行する。

sudo kubeadm reset
sudo iptables -F
sudo iptables -F -t nat
sudo iptables -F -t mangle
sudo iptables -X
sudo rm -r /etc/cni/net.d

ワーカーノードの場合は以下のコマンドをコントロールプレーンで実行する。

kubectl delete node <ワーカーノード名>

参考

*1:設定ファイルを変更すれば有効化できる

*2:指定しない場合のデフォルトは192.168.0.0/16