排解 Autopilot 叢集問題

如果 Google Kubernetes Engine (GKE) Autopilot 叢集發生問題,可能會影響應用程式的可用性和作業效率。這些問題可能會干擾應用程式的整個生命週期,從初始部署到負載下的資源調度都可能受到影響。

您可以透過這個頁面,診斷及解決 Autopilot 叢集特有的常見問題。瞭解如何排解叢集建立問題 (導致叢集無法佈建)、資源調度問題 (例如 out of resources 錯誤),以及工作負載特定問題 (例如暫時儲存空間錯誤或 Pod 卡在 Pending 狀態)。

應用程式開發人員需要確保應用程式順利部署及執行,而平台管理員和操作人員則負責 Autopilot 叢集的整體健康狀態和資源管理,因此這項資訊對他們來說非常重要。如要進一步瞭解 Cloud de Confiance by S3NS 內容中提及的常見角色和工作範例,請參閱「常見的 GKE 使用者角色和工作」。

叢集問題

無法建立叢集:已註冊 0 個節點

如果嘗試使用已停用或不具備必要權限的 IAM 服務帳戶建立 Autopilot 叢集,就會發生下列問題。叢集建立失敗,並顯示下列錯誤訊息:

All cluster resources were brought up, but: only 0 nodes out of 2 have registered.

如要解決這個問題,請按照下列步驟操作:

  1. 檢查預設 Compute Engine 服務帳戶或要使用的自訂 IAM 服務帳戶是否已停用:

    gcloud iam service-accounts describe SERVICE_ACCOUNT
    

    將 SERVICE_ACCOUNT 替換為服務帳戶電子郵件地址,例如 my-iam-account@my-first-project.s3ns.iam.gserviceaccount.com。

    如果服務帳戶已停用,輸出內容會類似如下:

    disabled: true
    displayName: my-service-account
    email: my-service-account@my-project.s3ns.iam.gserviceaccount.com
    ...
    
  2. 如果服務帳戶已停用,請啟用:

    gcloud iam service-accounts enable SERVICE_ACCOUNT
    

如果服務帳戶已啟用,但錯誤仍持續發生,請授予服務帳戶 GKE 所需的最低權限:

gcloud projects add-iam-policy-binding PROJECT_ID \
    --member "serviceAccount:SERVICE_ACCOUNT" \
    --role roles/container.defaultNodeServiceAccount

叢集節點數量為 0 時,命名空間卡在「Terminating」狀態

當叢集縮減至零個節點後,如果您刪除叢集中的命名空間,就會發生下列問題。metrics-server 元件沒有任何副本,因此無法接受命名空間刪除要求。

如要診斷這個問題,請執行下列指令:

kubectl describe ns/NAMESPACE_NAME

將 NAMESPACE_NAME 替換為命名空間名稱。

輸出內容如下:

Discovery failed for some groups, 1 failing: unable to retrieve the complete
list of server APIs: metrics.k8s.io/v1beta1: the server is currently unable to
handle the request

如要解決這個問題,請向上擴充任何工作負載,觸發 GKE 建立新節點。節點準備就緒後,命名空間刪除要求就會自動完成。GKE 刪除命名空間後,請縮減工作負載。

資源調度問題

無法向上擴充節點:Pod 可能無法排定

如果Cloud de Confiance by S3NS 專案停用序列埠記錄功能,就會發生下列問題。GKE Autopilot 叢集需要序列埠記錄功能,才能有效偵錯節點問題。如果停用序列埠記錄功能,Autopilot 就無法佈建節點來執行工作負載。

Kubernetes 事件記錄中的錯誤訊息大致如下:

LAST SEEN   TYPE      REASON          OBJECT                          MESSAGE
12s         Warning   FailedScaleUp   pod/pod-test-5b97f7c978-h9lvl   Node scale up in zones associated with this pod failed: Internal error. Pod is at risk of not being scheduled

