Kubernetes疑難問題總結(一)

  • 分析ExitCode定位Pod異常退出原因

    查看ExitCode

    使用kubectl describe pod查看到pod對應退出狀態碼,如果不爲0,表示異常退出

    退出狀態碼區間,0-255,0表示正常退出

    外界中斷將程序退出的時候狀態碼區間是129-255

    程序自身原因導致的異常退出狀態碼區間在1-128

    常見異常狀態碼:

        137:被SIGKILL中斷信號殺死,常爲內存溢出,CPU達到限制,在describe pod中的表現就是OOMKilled

  • 容器內抓包定位網絡問題

    在kubernetes中運行容器應用,當容器應用中沒有一些常見的問題盤查命令,出現問題後是很難定位的,這個時候,我們就能進入容器的網絡命名空間netns,再使用宿主機上的命令進行問題排查。

    解決方法:

        1、kubectl get pod -o wide查看到應用所在主機節點

        2、在應用所在主機節點上docker ps | grep 應用名,定位到應用docker容器,獲取docker id

        3、docker inspect -f {{.State.Pid}} docker-id獲取到應用容器對應的進程pid

        4、nsenter -n -t pid進入容器網絡命名空間,進行curl,tcpdump,ping等抓包排查操作

  • PID耗盡

    檢查當前PID限制

    [root@k8s-master1 ~]# cat /proc/sys/kernel/pid_max 

    32768

    [root@k8s-master1 ~]# cat /proc/sys/kernel/threads-max 

    14531

    檢查系統當前進程數量,若超過內核限制則會導致進程無法啓動,可以通過調整最大閾值解決

    ps aux | wc -l

    解決方法:

        echo "kernel.pid_mac=65535" >> /etc.sysctl.conf && sysctl -p

        echo "kernel.tjreads-max=65535" >> /etc/sysctl.conf && sysctl -p

  • 內存碎片化

    內存分頁失敗,內核日誌報錯如下

    page allocate failure

    無法申請到內存,pod就會一直維持在ContainerCreating狀態

    內存碎片化過多會導致,即便現在看上去系統內存很多,但是無法申請到大塊的內存給進程使用,系統就會一直殺掉一些進程來釋放內存,導致OOM

    解決方法:

        週期性進行drop cache操作

        echo 3 > /proc/sys/vm/drop_caches

  • 磁盤爆滿

    容器運行時的磁盤爆滿會導致docker無響應,docker Hang住,kubelet日誌也能看到PLEG unhealthy,因爲CRI調用timeout,就無法創建或者銷燬容器,一直處於ContainerCreating以及Terminating。如果kubelet所在目錄磁盤空間不足,Sandbox也會創建失敗。

    關注路徑/var/lib/docker /var/lib/kubelet

    解決方法:

        手動刪除docker log文件,不要將容器日誌寫在容器內,需要另外掛載數據盤

        清理docker無用數據docker system prune -a

        設置正確的kubelet gc機制

        給docker設置日誌歸檔配置,只保留固定大小的日誌內容

  • Node NotReady

    kubelet,docker異常都會導致Node NotReady

    解決方法:

        查看docker響應速度是否正常,查看節點是否有大量日誌寫入,iotop,pidstat進行定位分析

        查看kubelet日誌journalctl -u kubelet

  • Pod一直處於Terminating,ContainerCreating,Error,ImagePullBackOff,Pending,Unknown狀態

    Terminating

        進程通過bash -c啓動導致kill信號無法傳遞給進程

        進程還存在掛載點,被其他進程佔用或者寫入,無法卸載

    解決方法:

        停止數據寫入,釋放掛載點

    ContainerCreating

        解決方法:

            檢查鏡像正確性

            掛載volume失敗

            磁盤滿了,容器創建失敗

            節點內存碎片化

            拉取鏡像失敗

            CNI網絡錯誤:檢查運行節點網絡組件是否正常

            查看controller-manager是否正常

    Error

        解決方法:

            說明Pod啓動過程產生錯誤

            依賴的ConfigMap,Secret,Volume產生錯誤

            違反集羣設置的安全策略,比如違反了PodSecurityPolicy等

    ImagePullBackOff

        解決方法:

            鏡像拉取失敗,認證失敗,鏡像不存在等

            docker默認以https類型的registry拉取。,如果不支持https則必須配置非安全認證docker,如果時https類型,則dockerd會校驗registry的證書,在/etc/docker/cert.d/<registry:port>/ca.crt

            如果鏡像需要認證,但是沒有配置ImagePullSecret也會拉取失敗

            鏡像拉取超時中斷管,查看鏡像倉庫前面的負載均衡保持長連接的超時時長,進行調整

    Pending

        解決方法:

            容器沒有足夠的CPU,內存資源進行調度

            nodeSelector,污點容忍,親和性不匹配

            kube-scheduler異常導致

      Unknown

          通常時節點失聯,沒法與apiserver通信,到達閾值後,controller-manager認爲節點失聯,並將其狀態置爲Unknown

          解決方法:

              查看節點kubelet狀態

  • 容器進程主動退出

        容器進程主動退出,不是被外界中斷殺死的話,退出碼一般在0-128,一般都是業務程序的bug

        容器啓動強依賴於第三方應用以及coredns解析失敗,導致的應用重啓

  • Apiserver響應慢

        查看apiserver日誌具體問題具體分析

        通過VIP訪問緩慢,有可能時VIP對應的nginx,LVS異常,可以通過kubectl get pod -s apiserver:8080繞過負載均衡進行驗證

  • Namespace Terminating

        解決方法:

            Namespace上存在Finalizers,將其清理後就可以正常刪除

            高版本的k8s集羣不支持在線修改finalizers刪除ns,要使用如下方法

           curl -H "Content-Type: application/json" -XPUT -d '{"apiVersion":"v1","kind":"Namespace","metadata":{"name":"delete-me"},"spec":{"finalizers":[]}}' http://localhost:8001/api/v1/namespaces/delete-me/finalize

  • cgroup泄露

        在低版本內核(3.10)中,一旦開啓了cgroup,就可能會導致不能徹底清理memcg和對應的cssid,也就是說應用即使刪除了cgroup(/sys/fs/cgroup/memory下對應的cgroup目錄)但在內核中沒有釋放cssid,導致內核認爲的從group實際數量不一致。這個問題會導致容器創建失敗,因爲創建容器會爲其創建cgroup進行隔離,而低版本內核中有個限制:允許創建的cgroup最大數量寫死爲65535,如果節點上經常創建銷燬容器導致創建很多cgroup造成泄露,創建容器的時候就會導致cgroup創建失敗並報錯“no space left on device”

        解決方法:

             升級內核到3.10.1064以上版本並且關閉kernel,kmem特性,重啓主機

  • arp緩存爆滿導致健康檢查失敗

        某集羣節點數 1200+,用戶監控方案是 daemonset 部署 node-exporter 暴露節點監控指標,使用 hostNework 方式,statefulset 部署 promethues 且僅有一個實例,落在了一個節點上,promethues 請求所有節點 node-exporter 獲取節點監控指標,也就是或掃描所有節點,導致 arp cache 需要存所有 node 的記錄,而節點數 1200+,大於了 net.ipv4.neigh.default.gc_thresh3 的默認值 1024,這個值是個硬限制,arp cache記錄數大於這個就會強制觸發 gc,所以會造成頻繁gc,當有數據包發送會查本地 arp,如果本地沒找到 arp 記錄就會判斷當前 arp cache 記錄數+1是否大於 gc_thresh3,如果沒有就會廣播 arp 查詢 mac 地址,如果大於了就直接報 arp_cache: neighbor table overflow!,並且放棄 arp 請求,無法獲取 mac 地址也就無法知道探測報文該往哪兒發(即便就在本機某個 veth pair),kubelet 對本機 pod 做存活檢查發 arp 查 mac 地址,在 arp cahce 找不到,由於這時 arp cache已經滿了,剛要 gc 但還沒做所以就只有報錯丟包,導致存活檢查失敗重啓 pod

         解決方法:

             調整gc_thresh閾值           

            net.ipv4.neigh.default.gc_thresh1 = 128

            net.ipv4.neigh.default.gc_thresh2 = 512

            net.ipv4.neigh.default.gc_thresh3 = 4096

  • DNS解析異常

      如果DNS解析經常延時5s才返回,可能時conntrack衝突導致的丟包

         解析超時,查看coredns服務是否正常

         解析外部域名超時,若容器應用使用的dnspolicy時clusterfirst,則需要查看coredns所在節點的dns解析是否能夠解析到外部域名,若dnspolicy爲default,則需要查看容器所在主機的dns是否能夠解析到外部域名,確認上游dns狀態,是否有ACL限制

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章