您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關k8s pod被驅逐問題分析及解決方法是什么,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
環境說明:
異常信息:kubectl get pod
發現服務被驅逐,然后在調度到其它節點過程中出現問題,之所以出現問題是因為編排文件中添加了污點,已經標注該Pod不能被調度到其它節點。但是為什么會出現Pod被驅逐,這倒是個問題?查看/var/log/messages
中日志,發現大量鏡像無法被拉取的錯誤,如下所示:
Nov 7 06:20:49 k8work2 kubelet: E1107 06:20:49.829886 13241 remote_image.go:113] PullImage "k8s.gcr.io/kube-proxy:v1.14.2" from image service failed: rpc error: code = Unknown desc = Error response from daemon: Get https://k8s.gcr.io/v2/: dial tcp 74.125.204.82:443: connect: connection timed out
Nov 7 06:20:49 k8work2 kubelet: E1107 06:20:49.866132 13241 pod_workers.go:190] Error syncing pod 4fedf7b3-207e-11eb-90a3-2c534a095a16 ("kube-proxy-pqvvb_kube-system(4fedf7b3-207e-11eb-90a3-2c534a095a16)"), skipping: failed to "StartContainer" for "kube-proxy" with ErrImagePull: "rpc error: code = Unknown desc = Error response from daemon: Get https://k8s.gcr.io/v2/: dial tcp 74.125.204.82:443: connect: connection timed out"
這段日志的意思是因為鏡像無法拉取,所以啟動出現啟動失敗問題,除此之外還有coredns、Controller
等,也出現此類鏡像無法拉取問題。
出現這個問題,很容易理解,內網集群,在集群安裝過程中,鏡像是通過復制過來的,但是執行docker images|grep k8s
發現k8s的鏡像全不在了,難道有人為刪除,要不然鏡像為什么會無緣無故消失呢?
于是又開始查看日志,又發現日志中存在此類信息,確認不是人為刪除,而是kubelet回收掉了,具體日志如下所示:
Nov 7 05:44:51 k8work2 kubelet: I1107 05:44:51.041315 13241 image_gc_manager.go:317] attempting to delete unused images
Nov 7 05:44:51 k8work2 kubelet: I1107 05:44:51.083785 13241 image_gc_manager.go:371] [imageGCManager]: Removing image "sha256:6858809bf669cc5da7cb6af83d0fae838284d12e1be0182f92f6bd96559873e3" to free 1231725 bytes
為什么要把k8s自身運行需要的鏡像回收掉呢?這里先不過多解釋,具體原因,且看下文。
Nov 7 06:20:47 k8work2 kubelet: E1107 06:20:47.943073 13241 file_linux.go:61] Unable to read config path "/etc/kubernetes/manifests": path does not exist, ignoring
其實看了下網上這個問題,也挺多的,因為是計算節點,不包含manifests,但是日志中一直在提示這個錯誤,這種噪音日志看著就難受,我是直接在/etc/kubernetes/
創建了manifests文件夾,問題直接解決。此錯誤跟本文中的Pod驅逐應該沒什么關系,看了看其它計算接單存在同樣問題。
Nov 7 09:32:03 k8work2 kubelet: E1107 09:32:03.431224 13241 kubelet_volumes.go:154] Orphaned pod "f6a977f4-2098-11eb-90a3-2c534a095a16" found, but volume paths are still present on disk : There were a total of 1 errors similar to this. Turn up verbosity to see them.
進入到/var/lib/kubelet/pods/
,通過id號,進入kubelet的目錄,可以發現里面還存在容器的數據,etc-hosts文件中還保留著pod名稱等信息。
從錯誤信息可以推測,這臺計算節點存在一個孤兒Pod,并且該Pod掛載了數據卷(volume),阻礙了Kubelet對孤兒Pod正常的回收清理。所以一直在提示上面錯誤信息,我在確認該Pod確認該Pod確實已經不在運行,并且沒有數據丟失的風險,直接執行了rm -rf f6a977f4-2098-11eb-90a3-2c534a095a16
,刪除過后,不在刷此類錯誤。
Nov 7 07:21:19 k8work2 kubelet: E1107 07:21:19.021705 13241 eviction_manager.go:576] eviction manager: pod es-0_log(aa41dd4c-2085-11eb-90a3-2c534a095a16) failed to evict timeout waiting to kill pod
Nov 7 07:21:22 k8work2 kubelet: I1107 07:21:22.883681 13241 image_gc_manager.go:300] [imageGCManager]: Disk usage on image filesystem is at 86% which is over the high threshold (85%). Trying to free 21849563955 bytes down to the low threshold (80%).
Nov 7 07:21:22 k8work2 kubelet: E1107 07:21:22.890923 13241 kubelet.go:1278] Image garbage collection failed multiple times in a row: failed to garbage collect required amount of images. Wanted to free 21849563955 bytes, but freed 0 bytes
日志大概提示意思是磁盤壓力過大,已經超過閾值,于是df -h
查看了下磁盤,果然這臺機器服務產生了大量日志,導致磁盤占用過高,但是磁盤雖然占用過高,為什么要回收鏡像呢?在官網查詢了下,大概是這樣介紹的:
垃圾回收是
kubelet
的一個有用功能,它將清理未使用的鏡像和容器。kubelet
將每分鐘對容器執行一次垃圾回收,每五分鐘對鏡像執行一次垃圾回收。
鏡像垃圾回收策略只考慮兩個因素:
HighThresholdPercent
和LowThresholdPercent
。磁盤使用率超過上限閾值(HighThresholdPercent
)將觸發垃圾回收。垃圾回收將刪除最近最少使用的鏡像,直到磁盤使用率滿足下限閾值(LowThresholdPercent
)。
容器垃圾回收策略考慮三個用戶定義變量。
MinAge
是容器可以被執行垃圾回收的最小生命周期。MaxPerPodContainer
是每個pod
內允許存在的死亡容器的最大數量。MaxContainers
是全部死亡容器的最大數量。可以分別獨立地通過將MinAge
設置為0,以及將MaxPerPodContainer
和MaxContainers
設置為小于0來禁用這些變量。kubelet
將處理無法辨識的、已刪除的以及超出前面提到的參數所設置范圍的容器。最老的容器通常會先被移除。
對于k8s用戶來說上述kubelet參數都是可以調整的,具體調整方式請參考:https://kubernetes.io/zh/docs/concepts/cluster-administration/kubelet-garbage-collection/
這里不在過多贅述。
說到這里大概已經找到原因,之所以出現Pod被驅逐,原因是因為磁盤壓力超過閾值,在k8s看來,這個計算節點已經不正常,所以開啟垃圾回收機制,按照默認回收策略首先刪除了自身的鏡像信息,然后導致內網鏡像拉取失敗問題,然后開始重新調度Pod,但是因為該Pod中添加了污點,不能被調度到其它節點,最后導致啟動失敗。
于是找到占用磁盤數據所在文件夾,是一個以pod PVC命名的文件,確認里面的數據可以刪除之后,我直接把PVC文件夾以及內容,全部都給刪掉了,再次啟動Pod,一直處于init狀態,event事件提示無法找到PVC,仔細看了下該Pod所在編排文件內容,發現該Pod是有狀態應用,以sts進行編排,我們知道sts以特定順序啟動,并且擁有穩定網絡身份標識、寫入固定的存儲,現在我把存儲名稱都給干掉了,所以導致無法啟動,大家引以為戒。
但是之所以會出現上面有狀態Pod無法啟動的問題,究其原因是因為復用了過去的PVC,我只要把PVC、PV刪除了,重新創建,一切萬事大吉,于是我開始使用kubectl delete pvc pvc_name -n log
,有趣的一幕又發生了,PVC一直卡在Terminating無法刪除。
網上查了查解決方式,大概兩種:
直接到etcd中刪除
使用kubectl patch
kubectl delete pvc pvc_name -n log
kubectl patch pvc pvc_name -p '{"metadata":{"finalizers":null}}' -n log
之所以需要強制執行,因為原生k8s不允許執行刪除后的回滾動作。這大概就是k8s最終一致性原則的體現。
再次重新啟動Pod,啟動成功,已經重新創建PVC和PV。
通過本文可以看出兩點:
當然要徹底解決此類問題,還是需要監控巡邏系統,出現磁盤告警之后能夠立馬通知到系統管理員或者自動做出進一步數據處理,不至于服務掛掉。如有問題,請關注公眾號,加我微信,一起討論!
看完上述內容,你們對k8s pod被驅逐問題分析及解決方法是什么有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。