序列埠記錄功能可能已在組織層級停用,這是因為組織政策強制執行 compute.disableSerialPortLogging 限制。您也可以在專案或虛擬機器 (VM) 執行個體層級停用序列埠記錄功能。

請按照下列步驟解決這個問題:

  1. 請要求 Cloud de Confiance by S3NS 組織政策管理員,在 Autopilot 叢集所在的專案中移除 compute.disableSerialPortLogging 限制。
  2. 如果沒有強制執行這項限制的組織政策,請嘗試在專案中繼資料中啟用序列埠記錄功能。這項操作需要 compute.projects.setCommonInstanceMetadata IAM 權限。

節點向上擴充失敗:Compute Engine 資源不足

如果工作負載要求的資源量,超過該 Compute Engine 區域或可用區的可用資源量,就會發生下列問題。Pod 可能會維持在 Pending 狀態。

  • 檢查 Pod 事件:

    kubectl events --for='pod/POD_NAME' --types=Warning
    

    將 RESOURCE_NAME 替換為待處理 Kubernetes 資源的名稱。例如 pod/example-pod。

    輸出結果會與下列內容相似:

    LAST SEEN         TYPE            REASON                  OBJECT                   Message
    19m               Warning         FailedScheduling        pod/example-pod          gke.io/optimize-utilization-scheduler  0/2 nodes are available: 2 node(s) didn't match Pod's node affinity/selector. preemption: 0/2 nodes are available: 2 Preemption is not helpful for scheduling.
    14m               Warning         FailedScheduling        pod/example-pod          gke.io/optimize-utilization-scheduler  0/2 nodes are available: 2 node(s) didn't match Pod's node affinity/selector. preemption: 0/2 nodes are available: 2 Preemption is not helpful for scheduling.
    12m (x2 over 18m) Warning         FailedScaleUp           cluster-autoscaler       Node scale up in zones us-central1-f associated with this pod failed: GCE out of resources. Pod is at risk of not being scheduled.
    34s (x3 over 17m) Warning         FailedScaleUp           cluster-autoscaler       Node scale up in zones us-central1-b associated with this pod failed: GCE out of resources. Pod is at risk of not being scheduled.
    

如要解決這個問題,請嘗試下列做法:

  • 在其他區域或可用區部署 Pod。如果 Pod 有可用區限制 (例如拓撲選取器),請盡可能移除限制。如需操作說明,請參閱「將 GKE Pod 放在特定可用區」。
  • 在其他區域建立叢集,然後重新部署。
  • 請改用其他運算類別。由較小型 Compute Engine 機型支援的運算類別,較可能有可用資源。舉例來說,Autopilot 的預設機型可用性最高。如需運算類別和對應機器類型的清單,請參閱「何時應使用特定運算類別」。
  • 如果您執行 GPU 工作負載,節點位置可能無法提供要求的 GPU。請嘗試在其他位置部署工作負載,或要求其他類型的 GPU。

為避免日後因資源可用性而發生擴充問題,請考慮採用下列方法:

  • 定義自訂 ComputeClass,並列出優先順序的備用機器系列,然後啟用主動遷移 (optimizeRulePriority: true)。這項設定可讓 GKE 在可用區運算容量不足時,自動佈建替代硬體,並在偏好的容量恢復時,將 Pod 遷移回來。
  • 使用 Kubernetes PriorityClasses,在叢集中持續佈建額外的運算容量。詳情請參閱「佈建額外運算資源,快速擴充 Pod」。
  • 搭配使用 Compute Engine 運算資源預留項目與 Performance ComputeClass 或加速 Pod。詳情請參閱「使用預留的可用區資源」。

節點無法向上擴充:Pod 可用區資源超出上限

如果 Autopilot 未在特定可用區為 Pod 佈建新節點,因為新節點會違反資源限制,就會發生下列問題。

