【containerd】RunPodSandbox for XXX error="failed to reserve sandbox name"

問題背景

工業(yè)云部署使用k8s集群

  • k8s: 01746170708faa599113b027772802bcbb594ee8
  • containerd: v1.5.4
  • OS: Tencent tlinux 2.2 (Final)
  • kernel: Linux TENCENT64.site 3.10.0-693_4003268.tl2

問題描述

工業(yè)云同學通過控制臺升級業(yè)務容器鏡像版本,升級后導致容器創(chuàng)建失敗,失敗的error log如下所示:

Jun 06 20:45:29 TENCENT64.site containerd[5327]: time="2022-06-06T20:45:29.816213573+08:00" level=error msg="RunPodSandbox for &PodSandboxMetadata{Name:edge-56c86c995f-tqzz2,Uid:da70d1c2-0978-40c1-a9a6-c5a25a7f41a3,Namespace:edge-adapter,Attempt:0,} failed, error" error="failed to reserve sandbox name \"edge-56c86c995f-tqzz2_edge-adapter_da70d1c2-0978-40c1-a9a6-c5a25a7f41a3_0\": name \"edge-56c86c995f-tqzz2_edge-adapter_da70d1c2-0978-40c1-a9a6-c5a25a7f41a3_0\" is reserved for \"762b66093089b50109f74fa5a4cc6e7165d916b18dfd1b5c877fc4effff1e558\""

問題排查

  • 創(chuàng)建一個測試nginx的容器也創(chuàng)建失敗,報錯相同也是卡在create pod sandbox:


    image.png
  • 通過nerdctl run創(chuàng)建容器發(fā)現(xiàn)也創(chuàng)建失敗,卡在creating 狀態(tài):

  • 查看containerd的error log:


    image.png
  • 查看kubelet日志:

Jun 06 20:45:29 TENCENT64.site containerd[5327]: time="2022-06-06T20:45:29.816213573+08:00" level=error msg="RunPodSandbox for &PodSandboxMetadata{Name:edge-56c86c995f-tqzz2,Uid:da70d1c2-0978-40c1-a9a6-c5a25a7f41a3,Namespace:edge-adapter,Attempt:0,} failed, error" error="failed to reserve sandbox name \"edge-56c86c995f-tqzz2_edge-adapter_da70d1c2-0978-40c1-a9a6-c5a25a7f41a3_0\": name \"edge-56c86c995f-tqzz2_edge-adapter_da70d1c2-0978-40c1-a9a6-c5a25a7f41a3_0\" is reserved for \"762b66093089b50109f74fa5a4cc6e7165d916b18dfd1b5c877fc4effff1e558\""
  • 環(huán)境中發(fā)現(xiàn)kworker占用CPU的使用率很高:


    image.png
  • 集群上的Pod IP分配情況:


    image.png
  • 內(nèi)存使用情況


    image.png
  • 有個containerd的僵尸進程是5月25號啟動的,被systemd 1號進程托管,kill -9也殺不掉該進程

  • 環(huán)境中存在chaosmesh 進程使用containerd,

ps -ef | grep chao
root        752 101375  0 16:05 pts/1    00:00:00 grep --color=auto chao
root      60780  59079  0 06:30 ?        00:00:03 /usr/local/bin/chaos-daemon --runtime containerd --http-port 31766 --grpc-port 31767 --pprof --ca /etc/chaos-daemon/cert/ca.crt --cert /etc/chaos-daemon/cert/tls.crt --key /etc/chaos-daemon/cert/tls.key --runtime-socket-path /host-run/containerd.sock

問題處理

  • GitHub上搜索相關(guān)的issue,發(fā)現(xiàn)有類似error的issue:https://github.com/containerd/containerd/issues/4604
  • 根據(jù)issue描述,初步懷疑是磁盤的IO過高導致容器創(chuàng)建失敗,此問題社區(qū)已經(jīng)有對應的bug fix PR:https://github.com/containerd/containerd/pull/6478/files
  • 由于1.5.4版本中沒有這個fix,所以在環(huán)境上升級了containerd版本,v1.5.10,這個版本包含對應的code fix,并且重啟了機器,機器重啟后pod都正常running,kworker使用CPU也恢復正常,由于當時沒有查看IO的使用情況,所以不能排除IO不是真正的root cause,此問題需要繼續(xù)跟進。

后續(xù)問題跟進

  • 環(huán)境上已經(jīng)替換為新版本的containerd,后面繼續(xù)觀察集群節(jié)點上的IO使用情況iotop,kworker的資源使用情況top;
  • 在自測環(huán)境中做壓力測試復現(xiàn)問題:
stress-ng --io 30 -d 5
image.png

創(chuàng)建nginx deployment:

kubectl apply -f nginx.yaml
 kubectl get pods
NAME                               READY   STATUS              RESTARTS   AGE
nginx-deployment-857cbc9c6-7plrb   0/1     ContainerCreating   0          7m41s
nginx-deployment-857cbc9c6-f5gjq   0/1     ContainerCreating   0          7m40s
image.png

kubelet error log:


image.png

containerd error log:

Jun 07 21:03:05 VM-71-117-ubuntu containerd[14269]: time="2022-06-07T21:03:05.036947355+08:00" level=error msg="RunPodSandbox for &PodSandboxMetadata{Name:nginx-deployment-857cbc9c6-f5gjq,Uid:29d9b646-2ed6-411d-b89a-5e1526de3393,Namespace:default,Attempt:0,} failed, error" error="failed to reserve sandbox name \"nginx-deployment-857cbc9c6-f5gjq_default_29d9b646-2ed6-411d-b89a-5e1526de3393_0\": name \"nginx-deployment-857cbc9c6-f5gjq_default_29d9b646-2ed6-411d-b89a-5e1526de3393_0\" is reserved for \"aa39cc65311ca413accf095a659c372b02e987d5b97687d3241c830f3b1091d5\""

