如何對 Amazon EKS 中的 Pod 狀態進行疑難排解?

5 分的閱讀內容
0

在 mazon Elastic Compute Cloud (Amazon EC2) 執行個體或受管節點群組上執行的 Amazon Elastic Kubernetes Service (Amazon EKS) 節點已卡住。我想讓我的 Pod 處於「執行中」或「已終止」狀態。

解決方法

**重要:**下列步驟僅適用於在 Amazon EC2 執行個體或受管節點群組上啟動的 Pod。這些步驟不適用於在 AWS Fargate 上啟動的 Pod。

了解 Pod 的狀態

若要對 Amazon EKS 中的 Pod 狀態進行疑難排解,請完成下列步驟:

  1. 若要取得 Pod 的狀態,請執行下列命令:

    $ kubectl get pod
  2. 若要從 Pod 的事件歷史記錄取得資訊,請執行下列命令:

    $ kubectl describe pod YOUR_POD_NAME
  3. 根據 Pod 的狀態,完成下列區段中的步驟。

Pod 處於「待定」狀態

**注意:**下列步驟中的範例命令位於預設命名空間中。對於其他命名空間,在命令中附加 -n YOURNAMESPACE。

Pod 可能因為資源不足,或是您已定義 hostPort,而卡在待定狀態。如需詳細資訊,請參閱 Kubernetes 網站上的 Pod 階段

如果工作節點上的資源不足,請刪除不必要的 Pod。您也可以在工作節點上新增更多資源。當您的叢集中沒有足夠資源時,請使用 Kubernetes Cluster Autoscaler 自動擴展工作節點群組。

CPU 不足範例:

$ kubectl describe pod frontend-cpu
Name:         frontend-cpu
...
Status:       Pending
...
Events:
  Type     Reason            Age                 From               Message
  ----     ------            ----                ----               -------
  Warning  FailedScheduling  22s (x14 over 13m)  default-scheduler  0/3 nodes are available: 3 Insufficient cpu.

記憶體不足範例:

$ kubectl describe pod frontend-memory
Name:         frontend-memory
...
Status:       Pending
...
Events:
  Type     Reason            Age                 From               Message
  ----     ------            ----                ----               -------
  Warning  FailedScheduling  80s (x14 over 15m)  default-scheduler  0/3 nodes are available: 3 Insufficient memory.

如果您已為 Pod 定義 hostPort,請遵循下列最佳實務:

  • 由於 hostIPhostPortprotocol 必須是唯一的,因此僅在必要時指定 hostPort
  • 如果您指定 hostPort,則排程與工作節點相同數量的 Pod。

**注意:**當您將 Pod 繫結至 hostPort 時,可以排程 Pod 的位置數量有限。

下列範例顯示處於待定狀態的 Pod (frontend-port-77f67cff67-2bv7w) 的 describe 命令的輸出。由於叢集中的工作節點無法使用請求的主機連接埠,因此未排程 Pod:

$ kubectl describe pod frontend-port-77f67cff67-2bv7w
Name:           frontend-port-77f67cff67-2bv7w
...
Status:         Pending
IP:
IPs:            <none>
Controlled By:  ReplicaSet/frontend-port-77f67cff67
Containers:
  app:
    Image:      nginx
    Port:       80/TCP
    Host Port:  80/TCP
...
Events:
  Type     Reason            Age                  From               Message
  ----     ------            ----                 ----               -------
  Warning  FailedScheduling  11s (x7 over 6m22s)  default-scheduler  0/3 nodes are available: 3 node(s) didn't have free ports for the requested pod ports.

如果因為節點存在 Pod 不允許的污點而無法排程 Pod,則範例輸出類似於以下內容:

$ kubectl describe pod nginx
Name:         nginx
...
Status:       Pending
...
Events:
  Type     Reason            Age                  From               Message
  ----     ------            ----                 ----               -------
  Warning  FailedScheduling  8s (x10 over 9m22s)  default-scheduler  0/3 nodes are available: 3 node(s) had taint {key1: value1}, that the pod didn't tolerate.

若要檢查節點污點,請執行下列命令:

$ kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints

若要保留節點污點,請在 PodSpec 中指定 Pod 的容差。如需詳細資訊,請參閱 Kubernetes 網站上的概念。或者,在污點值的結尾處附加 -,以刪除節點污點:

$ kubectl taint nodes NODE_Name key1=value1:NoSchedule-

如果 Pod 仍處於待定狀態,請完成其他疑難排解區段中的步驟。

您的容器處於「等待中」狀態

