分析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限制