排解 GKE 中狀態為 NotReady 的節點問題

Google Kubernetes Engine (GKE) 中的 NotReady 狀態表示節點的 kubelet 未正確回報給控制層。由於 Kubernetes 不會在 NotReady 節點上排定新的 Pod,這個問題可能會降低應用程式容量並導致停機。

請參閱這份文件,區分預期 NotReady 狀態和實際問題,診斷根本原因,並找出常見問題的解決方法,例如資源耗盡、網路問題和容器執行階段失敗。

這項資訊適用於負責叢集穩定性的平台管理員和營運人員,以及想瞭解基礎架構相關應用程式行為的應用程式開發人員。如要進一步瞭解我們在 Google Cloud 內容中提及的常見角色和範例工作,請參閱「常見的 GKE 使用者角色和工作」。

事前準備

  • 如要取得執行本文中工作所需的權限,請要求管理員在 Google Cloud 專案中授予您下列 IAM 角色:

    如要進一步瞭解如何授予角色,請參閱「管理專案、資料夾和組織的存取權」。

    您或許也能透過自訂角色或其他預先定義的角色,取得必要權限。

  • 設定 kubectl 指令列工具,與 GKE 叢集通訊:

    gcloud container clusters get-credentials CLUSTER_NAME \
        --location LOCATION \
        --project PROJECT_ID
    

    更改下列內容:

    • CLUSTER_NAME:叢集名稱。
    • LOCATION:叢集的 Compute Engine 區域或可用區 (例如 us-central1us-central1-a)。
    • PROJECT_ID:您的 Google Cloud 專案 ID。

檢查節點的狀態和條件