您的容器可能因 Docker 映像檔不正確或儲存庫名稱不正確,而處於等待中狀態。或者,您的 Pod 可能因映像不存在或缺少許可,而處於等待中狀態。

若要確認映像和儲存庫名稱是否正確,請登入 Docker Hub、Amazon Elastic Container Registry (Amazon ECR) 或其他容器映像儲存庫。將儲存庫或儲存庫中的映像,與 Pod 規格中指定的儲存庫或映像名稱進行比較。如果映像不存在或缺少許可,請完成下列步驟:

  1. 確認指定的映像在儲存庫中可用,以及已設定正確許可以允許您提取映像。

  2. 若要確認您可以提取映像,並排除一般的網路和儲存庫許可問題,請手動提取映像。您必須使用 Docker 從 Amazon EKS 工作節點提取映像:

    $ docker pull yourImageURI:yourImageTag
  3. 若要確認映像存在,請檢查映像和標籤是否都位於 Docker Hub 或 Amazon ECR 中。

注意:如果您使用 Amazon ECR,請確認儲存庫政策允許為 NodeInstanceRole 提取映像。或者,請確認 AmazonEC2ContainerRegistryReadOnly 已附加至此政策。
下列範例顯示處於
待定
狀態的 Pod,其容器因映像提取錯誤而處於等待中狀態:

$ kubectl describe po web-test

Name:               web-test
...
Status:             Pending
IP:                 192.168.1.143
Containers:
  web-test:
    Container ID:
    Image:          somerandomnonexistentimage
    Image ID:
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Waiting
      Reason:       ErrImagePull
...
Events:
  Type     Reason            Age                 From  Message
  ----     ------            ----                ----                                                 -------
  Normal   Scheduled         66s                 default-scheduler                                    Successfully assigned default/web-test to ip-192-168-6-51.us-east-2.compute.internal
  Normal   Pulling           14s (x3 over 65s)   kubelet, ip-192-168-6-51.us-east-2.compute.internal  Pulling image "somerandomnonexistentimage"
  Warning  Failed            14s (x3 over 55s)   kubelet, ip-192-168-6-51.us-east-2.compute.internal  Failed to pull image "somerandomnonexistentimage": rpc error: code = Unknown desc = Error response from daemon: pull access denied for somerandomnonexistentimage, repository does not exist or may require 'docker login'
  Warning  Failed            14s (x3 over 55s)   kubelet, ip-192-168-6-51.us-east-2.compute.internal  Error: ErrImagePull

如果您的容器仍處於等待中狀態,請完成其他疑難排解區段中的步驟。

您的 Pod 處於 CrashLoopBackOff 狀態

如果您收到 "Back-Off restarting failed container" 輸出訊息,則您的容器可能已在 Kubernetes 啟動容器後不久結束。

若要尋找目前 Pod 日誌中的錯誤,請執行下列命令:

$ kubectl logs YOUR_POD_NAME

若要尋找先前當機的 Pod 的日誌中的錯誤,請執行下列命令:

$ kubectl logs --previous YOUR-POD_NAME

對於多容器 Pod,請在結尾處附加容器名稱。例如:

$ kubectl logs [-f] [-p] (POD | TYPE/NAME) [-c CONTAINER]

如果活躍性探針沒有傳回成功狀態,請確認已為應用程式設定正確的活躍性探針。如需詳細資訊,請參閱 Kubernetes 網站上的設定探針

下列範例顯示因應用程式在啟動後結束,而處於 CrashLoopBackOff 狀態的 Pod:

$ kubectl describe pod crash-app-b9cf4587-66ftw
Name:         crash-app-b9cf4587-66ftw
...
Containers:
  alpine:
    Container ID:   containerd://a36709d9520db92d7f6d9ee02ab80125a384fee178f003ee0b0fcfec303c2e58
    Image:          alpine
    Image ID:       docker.io/library/alpine@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a
    Port:           <none>
    Host Port:      <none>
    State:          Waiting
      Reason:       CrashLoopBackOff
    Last State:     Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Tue, 12 Oct 2021 12:26:21 +1100
      Finished:     Tue, 12 Oct 2021 12:26:21 +1100
    Ready:          False
    Restart Count:  4
    ...
Events:
  Type     Reason     Age                  From               Message
  ----     ------     ----                 ----               -------
  Normal   Started    97s (x4 over 2m25s)  kubelet            Started container alpine
  Normal   Pulled     97s                  kubelet            Successfully pulled image "alpine" in 1.872870869s
  Warning  BackOff    69s (x7 over 2m21s)  kubelet            Back-off restarting failed container
  Normal   Pulling    55s (x5 over 2m30s)  kubelet            Pulling image "alpine"
  Normal   Pulled     53s                  kubelet            Successfully pulled image "alpine" in 1.858871422s

