診斷流程
如果Pod狀態異常,可通過查看Pod的事件、Pod的日志、Pod的配置等信息確定異常原因。大體排查流程如下。
執行kubectl describe pod -n <pod所在命名空間> <podName>查看Pod事件,根據event中的報錯信息,排查對應原因
階段一:調度問題
Pod未調度到節點.
如果Pod長時間處于Pending狀態,說明該Pod沒有被安排到任何節點上運行。
| event中的報錯信息 | 說明 | 處理方式 |
|---|---|---|
| no nodes available to schedule pods. | 當前集群中沒有符合Pod要求的合適節點可供調度。 | 1、查看集群中是否存在狀態為NotReady的節點。如果存在,則對該類節點進行檢查和修復。 2、檢查Pod中是否聲明了nodeSelector、nodeAffinity或污點容忍。 3、若不存在親和性策略,可以檢查kube-system命名空間下的kube-scheduler對應的pod是否正常運行、pod中有無異常日志。 |
| 0/x nodes are available: x Insufficient cpu. 0/x nodes are available: x Insufficient memory. | 當前集群中沒有可用節點能夠滿足Pod所需的CPU或內存資源。 | 在節點頁面查看CPU、內存的使用情況,確定集群的資源使用率。 1、若集群中的CPU或內存已經耗盡,可參考如下方法處理。 1.1、調整工作負載副本數,刪除或減少不必要的Pod。 1.2、根據自身業務情況,調整Pod對應工作負載的CPU、內存資源的requests值和limits值。 2、在集群中擴容新的節點。 |
| x node(s) didn't match node selector. x node(s) didn't match pod affinity/anti-affinity. | 當前集群現有節點中,沒有節點滿足Pod聲明的nodeSelector要求或Pod親和性podAffinity或podAnitiAffinity要求。 | 1、檢查并調整Pod的節點親和性策略,包括節點標簽、nodeSelector、nodeAffinity、節點污點和Pod容忍等。 2、檢查并調整Pod的Pod親和性策略,如果Pod配置了podAffinity,則需要檢查目標節點上是否有匹配的Pod存在;如果配置了podAntiAffinity,則需確認目標節點上沒有不應共存的Pod。 |
| 0/x nodes are available: x node(s) had taints that the pod didn't tolerate. | 當前集群中Pod需要調度的目標節點被打上了污點,不允許該Pod調度到該節點上。 | 如果污點是由用戶手動添加,您可以刪除非預期的污點。如果無法刪除污點,可以為Pod配置相應的容忍。 如果污點為系統自動添加,您可以參見下文解決對應的問題,問題解決后等待Pod重新調度。 |
| 0/x nodes are available: x Insufficient ephemeral-storage. | 節點臨時存儲容量不足。 | 檢查Pod是否配置了臨時存儲卷的限制,即Pod YAML中spec.containers.resources.request.ephemeral-storage的取值。如果取值過高,超出了節點的實際可用容量,Pod會調度失敗。 執行kubectl describe node | grep -A10 Capacity命令,查看各個節點上可用于臨時存儲的總容量。如果容量不足,可擴容節點磁盤或增加節點數量。 |
| 0/x nodes are available: pod has unbound immediate PersistentVolumeClaims. | Pod綁定PVC失敗。 | 檢查Pod所指定的PVC或PV是否已經創建,通過kubectl describe pvc <pvc-name> 或 kubectl describe pv <pv-name>命令查看PVC、PV的Event信息,進一步進行判斷。 |
| too many pods | 當前集群中運行的Pod數量超過kubelet可容納的Pod最大值。 | 默認情況下,kubelet啟動參數--max-pods=110表明該節點最大只能容納110個Pod。根據自身業務情況和集群資源使用情況,調整工作負載副本數,刪除或減少不必要的Pod或修改kubelet的--max-pods啟動參數值。 |
| 系統自動添加的污點 | 對應含義 | 可能原因 | 處理方法 |
|---|---|---|---|
| node.kubernetes.io/not-ready | 節點未準備好,處于NotReady狀態。 | 1、節點上kubelet進程異常。 2、節點主機狀態異常,如:關機、hang死。 | 登錄主機檢查kubelet進程是否異常,有無錯誤日志。 |
| node.kubernetes.io/unreachable | 節點控制器訪問不到節點,相當于節點狀況Ready 的值為Unknown。 | 1、節點上kubelet進程異常 2、master節點到異常節點之間主機網絡異常 | 1、登錄主機檢查kubelet進程是否異常,有無錯誤日志。 2、排查異常節點到master節點直接的主機網絡。 |
| node.kubernetes.io/memory-pressure | 節點存在內存壓力。 | 節點上Pod進程和主機進程占用了較多內存,內存使用率較高。 | 1、調整工作負載副本數,刪除或減少不必要的Pod。2、根據自身業務情況,調整Pod對應工作負載的CPU、內存資源的requests值和limits值。 3、在集群中擴容新的節點。 |
| node.kubernetes.io/disk-pressure | 節點存在磁盤壓力。 | 節點上Pod進程和主機進程占用了較多的磁盤空間,磁盤空間不足。 | 1、清理主機上不再需要的大文件,如不再需要的鏡像文件、日志文件等。 2、新增磁盤掛載或擴容磁盤。 3、在集群中擴容新的節點。 |
| node.kubernetes.io/pid-pressure | 節點存在PID壓力。 | 節點上Pod進程和主機進程占用了較多的Pid,進程數過多導致可分配Pid不足。 | 1、盡量避免在k8s節點對應的主機上運行業務程序。 2、調整工作負載副本數,刪除或減少不必要的Pod。 3、在集群中擴容新的節點。 |
| node.kubernetes.io/network-unavailable | 節點網絡不可用。 | 節點上網絡插件Pod異常。 | 檢查該節點上的網絡插件Pod狀態和Pod日志。 |
| node.kubernetes.io/unschedulable | 節點不可調度。 | 節點被驅逐。 | 檢查是否人為將該節點設置為驅逐,可通過執行kubectl uncordon <nodeName>恢復。 |
Pod已調度到節點
如果Pod已經被調度到某個節點上但仍處于Pending狀態,請檢查Pod是否配置了hostPort。如果Pod配置了hostPort,那么每個節點最多只能運行一個使用該hostPort的Pod實例。因此,工作負載的副本數不能超過集群中的節點數。
檢查該端口被主機上的其他進程占用。
如果Pod沒有配置hostPort,且Event中沒有有效信息時,可查看該節點上的kubelet日志或系統日志(/var/log/messages*),根據Pod名稱進行過濾,進一步排查Pod啟動過程中存在的問題。
階段二:鏡像拉取問題
| 系統自動添加的污點 | 對應含義 | 可能原因 | 處理方法 |
|---|---|---|---|
| node.kubernetes.io/not-ready | 節點未準備好,處于NotReady狀態。 | 1、節點上kubelet進程異常。 2、節點主機狀態異常,如:關機、hang死。 | 登錄主機檢查kubelet進程是否異常,有無錯誤日志。 |
| node.kubernetes.io/unreachable | 節點控制器訪問不到節點,相當于節點狀況Ready 的值為Unknown。 | 1、節點上kubelet進程異常 2、master節點到異常節點之間主機網絡異常 | 1、登錄主機檢查kubelet進程是否異常,有無錯誤日志。 2、排查異常節點到master節點直接的主機網絡。 |
| node.kubernetes.io/memory-pressure | 節點存在內存壓力。 | 節點上Pod進程和主機進程占用了較多內存,內存使用率較高。 | 1、調整工作負載副本數,刪除或減少不必要的Pod。2、根據自身業務情況,調整Pod對應工作負載的CPU、內存資源的requests值和limits值。 3、在集群中擴容新的節點。 |
| node.kubernetes.io/disk-pressure | 節點存在磁盤壓力。 | 節點上Pod進程和主機進程占用了較多的磁盤空間,磁盤空間不足。 | 1、清理主機上不再需要的大文件,如不再需要的鏡像文件、日志文件等。 2、新增磁盤掛載或擴容磁盤。 3、在集群中擴容新的節點。 |
| node.kubernetes.io/pid-pressure | 節點存在PID壓力。 | 節點上Pod進程和主機進程占用了較多的Pid,進程數過多導致可分配Pid不足。 | 1、盡量避免在k8s節點對應的主機上運行業務程序。 2、調整工作負載副本數,刪除或減少不必要的Pod。 3、在集群中擴容新的節點。 |
| node.kubernetes.io/network-unavailable | 節點網絡不可用。 | 節點上網絡插件Pod異常。 | 檢查該節點上的網絡插件Pod狀態和Pod日志。 |
| node.kubernetes.io/unschedulable | 節點不可調度。 | 節點被驅逐。 | 檢查是否人為將該節點設置為驅逐,可通過執行kubectl uncordon <nodeName>恢復。 |
階段三:啟動問題
Pod處于init狀態
| 錯誤信息 | 說明 | 推薦的解決方案 |
|---|---|---|
| 停留在Init:N/M狀態 | 該Pod包含M個初始化容器中的N個已經啟動完成,剩余的容器未啟動成功。 | 通過kubectl describe pod -n <ns> <pod name>命令查看Pod的事件,確認當前Pod中未啟動的初始化容器是否存在異常。 通過kubectl logs -n <ns> <podName> -c <containerName>命令查看Pod中未成功啟動的初始化容器的日志,通過日志內容排查問題。 查看Pod的配置,例如檢查健康檢查配置,進一步確認未成功啟動的初始化容器配置是否正常。 |
| 停留在Init:Error狀態 | Pod中的初始化容器啟動失敗。 | |
| 停留在Init:CrashLoopBackOff狀態 | Pod中的初始化容器啟動失敗并處于反復重啟狀態。 |
Pod啟動失敗(CrashLoopBackOff)
| 錯誤信息 | 說明 | 推薦的解決方案 |
|---|---|---|
| 日志中存在exit(0)。 | 容器中前臺進程執行完畢正常退出。 | 非Job類型工作負載對應的Pod容器需要前臺進程作為常駐進程,若前臺進程執行完畢且無常駐進程,容器就會正常退出,kubelet檢測到容器退出后重新拉起該容器,進而導致容器一直在重啟。 修改容器主進程為常駐進程。 |
| Event信息中存在Liveness probe failed:。 | 容器健康檢查失敗。 | 核查Pod中所配置的容器健康檢查(Liveness Probe)策略是否符合預期,以及對應的健康檢查條件是否滿足。 |
| Pod日志中存在no left space。 | 磁盤空間不足。 | 清理主機上不再需要的大文件或擴容磁盤。 |
| 啟動失敗,無Event信息。 | 可能是Pod中聲明的Limit資源少于實際Pod進程啟動所需資源。 | 檢查Pod的資源配置是否正確。 |
| Pod日志中出現Address already in use。 | 同一Pod中的Container端口存在沖突。 | 檢查Pod是否配置了hostNetwork: true,這意味著Pod內的容器會直接與宿主機共享網絡接口和端口空間。如果無需使用,請改為hostNetwork: false。 如果Pod需要使用hostNetwork: true,請配置Pod的反親和性,確保同一副本集中的Pod被調度到不同節點。 檢查并確保不存在也不會有兩個或多個具有相同端口需求的Pod運行在同一臺節點上。 檢查主機上是否有主機進程占用了該端口,盡量避免在k8s節點主機上直接部署業務進程。 |
| Pod日志中出現container init caused \"setenv: invalid argument\"": unknown。 | 工作負載中掛載了Secret,但Secret對應的值沒有進行Base64加密。 | 通過控制臺創建Secret,Secret對應的值會自動進行Base64加密。 通過YAML創建Secret,并執行echo -n "xxxxx" | base64命令手動對密鑰值進行Base64加密。 |
| 無相關信息。 | 可能是業務Pod自身問題,如業務容器中進程啟動參數有誤。 | 查看Pod日志,通過業務日志內容排查問題。 |
階段四:Pod運行問題
OOM
當集群中的容器使用超過其限制的內存,容器可能會被終止,觸發OOM(Out Of Memory)事件,導致容器異常退出。
| OOM可能原因 | 說明 | 推薦的解決方案 |
|---|---|---|
| 系統內存不足 | 查看Pod所在節點的內核日志/var/log/messages,日志中存在Killed Process,但不存在kubepods相關日志;且主機內存使用量較高,表明是主機操作系統內存不足。 | 可能是系統全局內存不足、內存碎片化嚴重、內存泄露等。可提單排查。 |
| Pod內存不足 | 查看Pod所在節點的內核日志/var/log/messages,日志中存在類似Task in /kubepods.slice/xxxxx killed as a result of limit of /kubepods.slice/xxxx的報錯信息,且主機內存使用量不高或Pod的資源Limit值設置得較小,表明OOM為cgroup級別。 | 根據業務實際運行需要,適當增大Pod的內存Limit。 |
Terminating
| 可能原因 | 說明 | 推薦的解決方案 |
|---|---|---|
| 節點存在異常,處于NotReady狀態。 | 節點存在異常,處于NotReady狀態。 | 處于NotReady狀態的節點恢復正常后會被自動刪除。 |
| Pod配置了Finalizers。 | 如果Pod配置了Finalizers,Kubernetes會在刪除Pod之前執行Finalizers指定的清理操作。如果相關的清理操作沒有正常響應,Pod將保持在Terminating狀態。 | 通過kubectl get pod -n <ns> <podName> -o yaml查看Pod是否配置了Finalizers,進一步排查異常原因。 |
| Pod的preStop配置異常。 | 如果Pod配置了preStop,Kubernetes會在c。Pod正處于終止流程的preStop階段時,Pod將處于Terminating狀態。 | 通過kubectl get pod -n <ns> <pod name> -o yaml查看Pod的preStop配置,進一步排查異常原因。 |
| Pod配置了優雅退出時間。 | 如果Pod配置了優雅退出時間(terminationGracePeriodSeconds),Pod收到終止命令后(例如kubectl delete pod <pod_name>命令)會進入Terminating狀態。等待terminationGracePeriodSeconds設定的時間后,或容器提前退出后,Kubernetes才認為Pod已經成功關閉。 | 等待容器優雅退出后,Kubernetes將自動刪除Pod。 |
| 容器無響應。 | 發起停止或刪除Pod的請求后,Kubernetes會向Pod內的容器發送SIGTERM信號。如果容器在終止過程中沒有正確響應SIGTERM信號,Pod可能會停留在Terminating狀態。 | 使用kubectl delete pod <pod-name> --grace-period=0 --force強制刪除,釋放Pod資源。 檢查Pod所在節點的containerd或Docker日志,進一步進行排查。 |
Evicted
| 可能原因 | 說明 | 推薦的解決方案 |
|---|---|---|
| 節點存在資源壓力,包括內存不足、磁盤空間不足等,引發kubelet主動驅逐節點上的一個或者多個Pod,以回收節點資源。 | 可能存在內存壓力、磁盤壓力、Pid壓力等。可以通過kubectl describe node <node name> | grep Taints命令查詢。 內存壓力:帶有污點node.kubernetes.io/memory-pressure。 磁盤壓力:帶有污點node.kubernetes.io/disk-pressure。 Pid壓力:帶有污點node.kubernetes.io/pid-pressure。 | 內存壓力: 根據自身業務情況,調整Pod的資源配置。 磁盤壓力: 定時清理節點上的業務Pod日志,防止磁盤空間被耗盡。 為節點進行磁盤擴容。 Pid壓力:根據自身業務情況,調整Pod的資源配置。 |
| 發生了非預期的驅逐行為。 | 待運行Pod的節點被手動打上了NoExecute的污點,導致出現非預期的驅逐行為。 | 通過kubectl describe node <node name> | grep Taints命令檢查節點是否被打上了NoExecute污點。如是,請刪除。 |
| 未按照預期流程執行驅逐。 | --pod-eviction-timeout:當節點宕機時間超過設置時間后,開始驅逐宕機節點上的Pod,默認為5min。 --node-eviction-rate:每秒從節點上驅逐的Pod數量。默認為0.1,即每10s至多從一個節點上驅逐Pod。 --secondary-node-eviction-rate:第二檔的節點驅逐速率。當集群中宕機節點過多時,節點驅逐速率會降低至第二檔,默認值為0.01。 --unhealthy-zone-threshold:可用區的不健康閾值,默認為0.55,即當宕機的節點數量超過總節點數的55%時,該可用區被判定為不健康。 --large-cluster-size-threshold:集群的大規模閾值,默認為50,即當集群節點數量超過50時判定集群為大規模集群。 | 在小規格的集群(集群節點數小于等于50個節點)中,如果故障的節點大于總節點數的55%,實例的驅逐會被停止。 在大規模集群中(集群節點數大于50),如果集群中不健康的節點數量占總節點數的比例超過了預設的閾值--unhealthy-zone-threshold(默認為0.55),驅逐速率由--secondary-node-eviction-rate控制(代表每分鐘驅逐節點上Pod的最大比例),默認值為0.01。 |
| 容器被驅逐后仍然頻繁調度到原節點。 | 節點驅逐容器時會根據節點的資源使用率進行判斷,而容器的調度規則是根據節點上的“資源分配量”進行判斷,被驅逐的Pod有可能被再次調度到這個節點,從而出現頻繁調度到原節點的現象。 | 根據集群節點的可分配資源檢查Pod的資源Request請求配置是否合理。 |
Completed
Completed狀態下,Pod中容器的啟動命令已執行完畢,容器中的所有進程均已成功退出。Completed狀態通常適用于Job、Init容器等,該狀態是正常狀態。