k8s pod被驅逐問題分析及解決

一、問題現象及分析

環境說明

環境說明:java

  • centos7.3
  • Kubernetes1.14
  • docker 1.18.9

異常信息:kubectl get pod發現服務被驅逐,而後在調度到其它節點過程當中出現問題,之因此出現問題是由於編排文件中添加了污點,已經標註該Pod不能被調度到其它節點。可是爲何會出現Pod被驅逐,這卻是個問題?查看/var/log/messages中日誌,發現大量鏡像沒法被拉取的錯誤,以下所示:linux

鏡像被刪除問題

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等,也出現此類鏡像沒法拉取問題。nginx

出現這個問題,很容易理解,內網集羣,在集羣安裝過程當中,鏡像是經過複製過來的,可是執行docker images|grep k8s發現k8s的鏡像全不在了,難道有人爲刪除,要否則鏡像爲何會平白無故消失呢?web

因而又開始查看日誌,又發現日誌中存在此類信息,確認不是人爲刪除,而是kubelet回收掉了,具體日誌以下所示:docker

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自身運行須要的鏡像回收掉呢?這裏先不過多解釋,具體緣由,且看下文。centos

找不到manifests問題

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驅逐應該沒什麼關係,看了看其它計算接單存在一樣問題。微信

孤兒Volume問題

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,刪除事後,不在刷此類錯誤。app

驅逐問題

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查看了下磁盤,果真這臺機器服務產生了大量日誌,致使磁盤佔用太高,可是磁盤雖然佔用太高,爲何要回收鏡像呢?在官網查詢了下,大概是這樣介紹的:tcp

垃圾回收是kubelet的一個有用功能,它將清理未使用的鏡像和容器。kubelet將每分鐘對容器執行一次垃圾回收,每五分鐘對鏡像執行一次垃圾回收。

鏡像垃圾回收策略只考慮兩個因素:HighThresholdPercentLowThresholdPercent。磁盤使用率超過上限閾值(HighThresholdPercent)將觸發垃圾回收。垃圾回收將刪除最近最少使用的鏡像,直到磁盤使用率知足下限閾值(LowThresholdPercent)。

容器垃圾回收策略考慮三個用戶定義變量。MinAge是容器能夠被執行垃圾回收的最小生命週期。MaxPerPodContainer是每一個pod內容許存在的死亡容器的最大數量。MaxContainers是所有死亡容器的最大數量。能夠分別獨立地經過將MinAge設置爲0,以及將MaxPerPodContainerMaxContainers設置爲小於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

由於本地沒有安裝etcdctl,因此直接使用了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集羣出現問題時必定要仔細查看日誌,先看k8s自己事件信息,若是不能找到線索,緊接着查看內核日誌,出現問題以後,正常狀況下必定可以找到問題日誌。
  • 不要盲目刪除數據,必定搞明白東西的原理以後再作刪除操做,不然會帶來沒必要要的麻煩。

固然要完全解決此類問題,仍是須要監控巡邏系統,出現磁盤告警以後可以立馬通知到系統管理員或者自動作出進一步數據處理,不至於服務掛掉。若有問題,請關注公衆號,加我微信,一塊兒討論!

推薦

壓測nginx出現no live upstreams while connecting to upstream的問題分析

並不是每一個容器內部都能包含一個操做系統

原創不易,隨手關注或者」在看「,誠摯感謝!

本文分享自微信公衆號 - 雲原生技術愛好者社區(programmer_java)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索