本文介紹關于Pod異常問題排查的診斷流程、排查方法、常見問題及對應的解決方案。
如果您需要了解排查Pod問題常用的控制臺界面,例如如何查看Pod狀態、基礎信息、配置、事件和日志,使用終端進入容器,啟用Pod故障診斷等,可跳轉至常用排查界面了解。
診斷流程
如果Pod狀態異常,可通過查看Pod的事件、Pod的日志、Pod的配置等信息確定異常原因。大體排查流程如下。
階段一:調度問題
Pod未調度到節點
如果Pod長時間處于“未調度到節點”(Pending)狀態,沒有被安排到任何節點上運行,可能是出于以下原因。
報錯信息 | 說明 | 推薦的解決方案 |
| 當前集群中無可用節點可供調度。 |
|
| 集群中沒有可用節點能夠滿足Pod所需的CPU或內存資源。 | 在節點頁面查看容器組、CPU、內存的使用情況,確定集群的資源使用率。 說明 當某個節點的CPU和內存利用率維持在較低水平時,即便引入一個新Pod不會立即達到資源使用的上限,調度器也會謹慎考慮,以防該Pod的加入導致未來高峰時段節點資源緊張,避免因資源分配不當而引發的節點資源短缺問題。 若集群中的CPU或內存已經耗盡,可參考如下方法處理。
|
| 集群現有節點沒有匹配Pod聲明的節點親和性(nodeSelector)要求或Pod親和性(podAffinity和podAnitiAffinity)要求。 |
|
| Pod所使用的存儲卷與待調度的節點之間存在親和性沖突,云盤無法跨可用區掛載,導致調度失敗。 |
|
| ECS實例不支持掛載的云盤類型。 | 請參見實例規格族確認當前ECS支持的云盤類型。掛載時,將云盤類型更新為ECS實例當前支持的類型。 |
| 需要調度的節點打上了污點,不允許Pod調度到該節點上。 |
|
| 節點臨時存儲容量不足。 |
|
| Pod綁定PVC失敗。 | 檢查Pod所指定的PVC或PV是否已經創建,通過 |
Pod已調度到節點
如果Pod已經被調度到某個節點上但仍處于Pending狀態,請參見下文解決。
判斷Pod是否配置了
hostPort
:如果Pod配置了hostPort
,那么每個節點上只能運行一個使用該hostPort
的Pod實例。因此,Deployment或ReplicationController中Replicas
值不能超過集群中的節點數。如果該端口被其他應用占用,將導致Pod調度失敗。hostPort
會帶來一些管理和調度上的復雜性,推薦您使用Service來訪問Pod,請參見服務(Service)。如果Pod沒有配置
hostPort
,請參見下方步驟排查。通過
kubectl describe pod <pod-name>
命令查看Pod的Event信息,并解決對應的問題。Event可能會解釋Pod啟動失敗的原因,例如鏡像拉取失敗、資源不足、安全策略限制、配置錯誤等。Event中沒有有效信息時,進一步查看該節點kubelet的日志,進一步排查Pod啟動過程中存在的問題。您可以通過
grep -i <pod name> /var/log/messages* | less
命令搜索系統日志文件(/var/log/messages*
)中包含指定Pod名稱的日志條目。
階段二:鏡像拉取問題
報錯信息 | 說明 | 推薦的解決方案 |
| 請求訪問鏡像倉庫時被拒絕,創建Pod時未指定 | 檢查Pod YAML中 使用ACR時,可以使用免密插件拉取鏡像,請參見使用免密組件拉取容器鏡像。 |
| 通過HTTPS協議從指定的鏡像倉庫地址拉取鏡像時,鏡像地址解析失敗。 |
|
| 節點磁盤空間不足。 | 參見ECS遠程連接方式概述登錄到Pod所在節點,運行 |
| 第三方倉庫使用了非知名或不安全的CA簽署的證書。 |
|
| 操作取消,可能是由于鏡像文件過大。Kubernetes默認存在拉取鏡像超時時間,如果一定時間內鏡像下載沒有任何進度更新,Kubernetes會認為此操作異?;蛱幱跓o響應狀態,主動取消該任務。 |
|
| 無法連接鏡像倉庫,網絡不通。 |
|
| DockerHub對用戶拉取容器鏡像的請求設定了上限。 | 將鏡像上傳至容器鏡像服務ACR,從ACR鏡像倉庫中拉取鏡像。 |
一直顯示 | 可能觸發了kubelet的鏡像拉取限流機制。 | 通過自定義節點池kubelet配置功能調整registryPullQPS(鏡像倉庫的QPS上限)和registryBurst(突發性鏡像拉取的個數上限)。 |
階段三:啟動問題
Pod處于init狀態
錯誤信息 | 說明 | 推薦的解決方案 |
停留在 | 該Pod包含M個Init容器,其中N個已經啟動完成,但仍有M-N個Init容器未啟動成功。 |
關于Init容器的更多信息,請參見調試Init容器。 |
停留在 | Pod中的Init容器啟動失敗。 | |
停留在 | Pod中的Init容器啟動失敗并處于反復重啟狀態。 |
Pod創建中(Creating)
錯誤信息 | 說明 | 推薦的解決方案 |
| Flannel網絡插件設計原因,是預期內現象。 | 升級Flannel組件版本至v0.15.1.11-7e95fe23-aliyun及以上版本,請參見Flannel。 |
集群低于1.20版本時,如果發生Pod反復重啟、CronJob中的Pod在短時間內完成任務并退出等事件,可能會導致IP地址泄漏。 | 升級集群版本至1.20及以上,推薦使用最新版本的集群,請參見手動升級集群。 | |
containerd、runC存在的缺陷。 | 參見為什么Pod無法正常啟動,且報錯no IP addresses available in range?進行臨時緊急處理。 | |
| Pod所在的節點中,Terway網絡插件維護的用于追蹤和管理網絡接口ENI的內部數據庫狀態與實際的網絡設備配置之間存在數據不一致,造成ENI分配失敗。 |
|
| 可能是Terway向vSwitch申請IP時失敗。 |
|
Pod啟動失?。–rashLoopBackOff)
錯誤信息 | 說明 | 推薦的解決方案 |
日志中存在 |
| |
Event信息中存在 | 健康檢查失敗。 | 核查Pod中所配置的容器健康檢查(Liveness Probe)策略是否符合預期,能有效地反映出容器內應用程序的實際運行狀況。 |
Pod日志中存在 | 磁盤空間不足。 |
|
啟動失敗,無Event信息。 | Pod中聲明的Limit資源少于實際所需資源時,會導致啟動容器失敗。 | 檢查Pod的資源配置是否正確。您可以啟用資源畫像,獲得容器Request和Limit的推薦配置。 |
Pod日志中出現 | 同一Pod中的Container端口存在沖突。 |
|
Pod日志中出現 | 工作負載中掛載了Secret,但Secret對應的值沒有進行Base64加密。 |
|
自身業務問題。 | 查看Pod日志,通過日志內容排查問題。 |
階段四:Pod運行問題
OOM
當集群中的容器使用超過其限制的內存,容器可能會被終止,觸發OOM(Out Of Memory)事件,導致容器異常退出。關于OOM事件,請參見為容器和Pod分配內存資源。
若被終止的進程為容器的阻塞進程,可能會導致容器異常重啟。
若出現OOM異常問題,在控制臺的Pod詳情頁面單擊事件頁簽將展示OOM事件pod was OOM killed。
若集群配置了集群容器副本異常報警,OOM事件出現時會收到相關報警信息,請參見容器服務報警管理。
OOM級別 | 說明 | 推薦的解決方案 |
OS級別 | 查看Pod所在節點的內核日志 | 可能是系統全局內存不足、內存節點的內存不足或內存碎片化時伙伴系統內存不足。關于不同現象可能出現的原因,請參見可能原因;關于問題對應的解決方案,請參見解決方案。 |
cgroup級別 | 查看Pod所在節點的內核日志 | 若進程運行狀態正常,則根據實際運行需要,適當增大Pod的內存Limit,建議Pod的內存實際使用量不超過內存Limit取值的80%。具體操作,請參見設置容器的CPU和內存資源上下限。您可以啟用資源畫像,獲得容器Request和Limit的推薦配置。 |
Terminating
可能原因 | 說明 | 推薦的解決方案 |
節點存在異常,處于NotReady狀態。 | 處于NotReady狀態的節點恢復正常后會被自動刪除。 | |
Pod配置了Finalizers。 | 如果Pod配置了Finalizers,Kubernetes會在刪除Pod之前執行Finalizers指定的清理操作。如果相關的清理操作沒有正常響應,Pod將保持在Terminating狀態。 | 通過 |
Pod的preStop配置異常。 | 如果Pod配置了preStop,Kubernetes會在容器被終止之前執行preStop指定的操作。Pod正處于終止流程的preStop階段時,Pod將處于Terminating狀態。 | 通過 |
Pod配置了優雅退出時間。 | 如果Pod配置了優雅退出時間( | 等待容器優雅退出后,Kubernetes將自動刪除Pod。 |
容器無響應。 | 發起停止或刪除Pod的請求后,Kubernetes會向Pod內的容器發送 |
|
Evicted
可能原因 | 說明 | 推薦的解決方案 |
節點存在資源壓力,包括內存不足、磁盤空間不足等,引發kubelet主動驅逐節點上的一個或者多個Pod,以回收節點資源。 | 可能存在內存壓力、磁盤壓力、Pid壓力等??梢酝ㄟ^
|
|
發生了非預期的驅逐行為。 | 待運行Pod的節點被手動打上了NoExecute的污點,導致出現非預期的驅逐行為。 | 通過 |
未按照預期流程執行驅逐。 |
| 在小規格的集群(集群節點數小于等于50個節點)中,如果故障的節點大于總節點數的55%,實例的驅逐會被停止,更多信息請參見節點驅逐速率限制。 |
在大規模集群中(集群節點數大于50),如果集群中不健康的節點數量占總節點數的比例超過了預設的閾值 | ||
容器被驅逐后仍然頻繁調度到原節點。 | 節點驅逐容器時會根據節點的資源使用率進行判斷,而容器的調度規則是根據節點上的“資源分配量”進行判斷,被驅逐的Pod有可能被再次調度到這個節點,從而出現頻繁調度到原節點的現象。 | 根據集群節點的可分配資源檢查Pod的資源Request請求配置是否合理。如需調整,請參見設置容器的CPU和內存資源上下限。您可以啟用資源畫像,獲得容器Request和Limit的推薦配置。 |
Completed
Completed狀態下,Pod中容器的啟動命令已執行完畢,容器中的所有進程均已成功退出。Completed狀態通常適用于Job、Init容器等。
其他常見問題
Pod狀態為Running但沒正常工作
如果您的業務YAML存在問題,Pod可能會處于Running狀態但沒有正常工作。您可以參見以下流程解決。
查看Pod的配置,確定Pod中容器的配置是否符合預期。
使用以下方法,排查環境變量中的某一個Key是否存在拼寫錯誤。
創建Pod時,如果環境變量中的某個Key拼寫錯誤(例如將
command
拼寫為commnd
),集群會忽略該錯誤并使用該YAML成功創建資源。但在容器運行過程中,系統無法執行YAML文件中指定的命令。下文以
command
拼寫成commnd
為例,介紹拼寫問題的排查方法。在執行
kubectl apply -f
命令前為其添加--validate
,然后執行kubectl apply --validate -f XXX.yaml
命令。如拼寫存在錯誤,會提示報錯
XXX] unknown field: commnd XXX] this may be a false alarm, see https://gXXXb.XXX/6842pods/test
。執行以下命令,將輸出結果的pod.yaml與您創建Pod使用的YAML進行對比。
說明[$Pod]
為異常Pod的名稱,您可以通過kubectl get pods
命令查看。kubectl get pods [$Pod] -o yaml > pod.yaml
pod.yaml文件比您創建Pod所使用的文件行數更多,表明已創建的Pod符合預期。
如果您創建Pod的YAML代碼行不存在于pod.yaml文件中,表明YAML中存在拼寫問題。
查看Pod的日志,通過日志內容排查問題。
通過終端進入容器,查看容器內的本地文件是否符合預期。
Pod訪問數據庫概率性網絡斷聯
針對ACK集群中Pod訪問數據庫有概率性網絡斷聯的問題,可以按照以下步驟進行排查。
1、檢查Pod
查看目標集群中該Pod的事件記錄,檢查是否存在連接不穩定的異常事件,例如網絡異常、重啟事件、資源不足等。
查看Pod的日志輸出,確定是否有與數據庫連接相關的錯誤信息,例如超時、認證失敗或者重連機制觸發等。
查看Pod的CPU和內存使用情況,避免資源耗盡導致應用程序或數據庫驅動程序異常退出。
查看Pod的資源Request和Limit配置,確保Pod分配了足夠的CPU和內存資源。
2、檢查節點
查看節點的資源使用情況,確認是否有內存、磁盤等資源不足等情況。具體操作,請參見監控節點。
測試節點到與目標數據庫之間是否出現概率性網絡斷聯。
3、檢查數據庫
檢查數據庫的狀態和性能指標,是否出現重啟或性能瓶頸。
查看異常連接數和連接超時設置,并根據業務需求進行調整。
檢查日志數據庫是否有相關斷開連接的日志。
4、檢查集群組件狀態
集群組件異常會影響Pod與集群內其他組件的通信。使用如下命令,檢查ACK集群組件狀態。
kubectl get pod -n kube-system # 查看組件Pod狀態。
同時檢查網絡組件:
CoreDNS組件:檢查組件狀態和日志,確保Pod能正常解析數據庫服務的地址。
Flannel插件:查看kube-flannel組件的狀態和日志。
Terway插件:查看terway-eniip組件的狀態和日志。
5、分析網絡流量
您可以使用 tcpdump
來抓包并分析網絡流量,以幫助定位問題的原因。
使用以下命令確定數據庫連接斷開問題發生在哪個Pod和哪個節點上。
kubectl get pod -n [namespace] -o wide
登錄到目標節點,請參見ECS遠程連接方式概述。
使用以下命令,分別獲取不同版本的容器進程PID。
containerd(1.22以上集群)
執行以下命令查看容器
CONTAINER
。crictl ps |grep <Pod名稱關鍵字>
預期輸出:
CONTAINER IMAGE CREATED STATE a1a214d2***** 35d28df4***** 2 days ago Running
使用
CONTAINER ID
參數,執行以下命令查看容器PIDcrictl inspect a1a214d2***** |grep -i PID
預期輸出:
"pid": 2309838, # 目標容器的PID進程號。 "pid": 1 "type": "pid"
Docker(1.22及以下集群)
執行以下命令查看容器
CONTAINER ID
。docker ps |grep <pod名稱關鍵字>
預期輸出:
CONTAINER ID IMAGE COMMAND a1a214d2***** 35d28df4***** "/nginx
使用
CONTAINER ID
參數,執行以下命令查看容器PID。docker inspect a1a214d2***** |grep -i PID
預期輸出:
"Pid": 2309838, # 目標容器的PID進程號。 "PidMode": "", "PidsLimit": null,
執行抓包命令。
使用獲取到的容器PID,執行以下命令,捕獲Pod與目標數據庫之間的網絡通信數據包。
nsenter -t <容器PID> tcpdump -i any -n -s 0 tcp and host <數據庫IP地址>
使用獲取到的容器PID,執行以下命令,捕獲Pod與宿主機之間的網絡通信數據包。
nsenter -t <容器PID> tcpdump -i any -n -s 0 tcp and host <節點IP地址>
執行以下命令,捕獲宿主機與數據庫之間的網絡通信數據包。
tcpdump -i any -n -s 0 tcp and host <數據庫IP地址>
6、優化業務應用程序
在業務應用程序中實現數據庫連接的自動重連機制,確保數據庫發生切換或遷移時,應用程序能夠自動恢復連接,無需人工干預。
使用持久化的長連接而非短連接來與數據庫通信。長連接能顯著降低性能損耗和資源消耗,提高系統整體效率。
常用排查界面
您可以登錄容器服務管理控制臺,進入集群的詳情頁面,排查Pod可能存在的問題。
操作 | 控制臺界面 |
檢查Pod的狀態 |
|
檢查Pod的基礎信息 |
|
檢查Pod的配置 |
|
檢查Pod的事件 |
|
查看Pod的日志 |
說明 ACK集群集成了日志服務SLS。您可在集群中啟用SLS,快速采集集群的容器日志,請參見通過DaemonSet采集Kubernetes容器文本日志。 |
檢查Pod的監控 |
說明 ACK集群集成了阿里云Prometheus。您可以在集群中快速啟用阿里云Prometheus,以實時監控集群和容器的健康狀況,并查看可視化的Grafana監控數據大盤,請參見使用阿里云Prometheus監控。 |
使用終端進入容器,進入容器內部查看本地文件等信息 |
|
啟用Pod故障診斷 |
說明 容器智能運維平臺提供了一鍵故障診斷能力,輔助您定位集群中出現的問題,請參見使用集群診斷。 |