如要確認節點是否處於 NotReady 狀態,並協助診斷根本原因,請按照下列步驟檢查節點的條件、事件、記錄和資源指標:

  1. 查看節點狀態。如要取得 IP 位址和核心版本等有助於診斷的詳細資料,請使用 -o wide 旗標:

    kubectl get nodes -o wide
    

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

    NAME                                STATUS     ROLES    AGE   VERSION               INTERNAL-IP  EXTERNAL-IP  OS-IMAGE                             KERNEL-VERSION   CONTAINER-RUNTIME
    gke-cluster-pool-1-node-abc1        Ready      <none>   94d   v1.32.3-gke.1785003   10.128.0.1   1.2.3.4      Container-Optimized OS from Google   6.6.72+          containerd://1.7.24
    gke-cluster-pool-1-node-def2        Ready      <none>   94d   v1.32.3-gke.1785003   10.128.0.2   5.6.7.8      Container-Optimized OS from Google   6.6.72+          containerd://1.7.24
    gke-cluster-pool-1-node-ghi3        NotReady   <none>   94d   v1.32.3-gke.1785003   10.128.0.3   9.10.11.12   Container-Optimized OS from Google   6.6.72+          containerd://1.7.24
    

    在輸出中,尋找「STATUS」欄中值為 NotReady 的節點,並記下這些節點的名稱。

  2. 如要查看特定節點的詳細資訊 (包括狀態、條件和近期 Kubernetes 事件),請按一下 NotReady 狀態:

    kubectl describe node NODE_NAME
    

    NODE_NAME 替換為狀態為 NotReady 的節點名稱。

    在輸出內容中,請著重查看 Conditions 區段,瞭解節點的健康狀態,並查看 Events 區段,瞭解近期問題的記錄。例如:

    Name:                   gke-cluster-pool-1-node-ghi3
    ...
    Conditions:
    Type                          Status    LastHeartbeatTime                 LastTransitionTime                Reason                   Message
    ----                          ------    -----------------                 ------------------                ------                   -------
    NetworkUnavailable            False     Wed, 01 Oct 2025 10:29:19 +0100   Wed, 01 Oct 2025 10:29:19 +0100   RouteCreated             RouteController created a route
    MemoryPressure                Unknown   Wed, 01 Oct 2025 10:31:06 +0100   Wed, 01 Oct 2025 10:31:51 +0100   NodeStatusUnknown        Kubelet stopped posting node status.
    DiskPressure                  Unknown   Wed, 01 Oct 2025 10:31:06 +0100   Wed, 01 Oct 2025 10:31:51 +0100   NodeStatusUnknown        Kubelet stopped posting node status.
    PIDPressure                   False     Wed, 01 Oct 2025 10:31:06 +0100   Wed, 01 Oct 2025 10:29:00 +0100   KubeletHasSufficientPID  kubelet has sufficient PID available
    Ready                         Unknown   Wed, 01 Oct 2025 10:31:06 +0100   Wed, 01 Oct 2025 10:31:51 +0100   NodeStatusUnknown        Kubelet stopped posting node status.
    Events:
    Type     Reason                   Age                  From                                   Message
    ----     ------                   ----                 ----                                   -------
    Normal   Starting                 32m                  kubelet, gke-cluster-pool-1-node-ghi3  Starting kubelet.
    Warning  PLEGIsNotHealthy         5m1s (x15 over 29m)  kubelet, gke-cluster-pool-1-node-ghi3  PLEG is not healthy: pleg was last seen active 5m1.123456789s ago; threshold is 3m0s
    Normal   NodeHasSufficientMemory  5m1s (x16 over 31m)  kubelet, gke-cluster-pool-1-node-ghi3  Node gke-cluster-pool-1-node-ghi3 status is now: NodeHasSufficientMemory
    

    Conditions 部分中,任何負面條件的狀態為 True,或 Ready 條件的狀態為 Unknown,都表示有問題。請密切注意這些情況的 ReasonMessage 欄位,因為這些欄位會說明問題的原因。

    以下說明各條件類型代表的意義:

    • KernelDeadlockTrue 如果節點的作業系統核心偵測到死結,這項嚴重錯誤可能會導致節點凍結。
    • FrequentUnregisterNetDevice:如果節點經常取消註冊網路裝置,可能是驅動程式或硬體有問題,請使用 True
    • NetworkUnavailableTrue 節點的網路設定不正確。
    • OutOfDisk:如果可用磁碟空間完全耗盡,則為 True。這種情況比 DiskPressure 嚴重。
    • MemoryPressure:如果節點記憶體不足,則為 True
    • DiskPressure:如果節點的磁碟空間不足,則為 True
    • PIDPressureTrue 如果節點發生程序 ID (PID) 耗盡問題。
    • Ready:指出節點是否正常運作,且可接受 Pod。
      • True (如果節點健康狀態良好)。
      • False 如果節點健康狀態不良,且不接受 Pod。
      • Unknown 如果節點控制器在寬限期內 (預設為 50 秒) 未收到節點的訊息,且節點狀態為不明。

    接著,請查看「Events」部分,其中提供節點的動作和觀察結果的依時間順序記錄。這條時間軸對於瞭解節點在變成 NotReady 之前發生的情況至關重要。尋找有助於找出原因的特定訊息,例如驅逐警告 (表示資源壓力)、健康檢查失敗,或節點生命週期事件 (例如因維修而封鎖)。

  3. 如要進一步瞭解節點為何處於 NotReady 狀態,請查看節點及其元件的記錄檔。

    1. 查看 kubelet 記錄的 NotReady 狀態。

      kubelet 是主要代理程式,負責向控制層回報節點狀態,因此最有可能在記錄中找到實際的 NotReady 訊息。這些記錄是診斷 Pod 生命週期事件、資源壓力狀況 (例如 MemoryPressureDiskPressure),以及節點與 Kubernetes 控制層連線問題的權威來源。

    2. 前往 Google Cloud 控制台的「Logs Explorer」頁面:

      前往 Logs Explorer

    3. 在查詢窗格中,輸入下列查詢:

      resource.type="k8s_node"
      resource.labels.node_name="NODE_NAME"
      resource.labels.cluster_name="CLUSTER_NAME"
      resource.labels.location="LOCATION"
      log_id("kubelet")
      textPayload=~"(?i)NotReady"
      

      更改下列內容:

      • NODE_NAME:您要調查的節點名稱。
      • CLUSTER_NAME:叢集名稱。
      • LOCATION:叢集的 Compute Engine 區域或可用區 (例如 us-central1us-central1-a)。
    4. 按一下「執行查詢」並查看結果。

    5. 如果 kubelet 記錄檔未顯示根本原因,請檢查 container-runtimenode-problem-detector 記錄檔。這些元件可能不會直接記錄 NotReady 狀態,但通常會記錄導致問題的根本原因 (例如執行階段失敗或核心恐慌)。

    6. 在記錄檔探索工具查詢窗格中,輸入下列查詢:

      resource.type="k8s_node"
      resource.labels.node_name="NODE_NAME"
      resource.labels.cluster_name="CLUSTER_NAME"
      resource.labels.location="LOCATION"
      log_id("COMPONENT_NAME")
      

      COMPONENT_NAME 替換為下列其中一個值:

      • container-runtime:執行階段 (containerd),負責完整的容器生命週期,包括提取映像檔和管理容器執行作業。查看記錄是排解容器例項化、執行階段服務錯誤或執行階段設定導致問題的必要步驟。container-runtime
      • node-problem-detector:這項公用程式會主動監控各種節點層級的問題,並向控制層回報。這些記錄對於找出可能導致節點不穩定的根本系統性問題至關重要,例如核心死結、檔案系統損毀或硬體故障,而其他 Kubernetes 元件可能無法擷取這些問題。
    7. 按一下「執行查詢」並查看結果。

  4. 使用 Metrics Explorer 尋找節點變成 NotReady 時的資源耗盡情況:

    1. 前往 Google Cloud 控制台的「Metrics Explorer」頁面:

      前往 Metrics Explorer

    2. 在 Metrics Explorer 中,檢查節點的基礎 Compute Engine 執行個體是否發生資源耗盡問題。著重於 CPU、記憶體和磁碟 I/O 指標。例如:

      • GKE 節點指標:從前置字串為 kubernetes.io/node/ 的指標開始,例如 kubernetes.io/node/cpu/allocatable_utilizationkubernetes.io/node/memory/allocatable_utilization。這些指標會顯示 Pod 使用的節點可用資源量。可用量不包含 Kubernetes 為系統負荷保留的資源。
      • 客體作業系統指標:如要查看節點作業系統內部的資料,請使用以 compute.googleapis.com/guest/ 為前置字元的指標,例如 compute.googleapis.com/guest/cpu/usagecompute.googleapis.com/guest/memory/bytes_used
      • 管理程序指標:如要從管理程序層級查看 VM 的效能,請使用以 compute.googleapis.com/instance/ 為前置字串的指標,例如 compute.googleapis.com/instance/cpu/utilization 或磁碟 I/O 指標 (如 compute.googleapis.com/instance/disk/read_bytes_count)。

      如要查看客層 OS 和管理程序指標,請依基礎 Compute Engine 執行個體名稱 (而非 Kubernetes 節點名稱) 進行篩選。如要找出節點的執行個體名稱,請執行 kubectl describe node NODE_NAME 指令,並在輸出內容中尋找 ProviderID 欄位。執行個體名稱是該值的最後一部分。例如:

      ...
      Spec:
      ProviderID: gce://my-gcp-project-123/us-central1-a/gke-my-cluster-default-pool-1234abcd-5678
      ...
      

      在本範例中,執行個體名稱為 gke-my-cluster-default-pool-1234abcd-5678

