應用故障排查

東風夜放二叉樹發表於2020-12-24
kubectl describe pods ${POD_NAME}

Pods停滯在Pending狀態

Pod沒有被排程到節點上

  • 資源不足: 你可能耗盡了叢集上所有的 CPU 或記憶體。此時,你需要刪除 Pod、調整資源請求或者為叢集新增節點。 更多資訊請參閱計算資源文件

  • 使用了 hostPort: 如果繫結 Pod 到 hostPort,那麼能夠執行該 Pod 的節點就有限了。 多數情況下,hostPort 是非必要的,而應該採用 Service 物件來暴露 Pod。 如果確實需要使用 hostPort,那麼叢集中節點的個數就是所能建立的 Pod 的數量上限。

Pods停滯在Waiting狀態

表示Pod已經被排程到某工作節點,但是無法在該節點上執行。

Waiting 狀態的最常見原因是拉取映象失敗。要檢查的有三個方面:

  • 確保映象名字拼寫正確
  • 確保映象已被推送到映象倉庫
  • 用手動命令 docker pull <映象> 試試看映象是否可拉取

Pod 處於 Crashing 或別的不健康狀態

一旦 Pod 被排程,就可以採用 除錯執行中的 Pod 中的方法來進一步除錯。

Pod 處於 Running 態但是沒有正常工作

如果 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

接下來就要檢查的是 API 伺服器上的 Pod 與你所期望建立的是否匹配 (例如,你原本使用本機上的一個 YAML 檔案來建立 Pod)。 例如,執行 kubectl get pods/mypod -o yaml > mypod-on-apiserver.yaml,之後 手動比較 mypod.yaml 與從 API 伺服器取回的 Pod 描述。 從 API 伺服器處獲得的 YAML 通常包含一些建立 Pod 所用的 YAML 中不存在的行,這是正常的。 不過,如果如果原始檔中有些行在 API 伺服器版本中不存在,則意味著 Pod 規約是有問題的。

副本控制器相對比較簡單直接。它們要麼能建立 Pod,要麼不能。 如果不能建立 Pod,請參閱上述說明除錯 Pod。

你也可以使用 kubectl describe rc ${CONTROLLER_NAME} 命令來檢視副本控制器相關的事件。

服務支援在多個 Pod 間負載均衡。 有一些常見的問題可以造成服務無法正常工作。 以下說明將有助於除錯服務的問題。

首先,驗證服務是否有端點。對於每一個 Service 物件,API 伺服器為其提供 對應的 endpoints 資源。

通過如下命令可以檢視 endpoints 資源:

kubectl get endpoints ${SERVICE_NAME}

確保 Endpoints 與服務成員 Pod 個數一致。 例如,如果你的 Service 用來執行 3 個副本的 nginx 容器,你應該會在服務的 Endpoints 中看到 3 個不同的 IP 地址。

服務缺少 Endpoints

如果沒有 Endpoints,請嘗試使用 Service 所使用的標籤列出 Pod。 假定你的服務包含如下標籤選擇算符:

...
spec:
  - selector:
     name: nginx
     type: frontend

你可以使用如下命令列出與選擇算符相匹配的 Pod,並驗證這些 Pod 是否歸屬於建立的服務:

kubectl get pods --selector=name=nginx,type=frontend

如果 Pod 列表符合預期,但是 Endpoints 仍然為空,那麼可能暴露的埠不正確。 如果服務指定了 containerPort,但是所選中的 Pod 沒有列出該埠,這些 Pod 不會被新增到 Endpoints 列表。

驗證 Pod 的 containerPort 與服務的 targetPort 是否匹配。

網路流量未被轉發

如果你可以連線到服務上,但是連線立即被斷開了,並且在 Endpoints 列表中有末端表項, 可能是代理無法連線到 Pod。

要檢查的有以下三項:

  • Pod 工作是否正常? 看一下重啟計數,並參閱除錯 Pod
  • 是否可以直接連線到 Pod?獲取 Pod 的 IP 地址,然後嘗試直接連線到該 IP;
  • 應用是否在配置的埠上進行服務?Kubernetes 不進行埠重對映,所以如果應用在 8080 埠上服務,那麼 containerPort 欄位就要設定為 8080。

如果上述方法都不能解決你的問題,請按照 除錯服務文件中的介紹, 確保你的 Service 處於 Running 態,有 Endpoints 被建立,Pod 真的在提供服務; DNS 服務已配置並正常工作,iptables 規則也以安裝並且 kube-proxy 也沒有異常行為。
你也可以訪問故障排查文件來獲取更多資訊。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章