本文介紹關於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會認為此操作異常或處於無響應狀態,主動取消該任務。 |
|
| 無法串連鏡像倉庫,網路不通。 |
|
| DockerHub對使用者拉取容器鏡像的請求設定了上限。 | 將鏡像上傳至Container RegistryACR,從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啟動失敗(CrashLoopBackOff)
錯誤資訊 | 說明 | 推薦的解決方案 |
日誌中存在 |
| |
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事件出現時會收到相關警示資訊,請參見Container Service警示管理。
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、最佳化商務應用程式
在商務應用程式中實現資料庫連接的自動重連機制,確保資料庫發生切換或遷移時,應用程式能夠自動回復串連,無需人工幹預。
使用持久化的長串連而非短串連來與資料庫通訊。長串連能顯著降低效能損耗和資源消耗,提高系統整體效率。
常用排查介面
您可以登入Container Service管理主控台,進入叢集的詳情頁面,排查Pod可能存在的問題。
操作 | 控制台介面 |
檢查Pod的狀態 |
|
檢查Pod的基礎資訊 |
|
檢查Pod的配置 |
|
檢查Pod的事件 |
|
查看Pod的日誌 |
說明 ACK叢集整合了Log ServiceSLS。您可在叢集中啟用SLS,快速採集叢集的容器日誌,請參見通過DaemonSet採集Kubernetes容器文本日誌。 |
檢查Pod的監控 |
說明 ACK叢集整合了阿里雲Prometheus。您可以在叢集中快速啟用阿里雲Prometheus,以即時監控叢集和容器的健康情況,並查看可視化的Grafana監控資料大盤,請參見使用阿里雲Prometheus監控。 |
使用終端進入容器,進入容器內部查看本地檔案等資訊 |
|
啟用Pod故障診斷 |
說明 容器智能營運平台提供了一鍵故障診斷能力,輔助您定位叢集中出現的問題,請參見使用叢集診斷。 |