記錄中的錯誤訊息大致如下:

    "napFailureReasons": [
            {
              "messageId": "no.scale.up.nap.pod.zonal.resources.exceeded",
              ...

這項錯誤是指 noScaleUp 事件,其中自動佈建節點功能並未針對可用區內的 Pod 佈建任何節點群組。

如果遇到這項錯誤,請確認下列事項:

工作負載排定在舊版機器系列上執行,或因儲存空間不相容而卡在 Pending 狀態

如果具狀態工作負載使用較舊的 Persistent Disk 磁碟區類型,例如標準永久磁碟 (pd-standard) 或 SSD 永久磁碟 (pd-ssd) 磁碟區,就會發生這個問題。這些磁碟區類型與 C3 或 E4 等較新的機器系列不相容。

這個問題會以兩種方式呈現:

  • 症狀 1:您預期在較新的一般用途機器系列 (例如 C3) 上執行的工作負載,會自動改為排定在 E2 節點上執行。
  • 症狀 2:Pod 明確要求較新的機器系列 (例如使用 nodeSelector 欄位或自訂 ComputeClass),但仍卡在 Pending 狀態。

根本原因

GKE Autopilot 會強制要求要求的儲存空間類型與節點機器系列相容。C3 和 E4 等較新的機器系列需要 Google Cloud Hyperdisk 儲存空間 (例如 hyperdisk-balanced 磁碟類型)。這些機器系列不支援舊版 Persistent Disk 磁碟區類型,例如標準永久磁碟 (pd-standard) 或 SSD 永久磁碟 (pd-ssd) 磁碟區。

  • 如未指定機器系列,GKE Autopilot 會自動將工作負載排定在 E2 節點上,因為 E2 節點支援這些 Persistent Disk 磁碟區類型。工作負載會自動從預設的新硬體改回舊硬體。
  • 如果您明確要求較新的機器系列 (例如 C3 或 E4),但附加較舊的永久磁碟磁碟區類型,例如標準永久磁碟 (pd-standard) 或 SSD 永久磁碟 (pd-ssd) 磁碟區,GKE Autopilot 就無法同時滿足這兩項要求。Pod 會卡在 Pending 狀態。

驗證

如要確認工作負載是否受到這項相容性限制影響,請按照下列步驟操作:

  1. 檢查 Pod 的磁碟區設定,確認是否使用舊版 Persistent Disk 磁碟區類型,例如標準永久磁碟 (pd-standard) 或 SSD 永久磁碟 (pd-ssd) 磁碟區。
  2. 如果 Pod 卡在 Pending 狀態,請查看叢集自動配置器可見度記錄。尋找類似下列的節點自動佈建 (NAP) 評估記錄:

    NAP: injected node groups for requirements...
    
  3. 查看 families="..." 清單的記錄訊息。請檢查清單中是否缺少較新的機器家族 (例如 e4 或 c3 識別碼)。缺少 ID 表示 GKE 在排程期間因儲存空間需求而篩除這些系列。e4 識別碼用於 E4 機器系列的內部記錄。

解析度

如要解決這個問題,請採取下列任一做法:

  • 使用 Hyperdisk 儲存空間:更新 StorageClass 或磁碟區定義,改用與新版機器系列相容的 Google Cloud Hyperdisk 儲存空間 (例如 hyperdisk-balanced 磁碟類型)。
  • 允許在舊系列上排程:如果必須使用舊版 Persistent Disk 磁碟區類型 (例如標準永久磁碟 (pd-standard) 或 SSD 永久磁碟 (pd-ssd) 磁碟區),請移除任何明確要求新版機器系列 (例如 nodeSelector 欄位或自訂 ComputeClass) 的設定。移除這些要求後,GKE Autopilot 就能在 E2 等相容節點上排定 Pod。

工作負載問題

工作負載因臨時儲存空間錯誤而卡住

在 GKE 1.28.6-gke.1317000 以上版本中,如果 Pod 暫時儲存空間要求超過 Autopilot 上限 10 GiB,GKE 就不會建立 Pod。

如要診斷這個問題,請說明工作負載控制器,例如 Deployment 或 Job:

kubectl describe CONTROLLER_TYPE/CONTROLLER_NAME

更改下列內容:

  • CONTROLLER_TYPE:工作負載控制器的類型,例如 replicaset 或 daemonset。如需控制器類型清單,請參閱「工作負載管理」。
  • CONTROLLER_NAME:卡住的工作負載名稱。

如果 Pod 因臨時儲存空間要求超過上限而未建立,輸出內容會與下列內容相似:

# lines omitted for clarity

Events:

{"[denied by autogke-pod-limit-constraints]":["Max ephemeral-storage requested by init containers for workload '' is higher than the Autopilot maximum of '10Gi'.","Total ephemeral-storage requested by containers for workload '' is higher than the Autopilot maximum of '10Gi'."]}

如要解決這個問題,請更新臨時儲存空間要求,確保工作負載容器和 Webhook 插入的容器要求的臨時儲存空間總量,小於或等於允許的上限。如要進一步瞭解工作負載設定的上限,請參閱「Autopilot 中的資源要求」。

Pod 卡在「Pending」狀態

如果您為 Pod 選取特定節點,但 Pod 和必須在節點上執行的 DaemonSet 中的資源要求總和,超過節點的最大可分配容量,Pod 可能會卡在 Pending 狀態。這可能會導致 Pod 進入 Pending 狀態,且仍未排定。

為避免這個問題,請評估已部署工作負載的大小,確保其在 Autopilot 支援的最大資源要求範圍內。

您也可以先排定 DaemonSet,再排定一般工作負載 Pod。

特定節點的工作負載效能持續不穩定

在 GKE 1.24 以上版本中,如果特定節點上的工作負載持續發生中斷、當機或類似的不穩定行為,您可以使用下列指令封鎖該節點,向 GKE 回報問題:

kubectl drain NODE_NAME --ignore-daemonsets

將 NODE_NAME 替換為有問題的節點名稱。您可以執行 kubectl get nodes 來找出節點名稱。

GKE 會執行下列動作:

  • 從節點中剔除現有工作負載,並停止在該節點上排定工作負載。
  • 自動在其他節點上重新建立由控制器 (例如 Deployment 或 StatefulSet) 管理的任何遭淘汰工作負載。
  • 終止節點上剩餘的所有工作負載,並在一段時間後修復或重新建立節點。
  • 如果您使用 Autopilot,GKE 會立即關閉並更換節點,並忽略任何已設定的 PodDisruptionBudget。

在空白叢集上排定 Pod 的時間超出預期

當您將工作負載部署至沒有其他工作負載的 Autopilot 叢集時,就會發生這個事件。Autopilot 叢集一開始沒有可用的節點,如果叢集是空的,則會縮減至零個節點,避免叢集中有未使用的運算資源。在沒有節點的叢集中部署工作負載,會觸發擴充事件。

如果遇到這種情況,表示 Autopilot 正常運作,您不需採取任何行動。新節點啟動後,工作負載就會正常部署。

檢查 Pod 是否正在等待新節點:

  1. 描述待處理的 Pod:

    kubectl describe pod POD_NAME
    

    將 POD_NAME 替換為待處理 Pod 的名稱。

  2. 查看輸出內容的 Events 部分。如果 Pod 正在等待新節點,輸出內容會與下列內容相似:

    Events:
      Type     Reason            Age   From                                   Message
      ----     ------            ----  ----                                   -------
      Warning  FailedScheduling  11s   gke.io/optimize-utilization-scheduler  no nodes available to schedule pods
      Normal   TriggeredScaleUp  4s    cluster-autoscaler                     pod triggered scale-up: [{https://www.googleapis.com/compute/v1/projects/example-project/zones/example-zone/instanceGroups/gk3-example-cluster-pool-2-9293c6db-grp 0->1 (max: 1000)} {https://www.googleapis.com/compute/v1/projects/example-project/zones/example-zone/instanceGroups/gk3-example-cluster-pool-2-d99371e7-grp 0->1 (max: 1000)}]
    

    TriggeredScaleUp 事件顯示叢集正在擴充,從零個節點增加到執行已部署工作負載所需的節點數量。

系統 Pod 無法在空白叢集上排程

當叢集中沒有任何工作負載執行時,就會發生這個事件,導致叢集縮減至零個節點。Autopilot 叢集一開始沒有可用的節點,如果叢集中沒有執行任何工作負載,則會縮減至零個節點。這種行為可盡量減少叢集中浪費的運算資源。

當叢集縮減至零個節點時,GKE 系統工作負載不會排程,並會維持在 Pending 狀態。這是預期行為,您不需要採取任何行動。下次將工作負載部署至叢集時,GKE 會擴充叢集,而待處理的系統 Pod 會在這些節點上執行。

如要檢查系統 Pod 是否因叢集空白而處於待處理狀態,請按照下列步驟操作:

  1. 檢查叢集是否有任何節點:

    kubectl get nodes
    

    輸出內容如下,表示叢集沒有節點:

    No resources found
    
  2. 檢查系統 Pod 的狀態:

    kubectl get pods --namespace=kube-system
    

    輸出結果會與下列內容相似:

    NAME                                                       READY   STATUS    RESTARTS   AGE
    antrea-controller-horizontal-autoscaler-6d97f7cf7c-ngfd2   0/1     Pending   0          9d
    egress-nat-controller-84bc985778-6jcwl                     0/1     Pending   0          9d
    event-exporter-gke-5c5b457d58-7njv7                        0/2     Pending   0          3d5h
    event-exporter-gke-6cd5c599c6-bn665                        0/2     Pending   0          9d
    konnectivity-agent-694b68fb7f-gws8j                        0/2     Pending   0          3d5h
    konnectivity-agent-7d659bf64d-lp4kt                        0/2     Pending   0          9d
    konnectivity-agent-7d659bf64d-rkrw2                        0/2     Pending   0          9d
    konnectivity-agent-autoscaler-5b6ff64fcd-wn7fw             0/1     Pending   0          9d
    konnectivity-agent-autoscaler-cc5bd5684-tgtwp              0/1     Pending   0          3d5h
    kube-dns-65ccc769cc-5q5q7                                  0/5     Pending   0          3d5h
    kube-dns-7f7cdb9b75-qkq4l                                  0/5     Pending   0          9d
    kube-dns-7f7cdb9b75-skrx4                                  0/5     Pending   0          9d
    kube-dns-autoscaler-6ffdbff798-vhvkg                       0/1     Pending   0          9d
    kube-dns-autoscaler-8b7698c76-mgcx8                        0/1     Pending   0          3d5h
    l7-default-backend-87b58b54c-x5q7f                         0/1     Pending   0          9d
    metrics-server-v1.31.0-769c5b4896-t5jjr                    0/1     Pending   0          9d
    
  3. 查看系統 Pod 處於 Pending 狀態的原因:

    kubectl describe pod --namespace=kube-system SYSTEM_POD_NAME
    

    將 SYSTEM_POD_NAME 替換為前一個指令輸出內容中的任何系統 Pod 名稱。

    輸出結果會與下列內容相似:

    ...
    Events:
    Type     Reason            Age                       From               Message
    ----     ------            ----                      ----               -------
    Warning  FailedScheduling  4m35s (x27935 over 3d5h)  default-scheduler  no nodes available to schedule pods
    ...
    

    在輸出內容中,FailedScheduling 事件的 Message 欄位中的 no nodes available to schedule pods 值表示系統 Pod 未排程,因為叢集是空的。

在 GKE Autopilot 叢集中,您無法存取基礎節點。因此,您必須從 Pod 內執行 tcpdump 公用程式,然後使用 kubectl cp 指令複製。如果您通常在 GKE Autopilot 叢集的 Pod 內執行 tcpdump 公用程式,可能會看到下列錯誤:

    tcpdump: eth0: You don't have permission to perform this capture on that device
    (socket: Operation not permitted)

這是因為 GKE Autopilot 預設會將安全性背景資訊套用至所有 Pod,捨棄 NET_RAW 功能,降低潛在安全漏洞的風險。例如:

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: tcpdump
  name: tcpdump
spec:
  containers:
  - image: nginx
    name: nginx
    resources:
      limits:
        cpu: 500m
        ephemeral-storage: 1Gi
        memory: 2Gi
      requests:
        cpu: 500m
        ephemeral-storage: 1Gi
        memory: 2Gi
    securityContext:
      capabilities:
        # This section drops NET_RAW to mitigate security vulnerabilities
        drop:
        - NET_RAW

如果工作負載需要 NET_RAW 功能,可以重新啟用:

  1. 在 Pod 的 YAML 規格 securityContext 部分新增 NET_RAW 功能:

    securityContext:
      capabilities:
        add:
        - NET_RAW
    
  2. 在 Pod 中執行 tcpdump:

    tcpdump port 53 -w packetcap.pcap
    tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
    
  3. 使用 kubectl cp 指令將檔案複製到本機電腦,以便進一步分析:

    kubectl cp POD_NAME:/PATH_TO_FILE/FILE_NAME/PATH_TO_FILE/FILE_NAME
    
  4. 使用 kubectl exec 執行 tcpdump 指令,擷取網路封包並重新導向輸出內容:

    kubectl exec -it POD_NAME -- bash -c "tcpdump port 53 -w -" > packet-new.pcap
    

NRI RunPodSandbox 失敗,導致 Pod 無法在節點上執行

在極少數情況下,預設、Balanced、Scale-Out、autopilot 和 autopilot-spot 運算類別中的 Autopilot 節點可能會進入某種狀態,導致系統 Pod (例如 anetd) 和指派給該節點的使用者 Pod 無法轉換為執行中狀態。如果 anetd 無法轉換為執行中狀態,則節點上的 Pod 網路會部分或完全中斷。只有在特定叢集控制層升級期間,才會觸發這個錯誤狀態。

如果發現這個問題,可以按照緩解特定節點上不可靠的工作負載效能程序,在特定節點上緩解這個問題。

為避免問題再次發生,請手動將叢集升級至下列其中一個 GKE 修補程式版本:

  • 1.35:所有修補程式版本
  • 1.34:1.34.1-gke.3899000 以上版本
  • 1.33:1.33.5-gke.2392000 以上版本

如果您懷疑節點處於這個錯誤狀態,可以按照下列步驟確認:

  1. 找出在疑似有問題的節點上執行的 efficiency-daemon Pod:

    DAEMON_POD_NAME=$(kubectl get pods \
      --namespace kube-system \
      --selector k8s-app=efficiency-daemon \
      --field-selector spec.nodeName=NODE_NAME \
      --output custom-columns=":metadata.name" \
      --no-headers)
    echo $DAEMON_POD_NAME
    

    如果節點上沒有 efficiency-daemon Pod,則節點不會受到這個特定問題的影響。

  2. 檢查 efficiency-daemon Pod 是否有特定錯誤:

    kubectl logs -n kube-system $DAEMON_POD_NAME | grep "connect: operation not permitted" | wc -l
    

    如果輸出內容大於 10,則節點很有可能受到這個問題影響。

如果指派給節點的 Pod 持續在 Pod 事件中顯示下列錯誤訊息,表示節點受到這個問題影響:Failed to create pod sandbox: rpc error: code = Unknown desc = NRI RunPodSandbox failed: rpc error: code = Unknown desc = internal error: reconciliation failed。

後續步驟