除錯 Pod
本指南旨在幫助使用者除錯部署到 Kubernetes 中但行為不正常的應用程式。這**不是**一份關於如何除錯叢集的指南。有關叢集除錯,你應該查閱本指南。
診斷問題
故障排除的第一步是分類。問題是什麼?是你的 Pod、你的 Replication Controller 還是你的 Service?
除錯 Pods
除錯 Pod 的第一步是檢視它。使用以下命令檢查 Pod 的當前狀態和最新事件:
kubectl describe pods ${POD_NAME}
檢視 Pod 中容器的狀態。它們都處於 `Running` 狀態嗎?最近有沒有重啟?
根據 Pod 的狀態繼續除錯。
我的 Pod 一直處於 Pending 狀態
如果 Pod 一直處於 `Pending` 狀態,這意味著它無法被排程到節點上。通常這是因為缺少某種資源導致無法排程。檢視上面 `kubectl describe ...` 命令的輸出。應該有排程器關於為什麼無法排程你的 Pod 的訊息。原因包括:
**你的資源不足**:你可能已經耗盡了叢集中的 CPU 或記憶體供應,在這種情況下,你需要刪除 Pod、調整資源請求或向叢集新增新節點。有關更多資訊,請參閱計算資源文件。
**你正在使用 `hostPort`**:當你將 Pod 繫結到 `hostPort` 時,可以排程該 Pod 的位置數量是有限的。在大多數情況下,`hostPort` 是不必要的,嘗試使用 Service 物件來暴露你的 Pod。如果你確實需要 `hostPort`,那麼你只能排程與 Kubernetes 叢集中節點數量相同的 Pod。
我的 Pod 一直處於 Waiting 狀態
如果 Pod 停留在 `Waiting` 狀態,則說明它已被排程到工作節點,但無法在該機器上執行。同樣,來自 `kubectl describe ...` 的資訊應該很有用。`Waiting` 狀態 Pod 最常見的原因是無法拉取映象。有三件事需要檢查:
- 確保映象名稱正確。
- 你是否已將映象推送到登錄檔?
- 嘗試手動拉取映象,看看是否可以拉取。例如,如果你在 PC 上使用 Docker,請執行 `docker pull
`。
我的 Pod 一直處於 Terminating 狀態
如果 Pod 停留在 `Terminating` 狀態,這意味著已為該 Pod 發出刪除指令,但控制平面無法刪除該 Pod 物件。
這種情況通常發生在 Pod 具有終結器(finalizer)且叢集中安裝了阻止控制平面移除終結器的准入 Webhook 時。
要識別這種情況,請檢查你的叢集是否有針對 `pods` 資源的 `UPDATE` 操作的任何 ValidatingWebhookConfiguration 或 MutatingWebhookConfiguration。
如果 Webhook 由第三方提供
- 確保你使用的是最新版本。
- 停用 `UPDATE` 操作的 Webhook。
- 向相應的提供商報告問題。
如果你是 Webhook 的作者
- 對於變更 Webhook,請確保它永遠不會在 `UPDATE` 操作中更改不可變欄位。例如,通常不允許更改容器。
- 對於驗證 Webhook,請確保你的驗證策略僅適用於新更改。換句話說,你應該允許現有違規的 Pod 透過驗證。這允許在驗證 Webhook 安裝之前建立的 Pod 繼續執行。
我的 Pod 崩潰或不健康
一旦你的 Pod 被排程,除錯執行中的 Pod 中描述的方法即可用於除錯。
我的 Pod 正在執行,但沒有按照我的指示執行
如果你的 Pod 行為不如預期,可能是因為你的 Pod 描述(例如你本地機器上的 `mypod.yaml` 檔案)中存在錯誤,並且在建立 Pod 時該錯誤被默默忽略了。通常,Pod 描述的一部分巢狀不正確,或者鍵名輸入錯誤,因此該鍵被忽略。例如,如果你將 `command` 拼寫為 `commnd`,那麼 Pod 將被建立,但不會使用你打算使用的命令列。
首先要做的就是刪除你的 Pod,然後嘗試使用 `--validate` 選項再次建立它。例如,執行 `kubectl apply --validate -f mypod.yaml`。如果你將 `command` 拼寫為 `commnd`,那麼會給出如下錯誤:
I0805 10:43:25.129850 46757 schema.go:126] unknown field: commnd
I0805 10:43:25.129973 46757 schema.go:129] this may be a false alarm, see https://github.com/kubernetes/kubernetes/issues/6842
pods/mypod
接下來要檢查的是 apiserver 上的 Pod 是否與你想要建立的 Pod (例如你本地機器上的 yaml 檔案) 匹配。例如,執行 `kubectl get pods/mypod -o yaml > mypod-on-apiserver.yaml`,然後手動比較原始 Pod 描述 `mypod.yaml` 和你從 apiserver 獲取的 `mypod-on-apiserver.yaml`。通常,“apiserver” 版本會比原始版本多出一些行。這是預期的。但是,如果原始版本中有一些行在 apiserver 版本中沒有,那麼這可能表明你的 Pod 規範存在問題。
除錯 Replication Controllers
副本控制器(Replication Controller)相當直接。它們要麼能夠建立 Pod,要麼不能。如果它們不能建立 Pod,那麼請參閱上面的說明來除錯你的 Pod。
你還可以使用 `kubectl describe rc ${CONTROLLER_NAME}` 來檢查與副本控制器相關的事件。
除錯 Services
Service 提供一組 Pod 之間的負載均衡。Service 無法正常工作有幾個常見問題。以下說明應有助於除錯 Service 問題。
首先,驗證服務是否有端點。對於每個 Service 物件,apiserver 都會提供一個或多個 `EndpointSlice` 資源。
你可以使用以下命令檢視這些資源:
kubectl get endpointslices -l kubernetes.io/service-name=${SERVICE_NAME}
確保 EndpointSlices 中的端點與你期望成為服務成員的 Pod 數量相匹配。例如,如果你的服務是針對具有 3 個副本的 nginx 容器,你將期望在服務的端點切片中看到三個不同的 IP 地址。
我的服務缺少端點
如果缺少端點,請嘗試使用 Service 所用的標籤列出 Pod。假設你的 Service 的標籤是:
...
spec:
- selector:
name: nginx
type: frontend
你可以使用
kubectl get pods --selector=name=nginx,type=frontend
來列出與此選擇器匹配的 Pod。驗證列表是否與你期望提供服務的 Pod 匹配。驗證 Pod 的 `containerPort` 是否與 Service 的 `targetPort` 匹配。
網路流量未轉發
有關更多資訊,請參閱除錯服務。
下一步
如果以上方法都不能解決你的問題,請按照除錯服務文件中的說明進行操作,以確保你的 `Service` 正在執行、具有 `Endpoints` 並且你的 `Pods` 實際上正在提供服務;確保你的 DNS 正常工作,iptables 規則已安裝,並且 kube-proxy 似乎沒有異常行為。
你也可以訪問故障排除文件以獲取更多資訊。