排解 Autopilot 叢集問題


本頁面說明如何解決 Google Kubernetes Engine (GKE) Autopilot 叢集的問題。

叢集問題

無法建立叢集:已註冊 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.iam.gserviceaccount.com

    如果服務帳戶已停用,輸出結果會與下列內容相似:

    disabled: true
    displayName: my-service-account
    email: my-service-account@my-project.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 可能無法排定

如果Google Cloud 專案中停用了序列埠記錄功能,就會發生下列問題。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. 請 Google Cloud 機構政策管理員移除含有 Autopilot 叢集的專案中的 compute.disableSerialPortLogging 限制
  2. 如果沒有強制執行這項限制的機構政策,請嘗試在專案中繼資料中啟用序列埠記錄功能。執行這項操作需要 compute.projects.setCommonInstanceMetadata IAM 權限

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

當工作負載要求的資源超出 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。

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

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

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

記錄中的錯誤訊息類似於下列內容:

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

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

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

工作負載問題

工作負載卡住,並顯示暫時儲存空間錯誤

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

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

kubectl describe CONTROLLER_TYPE/CONTROLLER_NAME

更改下列內容:

  • CONTROLLER_TYPE:工作負載控制器類型,例如 replicasetdaemonset。如需控制器類型清單,請參閱工作負載管理
  • 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:
        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
    

後續步驟