依據症狀找出原因

如果您發現特定徵狀,例如記錄訊息、節點條件或叢集事件,請參閱下表,瞭解疑難排解建議:

類別 症狀或記錄訊息 可能原因 疑難排解步驟
節點條件 NetworkUnavailable: True 節點至控制層的連線問題,或容器網路介面 (CNI) 外掛程式故障。 排解網路連線問題
MemoryPressure: True 節點記憶體不足。 排解節點資源不足的問題
DiskPressure: True 節點的磁碟空間不足。 排解節點資源不足的問題
PIDPressure: True 節點可用的程序 ID 不足。 排解節點資源不足的問題
事件和記錄訊息 PLEG is not healthy CPU/IO 使用率過高或 Pod 過多,導致 Kubelet 超載。 解決 PLEG 問題
Out of memory: Kill process
sys oom event
節點記憶體已完全用盡。 解決系統層級的 OOM 事件
leases.coordination.k8s.io...is forbidden kube-node-lease 命名空間終止作業停滯。 解決 kube-node-lease 命名空間的問題
Container runtime not ready
runtime is down
參照 /run/containerd/containerd.sockdocker.sock 時發生錯誤
Containerd 或 Docker 服務失敗或設定錯誤。 解決容器執行階段問題
Pod 卡在 Terminating
Kubelet 記錄顯示 DeadlineExceeded,表示要終止容器
containerd 記錄顯示重複的 Kill container 訊息
程序停滯在無法中斷的磁碟休眠 (D 狀態),通常與 I/O 相關。 解決處於 D 狀態的程序
叢集層級症狀 DaemonSet 推出作業完成後,多個節點發生故障。 DaemonSet 會干擾節點作業。 解決第三方 DaemonSet 造成的問題
compute.instances.preempted 稽核記錄。 系統已先占 Spot VM,這是預期行為。 確認節點搶占
kube-system Pod 卡在 Pending 狀態。 Admission webhook 會封鎖重要元件。 解決准入 Webhook 造成的問題
exceeded quota: gcp-critical-pods 配額設定有誤,導致系統 Pod 遭到封鎖。 解決資源配額導致的問題

檢查預期的 NotReady 事件

NotReady 狀態不一定表示有問題。如果正在執行節點集區升級等預定作業,或是使用特定類型的虛擬機器,這可能是預期行為。

確認節點生命週期作業

症狀

在特定生命週期事件期間,節點會暫時顯示 NotReady 狀態。

原因

在幾個常見的生命週期事件中,節點的狀態會暫時變成 NotReady。每當建立或重新建立節點時,就會發生這種情況,例如:

  • 節點集區升級:升級期間,系統會排空並取代每個節點。新升級的節點完成初始化並加入叢集前,狀態為 NotReady
  • 節點自動修復:當 GKE 替換故障節點時,替代節點在佈建期間會維持 NotReady 狀態。
  • 叢集自動調度資源功能擴充:新增節點時,節點會先處於 NotReady 狀態,完全佈建並加入叢集後才會變成 Ready 狀態。
  • 手動變更執行個體範本:套用範本變更時,GKE 會重新建立節點。新節點在啟動階段會處於 NotReady 狀態。

解決方法

節點應只會短暫處於 NotReady 狀態。如果狀態持續超過 10 分鐘,請調查其他原因。

確認節點搶占

如果節點是在Spot VM先占 VM 上執行,Compute Engine 可能會突然終止節點,以回收資源。這是這類短期虛擬機器的預期行為,並非錯誤。

症狀

如果出現下列徵兆,節點的 NotReady 狀態很可能是因為系統預期會搶占 Spot VM 而導致:

  • 節點在叢集自動配置器刪除並重新建立之前,意外進入 NotReady 狀態。
  • Cloud 稽核記錄會顯示基礎 VM 執行個體的 compute.instances.preempted 事件。

原因

節點是在 Spot VM 或先占 VM 執行個體上執行,而 Compute Engine 將這些運算資源回收用於其他工作。Spot VM 可能隨時遭到中斷,但通常會提前 30 秒傳送終止通知。

解決方法

請僅將 Spot VM 或先占 VM 用於容錯、無狀態或批次工作負載,這些工作負載的設計目的在於妥善處理頻繁終止作業。對於無法容許突然中斷的正式環境或具狀態工作負載,請使用標準隨選 VM 佈建節點集區。

排解節點資源不足問題

節點通常會因為缺少 CPU、記憶體或磁碟空間等必要資源而變成 NotReady。如果節點的這些資源不足,重要元件就無法正常運作,導致應用程式不穩定,節點也會沒有回應。下列各節將說明這些短缺情況的各種表現方式,從一般壓力狀況到更嚴重的全系統事件都有。

解決節點資源壓力問題

如果節點的 CPU、記憶體、磁碟空間或程序 ID (PID) 不足,無法執行工作負載,就會發生資源耗盡的情況。這個問題可能會導致狀態為「NotReady」。

症狀

如果觀察到下列節點條件和記錄,資源耗盡可能是節點處於 NotReady 狀態的原因:

  • kubectl describe node 指令的輸出內容中,您會看到 OutOfDiskMemoryPressureDiskPressurePIDPressure 等條件的狀態為 True
  • kubelet 記錄檔可能包含記憶體不足 (OOM) 事件,表示系統的 OOM Killer 已遭叫用。

原因

節點上的工作負載集體要求的資源超出節點可提供的資源。

解決方法

如果是 Standard 叢集,請嘗試下列解決方案:

如果是 Autopilot 叢集,您無法直接控管節點機型或開機磁碟大小。系統會根據 Pod 要求自動管理節點容量。請確認工作負載資源要求符合 Autopilot 限制,並準確反映應用程式需求。如果資源問題持續發生,可能表示需要最佳化 Pod 要求,或在極少數情況下,可能發生平台問題,需要 Cloud Customer Care 團隊協助。