把壓力測試進程停掉,pod就創(chuàng)建成功了:

kubectl get pods
NAME                               READY   STATUS    RESTARTS   AGE
nginx-deployment-857cbc9c6-7plrb   1/1     Running   0          14m
nginx-deployment-857cbc9c6-f5gjq   1/1     Running   0          14m
  • 使用containerd v1.5.10做壓力測試
    創(chuàng)建Pod還是會卡在creating狀態(tài)大概五分鐘,最后狀態(tài)變成RunContainerError狀態(tài),最后還是會報錯failed to reserve sandbox name \"nginx-deployment-857cbc9c6-sp5rp_default_c2c8a3d4-0e02-4688-8b6e-711a0f6525c5_0\": name \"nginx-deployment-857cbc9c6-sp5rp_default_c2c8a3d4-0e02-4688-8b6e-711a0f6525c5_0\" is reserved for \"39ab9d7b6250608fd911ff079f3d0781044674e2d6a1e58893ed422d6a2adb60\""
 Normal   Scheduled               7m41s  default-scheduler  Successfully assigned default/nginx-deployment-857cbc9c6-sp5rp to 10.0.71.117
  Warning  FailedCreatePodSandBox  3m37s  kubelet            Failed to create pod sandbox: rpc error: code = DeadlineExceeded desc = context deadline exceeded
root@VM-71-117-ubuntu:~# kubectl get pods
NAME                               READY   STATUS              RESTARTS   AGE
nginx-deployment-857cbc9c6-sp5rp   0/1     ContainerCreating   0          7m23s
nginx-deployment-857cbc9c6-wm88t   0/1     RunContainerError   0          7m24s

kubelet log:

Jun 08 10:00:13 VM-71-117-ubuntu kubelet[11643]: E0608 10:00:13.322478   11643 pod_workers.go:190] "Error syncing pod, skipping" err="failed to \"CreatePodSandbox\" for \"nginx-deployment-857cbc9c6-sp5rp_default(c2c8a3d4-0e02-4688-8b6e-711a0f6525c5)\" with CreatePodSandboxError: \"Failed to create sandbox for pod \\\"nginx-deployment-857cbc9c6-sp5rp_default(c2c8a3d4-0e02-4688-8b6e-711a0f6525c5)\\\": rpc error: code = DeadlineExceeded desc = context deadline exceeded\"" pod="default/nginx-deployment-857cbc9c6-sp5rp" podUID=c2c8a3d4-0e02-4688-8b6e-711a0f6525c5

containerd log:


image.png
  • 分析錯誤產(chǎn)生的原因
    1、kubelet 發(fā)送請求給 containerd 創(chuàng)建容器,當 containerd 第一次嘗試創(chuàng)建這個容器的時候,它會創(chuàng)建名為Attempt的元數(shù)據(jù),該變量保持默認值為0代碼)
    2、在kubelet和containerd之間發(fā)生context timeout
    3、在下一次kubelet運行 SyncPod 時,kubelet 會嘗試再次創(chuàng)建相同的容器。但是,它不會在 CreateContainer 超時時增加Attempt次數(shù),只會在容器重新啟動時增加,在超時之后,Attempt number 不會增加,但是 CRI 已經(jīng)保留了容器名稱,因此所有后續(xù)創(chuàng)建相同容器的請求都會失敗代碼
    這是kubelet和containerd的正常的行為,如果容器設置策略為restartPolicy:Always or restartPolicy:OnFailure當磁盤IO下降,containerd最終會創(chuàng)建容器成功。(根據(jù)前面的壓測結(jié)果,如果kill掉IO比較高的壓測進程,容器會很快創(chuàng)建成功。)
  • PR fix解析
    目前社區(qū)內(nèi)針對這個問題,merge了一個PR ,此PR主要是解決在createContainer的時候調(diào)用umount觸發(fā)內(nèi)核調(diào)用sync-fs,這樣會增加磁盤的IO開銷,使用readonly mount就不會掉用sync-fs方法,此PR改用readonly mount,這樣可以減少 PodCreateContainer 中的 syncfs,減小containerd帶來的IO開銷,從而加快容器的創(chuàng)建,但它不能減少 runc 進程中的 mount 時的產(chǎn)生的磁盤IO。
    所以繼續(xù)跟蹤發(fā)現(xiàn):runc init確實也卡住了
root      3516  3508  0 15:54 pts/1    00:00:00 runc init
image.png
image.png

通過ps aux | grep runc會發(fā)現(xiàn)有些runc stack是卡在do_mount上,并且runc的進程狀態(tài)是D,什么是D狀態(tài)呢?D狀態(tài)的進程通常是在等待IO,比如磁盤IO,網(wǎng)絡IO,其他外設IO,很明顯這塊是在等待磁盤IO。

  • 目前的解決方法
    從上面的排查和社區(qū)的分析來看,此問題主要是磁盤IO過高導致的,所以要解決問題,就是從如何降低磁盤IO出發(fā),上面的PR fix也是從containerd方面降低磁盤IO:
    1、更換高性能的磁盤,提高磁盤IO,增大磁盤容量;
    2、增加集群節(jié)點,對于高IO的業(yè)務,遷移到其它節(jié)點,減小節(jié)點的IO(公有云的解決方法是加cbs或者挪到eks);
    3、在更新業(yè)務的時候,不要同時更新多個,可以每次保持最小化更新,防止pull image加大磁盤IO導致更新失敗。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容