/

不停機替換 Kubernetes CRI

問題

今天嘗試將 CRI 從預設的 dockershim 替換至 CRI-O,網路上的教學都是教你更換完畢之後使用 kubeadm 重新起一個 Cluster。但我的情境需要對現有的 Cluster 做替換,於是自己研究了一下如何不停機替換 CRI。

替換 CRI

首先將你需要替換的節點先設 drain

kubectl drain worker-node-1 --ignore-daemonsets

之後進入節點,將原本的 CRI dockershim 關閉

systemctl stop docker

我打算替換成 CRI-O,所以請先確定你想要替換的 CRI 已經安裝完畢,並且已經啟動:

systemctl status crio

1
2
3
4
5
6
7
8
9
● crio.service - Container Runtime Interface for OCI (CRI-O)
Loaded: loaded (/usr/lib/systemd/system/crio.service; enabled; vendor preset: disabled)
Active: active (running) since 六 2021-04-17 02:25:09 EDT; 15min ago
Docs: https://github.com/cri-o/cri-o
Main PID: 22001 (crio)
Tasks: 21
Memory: 1.1G
CGroup: /system.slice/crio.service
└─22001 /usr/bin/crio

接著照著網路上的教學,修改 /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf

並且增加

1
Environment="KUBELET_EXTRA_ARGS=--feature-gates='AllAlpha=false,RunAsGroup=true' --container-runtime=remote --cgroup-driver=systemd --container-runtime-endpoint='unix:///var/run/crio/crio.sock' --runtime-request-timeout=5m"

但是重啟 kubelet 之後會發現毫無作用(用 systemctl status kubelet 可以檢查啟動參數)

為何會毫無作用,是因為該檔案是 kubeadm 啟動時讀取的,但是我打算不停機所以不考慮使用 kubeadm 重啟,我打算在每一個節點上重啟 kubelet 來替換,所以需要針對 kubelet 來設定啟動參數。

於是我在該檔案找到了 EnvironmentFile 參數,並且值為 /etc/sysconfig/kubelet

於是我在 /etc/sysconfig/kubelet 加入了

1
KUBELET_EXTRA_ARGS=--feature-gates='AllAlpha=false,RunAsGroup=true' --container-runtime=remote --cgroup-driver=systemd --container-runtime-endpoint='unix:///var/run/crio/crio.sock' --runtime-request-timeout=5m

之後重啟 kubelet

systemctl daemon-reload
systemctl restart kubelet

可以看到啟動參數已經吃進去了

1
2
3
4
5
6
7
8
9
10
11
● kubelet.service - kubelet: The Kubernetes Node Agent
Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled)
Drop-In: /usr/lib/systemd/system/kubelet.service.d
└─10-kubeadm.conf
Active: active (running) since 六 2021-04-17 02:25:09 EDT; 22min ago
Docs: https://kubernetes.io/docs/
Main PID: 22114 (kubelet)
Tasks: 16
Memory: 51.2M
CGroup: /system.slice/kubelet.service
└─22114 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.2 --feature-gates=AllAlpha=false,RunAsGroup=true --container-runtime=remote --cgroup-driver=systemd --container-runtime-endpoint=unix:///var/run/crio/crio.sock --runtime-request-timeout=5m

使用

kubectl get node -o wide

也可以發現 CRI 已經更換

重新讓該節點可以被使用

kubectl uncordon worker-node-1

注意事項

  1. 替換 Control Plane 節點時請一定要把原本的 CRI 關閉,否則系統元件會佔用你節點上的 Port,導致使用新的 CRI 無法順利將系統元件跑起來!

  2. 部署完畢後 coredns 報錯

1
2
container_linux.go:349: starting container process caused "error adding seccomp rule for syscall socket: requested action matches default action of filter"               │   Warning  FailedCreatePodSandBox  36m  kubelet, worker-node-2  Failed to create pod sandbox: rpc error: code = Unknown desc = container create failed: time="2021-04-17
│ T02:23:10-04:00" level=error msg="container_linux.go:349: starting container process caused \"error adding seccomp rule for syscall socket: requested action matches def │ ault action of filter\""

看到這篇:https://github.com/cri-o/cri-o/issues/4491

將 runc 升級為 1.0.0-rc93 後解決

yum update runc -y

  1. 部署完畢後發現 busybox 不能使用 ping(權限不足),增加 CRI-O 的 capabilities,預設只有
1
2
3
4
5
6
7
8
9
10
11
default_capabilities = [
"CHOWN",
"DAC_OVERRIDE",
"FSETID",
"FOWNER",
"SETGID",
"SETUID",
"SETPCAP",
"NET_BIND_SERVICE",
"KILL",
]