解決系統層級的 OOM 事件

如果節點的總記憶體用盡,就會發生系統層級的記憶體不足 (OOM) 事件,導致 Linux 核心強制終止程序,以釋放資源。這類事件與容器層級的 OOM 事件不同,後者是指單一 Pod 超出記憶體限制。

症狀

如果發現下列徵兆,節點不穩定的原因很可能是系統層級的 OOM 事件:

  • 您會在節點的序列控制台記錄中看到 Out of memory: Kill process 訊息。
  • kubelet 記錄包含 oom_watcher 事件,表示 kubelet 已偵測到系統層級的 OOM 事件。
  • 各種程序意外終止,包括可能重要的系統精靈或工作負載 Pod,不一定是記憶體用量最高的程序。

原因

節點的整體記憶體已用盡。這個問題可能是因為系統服務發生錯誤、工作負載設定錯誤導致記憶體用量過高,或是節點太小,無法滿足所有執行中 Pod 的記憶體需求。

解決方法

如要解決系統層級的 OOM 事件,請診斷原因,然後減少記憶體需求或增加節點容量。詳情請參閱「排解 OOM 事件」。

解決 PLEG 問題

Pod 生命週期事件產生器 (PLEG) 是 kubelet 中的元件。並定期檢查節點上所有容器的狀態,然後將任何變更回報給 kubelet。

如果 PLEG 發生效能問題,就無法及時更新 kubelet,導致節點不穩定。

症狀

如果出現下列情況,表示 PLEG 可能無法正常運作:

  • 節點的 kubelet 記錄包含類似 PLEG is not healthy 的訊息。
  • 節點的狀態經常在 ReadyNotReady 之間變更。

原因

PLEG 問題通常是由效能問題所致,導致 kubelet 無法及時接收來自容器執行階段的更新。常見原因包括:

  • CPU 負載過高:節點的 CPU 飽和,導致 kubelet 和容器執行階段無法取得所需的處理效能。
  • I/O 節流:節點的開機磁碟正在執行大量 I/O 作業,這可能會導致所有磁碟相關工作變慢。
  • Pod 數量過多:單一節點上的 Pod 數量過多可能會讓 kubelet 和容器執行階段不堪負荷,導致資源爭用。

解決方法

如果是 Standard 叢集,請減少節點資源的負擔:

如果是 Autopilot 叢集,雖然您無法直接變更現有節點的大小或磁碟類型,但可以透過自訂 ComputeClass,影響工作負載執行的硬體。 這項功能可讓您在工作負載資訊清單中指定需求,例如 CPU 和記憶體的最低用量或特定機器系列,引導 Pod 的排程位置。

如果未使用 ComputeClass,請調整工作負載部署作業 (例如副本計數和資源要求或限制),並確保這些作業符合 Autopilot 限制。如果最佳化工作負載後,PLEG 問題仍持續發生,請與 Cloud Customer Care 團隊聯絡。

解決處於 D 狀態的程序

如果程序停滯在無法中斷的磁碟休眠 (D 狀態),節點可能會沒有回應。這個問題會導致 Pod 無法終止,並可能導致 containerd 等重要元件故障,進而出現 NotReady 狀態。

症狀

  • Pod (尤其是使用 NFS 等網路儲存空間的 Pod) 長時間處於 Terminating 狀態。
  • 嘗試停止容器時,Kubelet 記錄會顯示 DeadlineExceeded 錯誤。
  • 節點的序列埠記錄可能會顯示核心訊息,指出工作遭到封鎖超過 120 秒。hung tasks

原因

程序等待 I/O 作業完成時會進入 D 狀態,且無法中斷。常見原因包括:

  • 遠端檔案系統速度緩慢或沒有回應,例如設定錯誤或過度負載的 NFS 共用。
  • 節點本機磁碟的磁碟效能嚴重下降,或發生硬體 I/O 錯誤。

解決方法

如要解決 D 狀態程序的問題,請找出 I/O 來源,然後選取下列任一選項來清除狀態:

標準叢集

  1. 找出停滯的程序,並判斷該程序等待的項目

    1. 使用 SSH 連線至受影響的節點:

      gcloud compute ssh NODE_NAME \
          --zone ZONE \
          --project PROJECT_ID
      

      更改下列內容:

      • NODE_NAME:要連線的節點名稱。
      • ZONE:節點的 Compute Engine 可用區。
      • PROJECT_ID:您的專案 ID。
    2. 找出 D 狀態的任何程序:

      ps -eo state,pid,comm,wchan | grep '^D'
      

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

      D  12345  my-app      nfs_wait
      D  54321  data-writer io_schedule
      

      輸出內容不會有標題。各欄依序代表:

      • 狀態
      • 程序 ID (PID)
      • 指令
      • 等待通道 (wchan)
    3. 檢查 wchan 欄,找出 I/O 來源:

      • 如果 wchan 欄包含 nfsrpc 等字詞,表示程序正在等待 NFS 共用區。
      • 如果 wchan 欄包含 io_schedulejbd2ext4 等字詞,表示程序正在等待節點的本機開機磁碟。
    4. 如要進一步瞭解程序等待的哪些核心函式,請檢查程序的核心呼叫堆疊:

      cat /proc/PID/stack
      

      PID 替換為您在上一個步驟中找到的程序 ID。

  2. 重新啟動節點。重新啟動通常是清除 D 狀態程序最有效的方法。

    1. 清空節點
    2. 刪除基礎 VM 執行個體。 GKE 通常會建立新的 VM 來取代。
  3. 解決當下問題後,請調查底層儲存系統,避免問題再次發生。

    • 網路儲存空間 (NFS) 問題:使用儲存空間供應商的監控工具,檢查 GKE 節點與 NFS 伺服器之間是否有高延遲、伺服器端錯誤或網路問題。

    • 本機磁碟問題:在 Cloud Monitoring 中查看 Compute Engine 執行個體的 compute.googleapis.com/instance/disk/throttled_read_ops_countcompute.googleapis.com/instance/disk/throttled_write_ops_count 指標,確認是否有 I/O 節流。

