作者簡介
鄧宇星,SUSE Rancher 中國區軟體架構師,6 年雲原生領域經驗,參與 Rancher 1.x 到 Rancher 2.x 版本迭代,目前負責 Rancher For openEuler(RFO) 專案開發。
最近我們關注到一個關於 containerd 執行時的 issue,該問題在 containerd v1.6.9/v1.5.15 被引入。出現的問題是,當 containerd 重啟後,在其中執行的 Pod 後設資料中關於網路相關的資料(如 pod ip)丟失,核心原因在於部分資料沒有落盤。
受影響的版本:
- v1.6.9 ~ v1.6.14,問題在 v1.6.15 版本中被修復。
- v1.5.15 ~ v1.5.16,問題在 v1.5.17 版本中被修復。
透過以下步驟,可以快速重現該問題,並驗證該問題的修復情況。
本文使用 rke2 為例進行演示,版本為 rke2 v1.24.9+rke2r1,該版本使用了 k3s-containerd v1.6.12-k3s1,受該 containerd 問題影響。
在 containerd 的預設行為中,重啟 containerd 服務不會影響正在執行的業務容器,並在啟動容器時,透過將容器父程式繫結 Pid 1 的方式進行體現。即使使用 systemctl 對服務進行重啟,也不會影響到已經在執行的容器狀態。
問題重現
# 配置rke2使用國內映象倉庫下載映象
mkdir -p /etc/rancher/rke2
echo "system-default-registry: registry.cn-hangzhou.aliyuncs.com" > /etc/rancher/rke2/config.yaml
# 使用命令安裝 rke2,以下命令使用了我們在國內維護的 rke2 安裝映象指令碼,會從aliyun OSS下載RKE2資源
curl -sfL https://rancher-mirror.oss-cn-beijing.aliyuncs.com/rke2/install.sh | INSTALL_RKE2_MIRROR=cn INSTALL_RKE2_VERSION=v1.24.9+rke2r1 sh -
# [INFO] using v1.24.9-rke2r1 as release
# [INFO] downloading checksums at https://rancher-mirror.rancher.cn/rke2/releases/download/v1.24.9-rke2r1/sha256sum-amd64.txt
# [INFO] downloading tarball at https://rancher-mirror.rancher.cn/rke2/releases/download/v1.24.9-rke2r1/rke2.linux-amd64.tar.gz
# [INFO] verifying tarball
# [INFO] unpacking tarball file to /usr/local
# 啟動 rke2 服務,並等待服務啟動成功
systemctl start rke2-server
# 配置 rke2 相關的 PATH 路徑以及 kube-config 路徑
export KUBECONFIG=/etc/rancher/rke2/rke2.yaml
export PATH=/var/lib/rancher/rke2/bin:$PATH
# 使用 kubectl 查詢當前叢集狀態
kubectl get po -A | grep rke2-metrics-server-5b987d776b-gqxv9
# kube-system rke2-metrics-server-5b987d776b-gqxv9 1/1 Running 0 15m
至此,rke2 單節點服務啟動完成,但我們的目標是 containerd,接下來繼續操作:
# 配置 containerd 相關環境變數
export CRI_CONFIG_FILE=/var/lib/rancher/rke2/agent/etc/containerd/config.toml CONTAINER_RUNTIME_ENDPOINT=unix:///var/run/k3s/containerd/containerd.sock
# 使用 crictl 查詢pods以及container資訊
crictl pods | grep rke2-metrics-server
# bfad445917423 18 minutes ago Ready rke2-metrics-server-5b987d776b-gqxv9 kube-system 0 (default)
crictl ps | grep rke2-metrics-server
# db5d6392a310e f6dc23a68f5fb 18 minutes ago Running metrics-server 0 bfad445917423 rke2-metrics-server-5b987d776b-gqxv9
我們以 metrics-server 的 pod 為例,查詢 pod 詳情中的網路部分內容,並對 containerd 進行重啟,對問題進行重現:
# 查詢 metrics-server pod的詳情
crictl inspectp bfad445917423 | jq .status.network
# {
# "additionalIps": [],
# "ip": "10.42.0.6"
# }
# 停止rke2-server服務並單獨啟動containerd,避免kubelet影響重現結果
systemctl stop rke2-server
# 單獨啟動 containerd
containerd -c /var/lib/rancher/rke2/agent/etc/containerd/config.toml -a /run/k3s/containerd/containerd.sock --state /run/k3s/containerd --root /var/lib/rancher/rke2/agent/containerd
透過新的 terminal,使用 crictl 查詢 containerd 執行狀態
crictl pods | grep rke2-metrics-server
# bfad445917423 24 minutes ago Ready rke2-metrics-server-5b987d776b-gqxv9 kube-system 0 (default)
# 再次查詢metrics-server pod詳情
crictl inspectp bfad445917423 | jq .status.network
# {
# "additionalIps": [],
# "ip": ""
# }
從最後的返回結果可以看出,containerd 重啟後容器的 IP 丟失。
問題影響
透過在上述例子中重啟 rke2-server 可以看到,由於 ip 資訊丟失,導致了業務容器被重建,帶來了業務中斷的風險。
# 在中斷 containerd程式後,重啟rke2-server程式(以下資料為重新驗證後的資料)
systemctl restart rke2-server
kubectl get po -A |grep rke2-metrics-server-5b987d776b-8vg69
# kube-system rke2-metrics-server-5b987d776b-8vg69 1/1 Running 2 (115s ago) 23m
crictl pods | grep rke2-metrics-server
# caba6d8d15823 41 seconds ago Ready rke2-metrics-server-5b987d776b-8vg69 kube-system 1 (default)
# 2dec6a11fd36f 22 minutes ago NotReady rke2-metrics-server-5b987d776b-8vg69 kube-system 0 (default)
可以看到,在 rke2-server 重啟後,使用了 cni 的 pod 發生了重啟,在 crictl pods 返回中可以看到重新建立的 pods。
問題修復驗證
下載新版本 containerd,這次驗證使用 k3s-containerd v1.6.14+k3s1。該版本為 Rancher 在 containerd v1.6.15 釋出前緊急釋出的修復補丁版本。
# 拉取新映象
docker pull rancher/hardened-containerd:v1.6.14-k3s1-build20230105
mkdir container-new
cd container-new
# 從映象中獲取新版本containerd
docker run --rm -it -v ${PWD}:/output rancher/hardened-containerd:v1.6.14-k3s1-build20230105 cp -r /usr/local/bin /output
./output/bin/containerd --version
# containerd github.com/k3s-io/containerd v1.6.14-k3s1 6f9c63d571f5026e85a0768f0f2ef03d1c8dbc6e
# 關閉當前執行的容器
pkill -f /var/lib/rancher/rke2/data/v1.24.9-rke2r1-d4d8faf800d0/bin/containerd-shim-runc-v2
# 替換containerd binary版本
cp ./bin/* /var/lib/rancher/rke2/bin
/var/lib/rancher/rke2/bin/containerd --version
# containerd github.com/k3s-io/containerd v1.6.14-k3s1 6f9c63d571f5026e85a0768f0f2ef03d1c8dbc6e
# 啟動 rke2
systemctl start rke2-server
# 此時使用 crictl 查詢新的 metrics-server pod
crictl pods | grep " Ready" |grep metrics-server
# ad8b101f819df 3 minutes ago Ready rke2-metrics-server-5b987d776b-gqxv9 kube-system 1 (default)
# 停止 rke2 並使用命令列啟動 containerd
systemctl stop rke2-server
containerd -c /var/lib/rancher/rke2/agent/etc/containerd/config.toml -a /run/k3s/containerd/containerd.sock --state /run/k3s/containerd --root /var/lib/rancher/rke2/agent/containerd
透過新的 terminal,使用 crictl 查詢 containerd 執行狀態
crictl inspectp ad8b101f819df | jq .status.network
# {
# "additionalIps": [],
# "ip": "10.42.0.13"
# }
可以看到 containerd 重啟後,pod ip 沒有丟失。
RKE2 與 RFO
RKE2 以下版本受該 issue 影響:
- v1.23.15+rke2r1
- v1.24.9+rke2r1
- v1.25.5+rke2r1
- v1.26.0+rke2r1
該 issue 在 2022 年 12 月 20 日被提交,RKE2 團隊在 2023 年 1 月 6 日緊急合併了 containerd 中修復該 issue 的 commit,釋出了 k3s-containerd v1.6.14+k3s1 版本,併發布了新的 rke2 rc 版本進行測試驗證。
最終在 1 月 11 日,RKE2 團隊釋出以下已經修復 containerd 問題的版本:
- v1.23.16+rke2r1
- v1.24.9+rke2r2
- v1.25.5+rke2r2
- v1.26.0+rke2r2
RFO 是 Rancher For openEuler 的縮寫,顧名思義,目的在於面向 openEuler 打造 Rancher 基礎平臺。
由於 RFO 版本釋出週期在 RKE2 之後,RFO 並沒有受到該 issue 影響,並在近期釋出了以下版本:
- v1.23.16+rfor1
- v1.24.9+rfor1
- v1.24.10+rfor1
- v1.25.5+rfor1
- v1.25.6+rfor1
- v1.26.0+rfor1
- v1.26.1+rfor1
寫在最後
由於作業系統的軟體包釋出存在一定的時間延後性,在大部分情況下都無法及時修復軟體出現的問題。像 CVE、功能缺陷等問題都比較緊急,等待作業系統供應商提供修復版本將是一個漫長的過程,甚至有時候由於一些限制,作業系統提供商無法提供新版本的軟體包,這會給系統執行帶來不確定因素。
在這種情況下,將軟體自身依賴的元件打包到自己的 rootfs 中進行分發,能更好地對其進行管理和升級,避免給系統執行帶來風險以及潛在的損失。
關於 RFO 的專案說明和部署使用,請點選《Rancher RFO 正式 GA》。