以下是 Pod 的活躍性探針失敗的範例:

$ kubectl describe pod nginx
Name:         nginx
...
Containers:
  nginx:
    Container ID:   containerd://950740197c425fa281c205a527a11867301b8ec7a0f2a12f5f49d8687a0ee911
    Image:          nginx
    Image ID:       docker.io/library/nginx@sha256:06e4235e95299b1d6d595c5ef4c41a9b12641f6683136c18394b858967cd1506
    Port:           80/TCP
    Host Port:      0/TCP
    State:
          Waiting      Reason:       CrashLoopBackOff
    Last State:     Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Tue, 12 Oct 2021 13:10:06 +1100
      Finished:     Tue, 12 Oct 2021 13:10:13 +1100
    Ready:          False
    Restart Count:  5
    Liveness:       http-get http://:8080/ delay=3s timeout=1s period=2s #success=1 #failure=3
    ...
Events:
  Type     Reason     Age                    From               Message
  ----     ------     ----                   ----               -------
  Normal   Pulled     2m25s                  kubelet            Successfully pulled image "nginx" in 1.876232575s
  Warning  Unhealthy  2m17s (x9 over 2m41s)  kubelet            Liveness probe failed: Get "http://192.168.79.220:8080/": dial tcp 192.168.79.220:8080: connect: connection refused
  Normal   Killing    2m17s (x3 over 2m37s)  kubelet            Container nginx failed liveness probe, will be restarted
  Normal   Pulling    2m17s (x4 over 2m46s)  kubelet            Pulling image "nginx"

如果 Pod 仍處於 CrashLoopBackOff 狀態,請完成其他疑難排解區段中的步驟。

Pod 處於「正在終止」狀態

如果 Pod 狀態卡在正在終止狀態,請檢查正在執行該 Pod 的節點和完成項的運作狀態。完成項是在 Pod 轉換為已終止前執行終止處理的函數。如需詳細資訊,請參閱 Kubernetes 網站上的完成項。若要檢查正在終止的 Pod 的完成項,請執行下列命令:

$ kubectl get po nginx -o yaml  

apiVersion: v1  
kind: Pod  
metadata:  
...  
  finalizers:  
  - sample/do-something  
...

在上述範例中,只有在完成項 sample/do-something 已移除後,Pod 才會轉換為已終止。通常,自訂控制器會處理該完成項,然後將其移除。然後,Pod 會轉換為已終止狀態。

若要解決此問題,請檢查自訂控制器的 Pod 是否正確執行。解決控制器 POD 的任何問題,並讓自訂控制器完成完成項處理程序。然後,Pod 會自動轉換為已終止狀態。或者,執行下列命令直接刪除完成項:

$ kubectl edit po nginx

其他疑難排解

如果您的 Pod 仍然卡住,請完成下列步驟:

  1. 若要確認工作節點位於叢集中且處於就緒狀態,請執行下列命令:

    $ kubectl get nodes

    如果節點狀態為 NotReady,請參閱如何將節點的狀態從 NotReady 或不明狀態變更為就緒狀態?如果節點無法加入叢集,請參閱如何讓我的工作節點加入 Amazon EKS 叢集?

  2. 若要檢查 Kubernetes 叢集版本,請執行下列命令:

    $ kubectl version --short
  3. 若要檢查 Kubernetes 工作節點版本,請執行下列命令:

    $ kubectl get node -o custom-columns=NAME:.metadata.name,VERSION:.status.nodeInfo.kubeletVersion
  4. 確認叢集的 Kubernetes 伺服器版本與可接受版本扭曲內的工作節點版本相符。如需詳細資訊,請參閱 Kubernetes 網站上的版本偏差政策
    **重要:**叢集和工作節點之間的修補程式版本可能有所不同,例如叢集為 v1.21.x,而工作節點為 v1.21.y。如果叢集和工作節點的版本不相容,請使用 eksctl 或 AWS CloudFormation 建立新節點群組。或者,使用相容的 Kubernetes 版本建立新受管節點群組,例如、Kubernetes:v1.21、平台:eks.1 及更高版本。然後,刪除包含不相容 Kubernetes 版本的節點群組。

  5. 確認 Kubernetes 控制平面可以與工作節點通訊。根據 Amazon EKS 安全群組需求和考量中的必要規則檢查防火牆規則。然後,確認節點處於就緒狀態。

AWS 官方
AWS 官方已更新 4 個月前