Autopilot 叢集

  1. 嘗試找出封鎖來源

    您無法在 Autopilot 叢集中直接透過 SSH 存取節點,也無法執行 pscat /proc 等指令。您必須依據記錄和指標。

    1. 檢查節點記錄:在 Cloud Logging 中,分析受影響節點的記錄。依節點名稱和問題時間範圍篩選。尋找指出 I/O 錯誤、儲存空間逾時 (例如磁碟或 NFS) 或 CSI 驅動程式訊息的核心訊息。
    2. 檢查工作負載記錄:檢查在受影響節點上執行的 Pod 記錄。應用程式記錄檔可能會顯示與檔案作業、資料庫呼叫或網路儲存空間存取權相關的錯誤。
    3. 使用 Cloud Monitoring:雖然無法取得程序層級的詳細資料,但可以檢查節點層級的 I/O 問題。
  2. 觸發節點更換作業,清除狀態。

    您無法手動刪除基礎 VM。如要觸發更換作業,請排空節點。這項操作會封鎖節點並逐出 Pod。

    GKE 會自動偵測健康狀態不良的節點,並啟動修復程序,通常是更換底層的 VM。

    如果節點在耗盡電力後仍無法運作,且系統未自動更換節點,請與 Cloud Customer Care 聯絡。

  3. 解決當下問題後,請調查底層儲存系統,避免問題再次發生。

    • 本機磁碟問題:查看 compute.googleapis.com/instance/disk/throttled_read_ops_countcompute.googleapis.com/instance/disk/throttled_write_ops_count 指標,確認 Cloud Monitoring 是否有 I/O 節流。您可以篩選節點集區基礎執行個體群組的這些指標,但個別執行個體是由 Google 管理。
    • 網路儲存空間 (NFS) 問題:使用儲存空間供應商的監控工具,檢查 GKE 節點與 NFS 伺服器之間是否有高延遲、伺服器端錯誤或網路問題。在 Cloud Logging 中檢查任何 CSI 驅動程式 Pod 的記錄。

排解核心元件故障問題

排除預期原因和資源不足後,問題可能出在節點的軟體或核心 Kubernetes 機制。如果容器執行階段等重要元件發生故障,就會出現 NotReady 狀態。如果核心 Kubernetes 健康狀態檢查機制 (例如節點租用系統) 發生故障,也可能導致這種情況。

解決容器執行階段問題

容器執行階段 (例如 containerd) 的問題可能會導致 kubelet 無法在節點上啟動 Pod。

症狀

如果 kubelet 記錄中出現下列訊息,節點的 NotReady 狀態很可能是由容器執行階段問題所導致:

  • Container runtime not ready
  • Container runtime docker failed!
  • docker daemon exited
  • 連線至執行階段通訊端時發生錯誤 (例如 unix:///var/run/docker.sockunix:///run/containerd/containerd.sock)。

原因

容器執行階段無法正常運作、設定錯誤,或陷入重新啟動迴圈。

解決方法

如要解決容器執行階段問題,請按照下列步驟操作:

  1. 分析容器執行階段記錄檔

    1. 前往 Google Cloud 控制台的「Logs Explorer」頁面。

      前往 Logs Explorer

    2. 如要在受影響的節點上查看所有容器執行階段的警告和錯誤記錄,請在查詢窗格中輸入下列內容:

      resource.type="k8s_node"
      resource.labels.node_name="NODE_NAME"
      resource.labels.cluster_name="CLUSTER_NAME"
      resource.labels.location="LOCATION"
      log_id("container-runtime")
      severity>=WARNING
      

      更改下列內容:

      • NODE_NAME:您要調查的節點名稱。
      • CLUSTER_NAME:叢集名稱。
      • LOCATION:叢集的 Compute Engine 區域或可用區 (例如 us-central1us-central1-a)。
    3. 按一下「執行查詢」,然後查看輸出內容中的具體錯誤訊息,瞭解執行階段失敗的原因。Cloud Logging 的 containerd 記錄中出現 failed to load TOML 等訊息,通常表示檔案格式有誤。

    4. 如要確認執行階段是否陷入重新啟動迴圈,請執行查詢來搜尋啟動訊息。如果短時間內出現大量這類訊息,表示裝置經常重新啟動。

      resource.type="k8s_node"
      resource.labels.node_name="NODE_NAME"
      resource.labels.cluster_name="CLUSTER_NAME"
      resource.labels.location="LOCATION"
      log_id("container-runtime")
      ("starting containerd" OR "Containerd cri plugin version" OR "serving..."
      OR "loading plugin" OR "containerd successfully booted")
      

      如果服務經常重新啟動,通常表示有潛在問題,例如設定檔損毀或資源壓力過大,導致服務不斷異常終止。

  2. 檢查 containerd 設定是否有修改:設定有誤可能會導致容器執行階段失敗。您可以透過節點系統設定檔進行設定變更,也可以透過工作負載直接修改設定,但工作負載必須具備提升的權限。

    1. 判斷節點集區是否使用節點系統設定檔:

      gcloud container node-pools describe NODE_POOL_NAME \
          --cluster CLUSTER_NAME \
          --location LOCATION \
          --format="yaml(config.containerdConfig)"
      

      更改下列內容:

      • NODE_POOL_NAME:節點集區的名稱。
      • CLUSTER_NAME:叢集名稱。
      • LOCATION:叢集的 Compute Engine 區域或可用區。

      如果輸出內容顯示 containerdConfig 區段,表示 GKE 正在管理這些自訂設定。如要修改或還原設定,請按照「在 GKE 節點中自訂 containerd 設定」一文中的操作說明進行。

    2. 如果 GKE 管理的自訂項目未啟用,或您懷疑有其他變更,請找出可能直接修改節點檔案系統的工作負載。尋找具有提升權限的 DaemonSet (securityContext.privileged: true) 或 hostPath 磁碟區,例如裝載機密目錄 (如 /etc)。

      如要檢查設定,請以 YAML 格式列出所有 DaemonSet:

      kubectl get daemonsets --all-namespaces -o yaml
      

      查看輸出內容,並檢查任何可疑 DaemonSet 的記錄。

    3. 如果是標準叢集,請直接檢查設定檔。 在 Autopilot 叢集中,由於 Google 會管理執行階段設定,因此無法進行 SSH 存取和手動檢查檔案。如果持續發生執行階段問題,請向 Google Cloud Customer Care 團隊回報。

      如果使用標準叢集,請檢查檔案:

      1. 使用 SSH 連線至節點:

        gcloud compute ssh NODE_NAME \
            --zone ZONE \
            --project PROJECT_ID
        

        更改下列內容:

        • NODE_NAME:要連線的節點名稱。
        • ZONE:節點的 Compute Engine 可用區。
        • PROJECT_ID:您的專案 ID。
      2. 顯示 containerd 設定檔的內容:

        sudo cat /etc/containerd/config.toml
        
      3. 如要查看近期修改,請列出檔案詳細資料:

        ls -l /etc/containerd/config.toml
        
    4. 比較這個檔案的內容與您在上一個步驟中執行的 gcloud node-pools describe 指令所產生的 containerdConfig 輸出內容。/etc/containerd/config.toml 中不在 gcloud 輸出內容中的任何設定,都是未受管理的變更。

    5. 如要修正任何設定錯誤,請移除未透過節點系統設定套用的變更。

  3. 排解常見的執行階段問題:如需更多疑難排解步驟,請參閱「排解容器執行階段問題」。

解決 kube-node-lease 命名空間的問題

kube-node-lease 命名空間中的資源負責維護節點健康狀態。請勿刪除這個命名空間。嘗試刪除這個命名空間會導致命名空間停滯在 Terminating 狀態。如果 kube-node-lease 命名空間停滯在 Terminating 狀態,kubelet 就無法續約健康狀態檢查租約。這個問題會導致控制平面將節點視為不健全,進而造成叢集範圍的問題,節點會在 ReadyNotReady 狀態之間交替。

症狀

如果出現下列徵兆,則可能是 kube-node-lease 命名空間發生問題,導致叢集不穩定:

  • 每個節點上的 kubelet 記錄檔都會顯示類似下列內容的持續性錯誤:

    leases.coordination.k8s.io NODE_NAME is forbidden: unable to create new content in namespace kube-node-lease because it is being terminated
    
  • 叢集中的節點會不斷在 ReadyNotReady 狀態之間切換。

原因

管理節點心跳kube-node-lease 命名空間異常停滯在 Terminating 狀態。這項錯誤會導致 Kubernetes API 伺服器無法在命名空間中建立或修改物件。因此,kubelet 無法更新 Lease 物件,而這類物件對於向控制層發出存活信號至關重要。如果沒有這些狀態更新,控制層就無法確認節點是否正常運作,導致節點狀態在 ReadyNotReady 之間交替。

kube-node-lease 命名空間本身可能停滯在 Terminating 狀態的根本原因包括:

  • 具有終結器的資源:雖然系統 kube-node-lease 命名空間 (主要包含 Lease 物件) 較少出現這種情況,但其中的資源可能具有終結器。Kubernetes 終結器是金鑰,可發出訊號,指出控制器必須先執行清理工作,才能刪除資源。如果負責移除終結器的控制器運作不正常,資源就不會遭到刪除,命名空間刪除程序也會停止。
  • 匯總 API 服務狀況不佳或沒有回應:如果用於註冊匯總 API 伺服器的 APIService 物件連結至命名空間,且狀況不佳,命名空間終止作業可能會遭到封鎖。控制層可能會等待匯總 API 伺服器正常關閉或清除,但如果服務沒有回應,就不會發生這種情況。
  • 控制層或控制器問題:在極少數情況下,Kubernetes 控制層 (尤其是命名空間控制器) 內的錯誤或問題,可能會導致垃圾收集作業無法順利完成,進而無法刪除命名空間。

解決方法

請按照「排解命名空間停滯在終止狀態的問題」一文中的指引操作。

疑難排解網路連線

網路問題可能會導致節點無法與控制層通訊,或導致 CNI 外掛程式等重要元件無法運作,進而出現 NotReady 狀態。

症狀

如果出現下列徵兆,節點的 NotReady 狀態可能就是網路問題所致:

  • NetworkNotReady 條件為 True
  • 節點上的 Kubelet 記錄檔會顯示類似下列的錯誤:
    • connection timeout to the control plane IP address
    • network plugin not ready
    • CNI plugin not initialized
    • 嘗試連線至控制層 IP 位址時,會收到 connection refusedtimeout 訊息。
  • Pod (尤其是 kube-system 命名空間中的 Pod) 會停留在 ContainerCreating 狀態,並發生 NetworkPluginNotReady 等事件。

原因

網路相關症狀通常表示下列其中一個領域發生故障:

  • 連線問題:節點無法與 Kubernetes 控制層建立穩定的網路連線。
  • CNI 外掛程式失敗:負責設定 Pod 網路的 CNI 外掛程式未正確執行,或初始化失敗。
  • Webhook 問題:設定錯誤的許可控制 Webhook 可能會干擾 CNI 外掛程式相關資源,導致網路設定不正確。

解決方法

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

  1. 解決暫時性 NetworkNotReady 狀態:在新建立的節點上,短暫出現 NetworkNotReady 事件是正常現象。CNI 外掛程式和其他元件初始化時,這個狀態應會在幾分鐘內解決。 如果狀態仍未變更,請繼續執行下列步驟。

  2. 驗證節點到控制平面的連線能力和防火牆規則:確保節點和控制平面之間的網路路徑已開啟,且運作正常:

    1. 檢查防火牆規則:確認虛擬私有雲防火牆規則允許 GKE 節點與控制平面之間的必要流量。如要瞭解 GKE 節點與控制層通訊所需的規則,請參閱「自動建立的防火牆規則」一文。
    2. 測試連線:使用 Network Intelligence Center 中的連線測試,驗證節點內部 IP 位址與控制平面端點 IP 位址之間的網路路徑 (位於 443 連接埠)。Not Reachable 結果通常有助於找出封鎖通訊的防火牆規則或路由問題。
  3. 調查 CNI 外掛程式狀態和記錄:如果節點的網路尚未準備就緒,可能是 CNI 外掛程式發生錯誤。

    1. 檢查 CNI Pod 狀態:找出使用的 CNI 外掛程式 (例如 netdcalico-node),並檢查 kube-system 命名空間中 Pod 的狀態。您可以使用下列指令篩選特定節點:

      kubectl get pods \
          -n kube-system \
          -o wide \
          --field-selector spec.nodeName=NODE_NAME \
          | grep -E "netd|calico|anetd"
      
    2. 檢查 CNI Pod 記錄:如果 Pod 無法正常運作,請在 Cloud Logging 中檢查記錄,查看詳細的錯誤訊息。如要查詢特定節點上的 netd Pod,請使用類似下列的查詢:

      resource.type="k8s_container"
      resource.labels.cluster_name="CLUSTER_NAME"
      resource.labels.location="LOCATION"
      resource.labels.namespace_name="kube-system"
      labels."k8s-pod/app"="netd"
      resource.labels.node_name="NODE_NAME"
      severity>=WARNING
      
    3. 解決特定 CNI 錯誤

      • 如果記錄顯示 Failed to allocate IP address,表示 Pod IP 位址範圍可能已用盡。驗證 Pod IP 位址使用率,並檢查叢集的 CIDR 範圍。
      • 如果記錄檔顯示 NetworkPluginNotReadycni plugin not initialized,請確認節點的 CPU 和記憶體資源是否充足。你也可以嘗試刪除 CNI Pod 來重新啟動,讓 DaemonSet 重新建立該 Pod。
      • 如果您使用 GKE Dataplane V2,且記錄顯示 Cilium API client timeout exceeded,請重新啟動節點上的 anetd Pod。
    4. 檢查准入 Webhook 干擾情形:Webhook 故障可能會導致 CNI Pod 無法啟動,使節點處於 NetworkNotReady 狀態。

    5. 檢查 API 伺服器記錄:在 Cloud Logging 中查看 API 伺服器記錄,找出與 Webhook 呼叫相關的錯誤。如要判斷 Webhook 是否會封鎖 CNI 資源建立作業,請搜尋類似 failed calling webhook 的訊息。

      如果 Webhook 造成問題,您可能需要找出有問題的 ValidatingWebhookConfigurationMutatingWebhookConfiguration,並暫時停用,讓節點準備就緒。詳情請參閱「解決因准入 Webhook 造成的相關問題」。

排解叢集設定錯誤

以下各節將協助您稽核部分叢集範圍的設定,這些設定可能會干擾正常的節點作業。

解決因准入 Webhook 導致的問題

如果准入 Webhook 設定錯誤、無法使用或速度過慢,可能會封鎖重要 API 要求,導致必要元件無法啟動,或節點無法加入叢集。

症狀

如果發現下列徵兆,表示設定錯誤或無法使用的許可控制 Webhook 可能會封鎖重要的叢集作業:

  • Pod,尤其是在 kube-system 命名空間中 (例如 CNI 或儲存空間 Pod),會停留在 PendingTerminating 狀態。
  • 新節點無法加入叢集,通常會因逾時而顯示 NotReady 狀態。

原因

設定錯誤或沒有回應的准入 Webhook 可能會封鎖重要的叢集作業。

解決方法

檢查網路鉤子設定,確保設定具有彈性且範圍適當。如要避免服務中斷,請將非重要 Webhook 的 failurePolicy 欄位設為 Ignore。如果是重要 Webhook,請確保其支援服務具備高可用性,並使用 namespaceSelectorkube-system 命名空間從 Webhook 監控中排除,避免控制層發生死結。詳情請參閱「使用 Webhook 時確保控制層穩定性」。

解決資源配額造成的問題

kube-system 命名空間中計算錯誤的資源配額,可能會導致 GKE 無法建立重要的系統 Pod。由於網路 (CNI) 和 DNS 等元件遭到封鎖,這個問題可能會導致新節點無法順利加入叢集。

症狀

  • kube-system 命名空間中的重要 Pod (例如 netdkonnectivity-agentkube-dns) 處於 Pending 狀態。
  • 叢集記錄或 kubectl describe pod 輸出內容中的錯誤訊息會顯示類似 exceeded quota: gcp-critical-pods 的失敗情形。

原因

當 Kubernetes 資源配額控制器停止準確更新 ResourceQuota 物件中的使用次數時,就會發生這個問題。常見原因是第三方准入 Webhook 發生故障,導致控制器更新遭到封鎖,配額用量因此會比實際用量高出許多。

解決方法

  1. 由於有問題的 Webhook 最可能是根本原因,請按照「解決因准入 Webhook 造成的問題」一節的指引,找出並修正可能封鎖系統元件的 Webhook。修正 Webhook 後,配額問題通常就會自動解決。
  2. 確認配額記錄的使用量與實際執行的 Pod 數量不同步。這個步驟會確認 ResourceQuota 物件的計數是否不正確:

    1. 查看配額的預定用途:

      kubectl get resourcequota gcp-critical-pods -n kube-system -o yaml
      
    2. 檢查實際的 Pod 數量:

      kubectl get pods -n kube-system --no-headers | wc -l
      
  3. 如果 ResourceQuota 中的使用次數似乎不正確 (例如遠高於實際 Pod 數量),請刪除 gcp-critical-pods 物件。GKE 控制層的設計宗旨是自動重新建立這個物件,並提供正確的已對帳用量計數:

    kubectl delete resourcequota gcp-critical-pods -n kube-system
    
  4. 監控 kube-system 命名空間幾分鐘,確保物件重新建立,且待處理的 Pod 開始排程。

解決第三方 DaemonSet 造成的問題

新部署或更新的第三方 DaemonSet (通常用於安全性、監控或記錄),有時會導致節點不穩定。如果 DaemonSet 干擾節點的容器執行階段或網路,耗用過多系統資源,或進行非預期的系統修改,就可能發生這個問題。

症狀

如果出現下列徵兆,可能是因為最近部署或修改的第三方 DaemonSet 導致節點故障:

  • DaemonSet 部署或更新後不久,叢集中可能有多個節點進入 NotReady 狀態。
  • 受影響節點的 Kubelet 記錄檔會回報下列錯誤:
    • container runtime is down
    • Failed to create pod sandbox
    • 連線至容器執行階段通訊端時發生錯誤 (例如 /run/containerd/containerd.sock)。
  • Pod (包括系統 Pod 或 DaemonSet 自己的 Pod) 停留在 PodInitializingContainerCreating 狀態。
  • 應用程式的容器記錄顯示異常錯誤,例如 exec format error
  • 節點問題偵測工具可能會回報與執行階段健康狀態或資源壓力相關的狀況。

原因

第三方 DaemonSet 可能會因為下列原因影響節點穩定性:

  • 耗用過多 CPU、記憶體或磁碟 I/O,影響重要節點元件的效能。
  • 干擾容器執行階段的運作。
  • 與節點的網路設定或容器網路介面 (CNI) 外掛程式發生衝突。
  • 以非預期的方式變更系統設定或安全性政策。

解決方法

如要判斷 DaemonSet 是否為原因,請隔離並測試:

  1. 找出 DaemonSet:列出叢集中執行的所有 DaemonSet:

    kubectl get daemonsets --all-namespaces
    

    請密切注意不屬於預設 GKE 安裝項目的 DaemonSet。

    您通常可以透過下列方式找出這些 DaemonSet:

    • 命名空間:預設 GKE 元件通常會在 kube-system 命名空間中執行。其他命名空間中的 DaemonSet 可能是第三方或自訂項目。
    • 命名:預設 DaemonSet 的名稱通常是 gke-metrics-agentnetdcalico-node。第三方代理程式的名稱通常會反映產品。
  2. 關聯部署時間:檢查 NotReady 節點的出現時間是否與特定第三方 DaemonSet 的部署或更新時間一致。

  3. 在單一節點上測試

    1. 選擇一個受影響的節點。
    2. 封鎖並清空節點。
    3. 暫時禁止 DaemonSet 在這個節點上排定:
      • 套用臨時節點標籤,並在 DaemonSet 的資訊清單中設定節點相依性或反相依性。
      • 刪除該特定節點上的 DaemonSet Pod。
    4. 重新啟動節點的虛擬機器執行個體。
    5. 觀察節點是否會變成 Ready,並在 DaemonSet 未於節點上執行時保持穩定。如果重新導入 DaemonSet 後問題再次出現,可能就是造成問題的原因。
  4. 諮詢供應商:如果懷疑第三方代理程式是造成問題的原因,請參閱供應商的說明文件,瞭解已知的相容性問題,或在 GKE 上執行代理程式的最佳做法。如需進一步支援,請與軟體供應商聯絡。

確認節點已復原

套用可能的解決方案後,請按照下列步驟操作,確認節點已成功復原並穩定運作:

  1. 檢查節點狀態:

    kubectl get nodes -o wide
    

    在輸出內容中找出受影響的節點。Status 欄現在應顯示 Ready 值。套用修正措施後,狀態可能需要幾分鐘才會更新。如果狀態仍顯示 NotReady 或在不同狀態之間循環,表示問題尚未完全解決。

  2. 檢查節點的 Conditions 部分:

    kubectl describe node NODE_NAME
    

    Conditions 區段中,確認下列值:

    • Ready 條件的狀態為 True
    • 先前狀態為 True 的負面條件 (例如 MemoryPressureNetworkUnavailable),現在狀態為 False。這些情況的 ReasonMessage 欄位應指出問題已解決。
  3. 測試 Pod 排程。如果節點先前無法執行工作負載,請檢查是否已在節點上排定新的 Pod,以及現有 Pod 是否正常運作:

    kubectl get pods --all-namespaces -o wide --field-selector spec.nodeName=NODE_NAME
    

    節點上的 Pod 應處於 RunningCompleted 狀態。您不應看到 Pod 卡在 Pending 或其他錯誤狀態。

後續步驟