本頁說明如何解決 GKE 標準模式節點集區的問題。
節點集區建立問題
本節列出在標準叢集中建立新節點集區時可能會發生的問題,並提供修正建議。
問題:資源不足,無法建立節點集區
如果您在 Google Cloud 區域中建立節點集區時指定特定硬體,但該區域的可用硬體不足以滿足您的需求,就會發生下列問題。
如要驗證節點集區建立作業失敗是否是因為區域資源不足,請檢查記錄中是否有相關錯誤訊息。
前往 Google Cloud 控制台的「記錄檔探索工具」:
在「Query」(查詢) 欄位中,指定下列查詢:
log_id(cloudaudit.googleapis.com/activity) resource.labels.cluster_name="CLUSTER_NAME" protoPayload.status.message:("ZONE_RESOURCE_POOL_EXHAUSTED" OR "does not have enough resources available to fulfill the request" OR "resource pool exhausted" OR "does not exist in zone")
將
CLUSTER_NAME
替換為您的 GKE 叢集名稱。點選「執行查詢」
你可能會看到下列其中一則錯誤訊息:
resource pool exhausted
The zone does not have enough resources available to fulfill the request. Try a different zone, or try again later.
ZONE_RESOURCE_POOL_EXHAUSTED
ZONE_RESOURCE_POOL_EXHAUSTED_WITH_DETAILS
Machine type with name 'MACHINE_NAME' does not exist in zone 'ZONE_NAME'
如要解決這個問題,請嘗試下列建議:
- 確認所選 Google Cloud 區域或地區具備您需要的特定硬體。請使用 Compute Engine 可用性表,確認特定區域是否支援特定硬體。為節點選擇其他Google Cloud 區域或可用區,這些區域或可用區可能提供您需要的硬體。
- 使用較小的機型建立節點集區。增加節點集區中的節點數量,讓總運算容量維持不變。
- 使用 Compute Engine 容量預留功能預先預留資源。
- 如果系統能從要求數量中,佈建至少指定數量的節點,請使用下一節所述的盡力佈建功能,順利建立節點集區。
盡力佈建
對於特定硬體,您可以使用「盡量佈建」,這會告知 GKE,如果可以佈建至少指定數量的節點,就成功建立節點集區。GKE 會持續嘗試佈建其餘節點,以滿足原始要求。如要告知 GKE 使用盡量供應資源的機制,請使用下列指令:
gcloud container node-pools create NODE_POOL_NAME \
--cluster=CLUSTER_NAME \
--node-locations=ZONE1,ZONE2,... \
--machine-type=MACHINE_TYPE
--best-effort-provision \
--min-provision-nodes=MINIMUM_NODES
更改下列內容:
NODE_POOL_NAME
:新節點集區的名稱。ZONE1,ZONE2,...
:節點的 Compute Engine 區域。這些可用區必須支援所選硬體。MACHINE_TYPE
:節點的 Compute Engine 機器類型。例如:a2-highgpu-1g
。MINIMUM_NODES
:GKE 佈建節點並成功建立節點集區時,節點數量下限。如未填寫此欄位,則預設值為1
。
舉例來說,假設您需要在 us-central1-c
中使用 10 個節點,並附加 NVIDIA A100 40GB GPU。根據 GPU 地區和區域可用性表,這個區域支援 A100 GPU。如要避免因沒有 10 部 GPU 電腦而無法建立節點集區,請使用盡力佈建。
gcloud container node-pools create a100-nodes \
--cluster=ml-cluster \
--node-locations=us-central1-c \
--num-nodes=10 \
--machine-type=a2-highgpu-1g \
--accelerator=type=nvidia-tesla-a100,count=1 \
--best-effort-provision \
--min-provision-nodes=5
即使 us-central1-c
中只有五個 GPU 可用,GKE 仍會建立節點集區。隨著時間推移,GKE 會嘗試佈建更多節點,直到節點集區中有 10 個節點為止。
錯誤:執行個體不含「instance-template」中繼資料
如果節點集區無法升級、調度資源或執行節點自動修復作業,您可能會看到下列錯誤訊息:
Instance INSTANCE_NAME does not contain 'instance-template' metadata
這項錯誤表示 GKE 分配的 VM 執行個體中繼資料已損毀。如果自訂的自動化程序或指令碼嘗試新增執行個體中繼資料 (例如 block-project-ssh-keys
),但除了新增或更新值之外,還刪除現有中繼資料,通常就會發生這種情況。如要瞭解 VM 執行個體中繼資料,請參閱「設定自訂中繼資料」。
如果刪除任何重要中繼資料值 (包括 instance-template
、kube-labels
、kubelet-config
、kubeconfig
、cluster-name
、configure-sh
、cluster-uid
等),節點或整個節點集區可能會進入不穩定狀態,因為這些值對 GKE 作業至關重要。
如果執行個體中繼資料已損毀,建議您重新建立含有損毀 VM 執行個體的節點集區,藉此復原中繼資料。您必須在叢集中新增節點集區,並增加新節點集區的節點數量,同時限制並移除其他節點的節點。請參閱這篇文章的操作說明,瞭解如何在節點集區之間遷移工作負載。
如要瞭解是誰在何時編輯執行個體中繼資料,可以查看 Compute Engine 稽核記錄資訊,或使用記錄檔探索工具執行類似下列的搜尋查詢,找出相關記錄:
resource.type="gce_instance_group_manager"
protoPayload.methodName="v1.compute.instanceGroupManagers.setInstanceTemplate"
您可以在記錄中找到要求發起者的 IP 位址和使用者代理程式。例如:
requestMetadata: {
callerIp: "REDACTED"
callerSuppliedUserAgent: "google-api-go-client/0.5 GoogleContainerEngine/v1"
}
在節點集區之間遷移工作負載
請按照下列操作說明,將工作負載從一個節點集區遷移至另一個節點集區。如要變更節點集區中節點的機器屬性,請參閱變更節點機器屬性以垂直擴充。
瞭解如何將 Pod 遷移至新的節點集區
如要將 Pod 遷移至新的節點集區,請執行下列步驟:
隔離現有節點集區中的節點:此作業會將現有節點集區中的節點標示為「不可排程」。當節點被標示為「不可排程」時,Kubernetes 即會停止將新 Pod 排入這些節點中。
清空現有節點集區中的節點:此作業會正常清空在現有節點集區的節點上執行的工作負載。
針對每個節點個別執行這些步驟,可讓現有節點集區中執行的 Pod 正常終止。Kubernetes 會將 Pod 重新排程到其他可用的節點上。
為確保 Kubernetes 會正常終止您的應用程式,您的容器需處理 SIGTERM 信號。使用這種方法可關閉連到用戶端的作用中連線,並乾淨地執行或回滾資料庫交易。在 Pod 資訊清單中,您可以使用 spec.terminationGracePeriodSeconds
欄位,指定 Kubernetes 在停止 Pod 中的容器之前必須等待的時間長度。預設為 30 秒。請參閱 Kubernetes 說明文件,進一步瞭解 Pod 終止。
您可以使用 kubectl cordon
和 kubectl drain
指令,封鎖及排空節點。
建立節點集區並遷移工作負載
如要將工作負載遷移至新的節點集區,請建立新的節點集區,然後封鎖並清空現有節點集區中的節點:
-
執行下列指令,確認已建立新的節點集區:
gcloud container node-pools list --cluster CLUSTER_NAME
如要停用現有節點集區的自動調度資源功能 (如果已啟用),請執行下列指令:
gcloud container clusters update CLUSTER_NAME --region=CLUSTER_REGION \ --no-enable-autoscaling \ --node-pool=EXISTING_NODE_POOL_NAME
執行下列指令,查看 Pod 目前在哪個節點上執行 (請見
NODE
欄):kubectl get pods -o=wide
取得現有節點集區中的節點清單,並將
EXISTING_NODE_POOL_NAME
取代為名稱:kubectl get nodes -l cloud.google.com/gke-nodepool=EXISTING_NODE_POOL_NAME
執行
kubectl cordon NODE
指令 (將NODE
替換為上一個指令中的名稱)。以下殼層指令會查看現有節點集區中的每個節點,並將節點標示為不可排程:for node in $(kubectl get nodes -l cloud.google.com/gke-nodepool=EXISTING_NODE_POOL_NAME -o=name); do kubectl cordon "$node"; done
(選用) 更新在現有節點集區上執行的工作負載,為標籤
cloud.google.com/gke-nodepool:NEW_NODE_POOL_NAME
新增 nodeSelector,其中NEW_NODE_POOL_NAME
是新節點集區的名稱。這樣可確保 GKE 將這些工作負載放置在新節點集區的節點上。清空每個節點,方法是在 10 秒的終止寬限期後移除所有 Pod:
for node in $(kubectl get nodes -l cloud.google.com/gke-nodepool=EXISTING_NODE_POOL_NAME -o=name); do kubectl drain --force --ignore-daemonsets --delete-emptydir-data --grace-period=GRACEFUL_TERMINATION_SECONDS "$node"; done
將
GRACEFUL_TERMINATION_PERIOD_SECONDS
替換為正常終止所需的時長。執行下列指令,確認現有節點集區中的節點在節點清單中處於
SchedulingDisabled
狀態:kubectl get nodes
此外,您應該會看到 Pod 現在已在新節點集區的節點上執行:
kubectl get pods -o=wide
如不需要現有的節點集區,請刪除:
gcloud container node-pools delete default-pool --cluster CLUSTER_NAME
後續步驟
如果無法在說明文件中找到問題的解決方法,請參閱「取得支援」一文,尋求進一步的協助, 包括下列主題的建議:
- 與 Cloud 客戶服務聯絡,建立支援案件。
- 在 StackOverflow 上提問,並使用
google-kubernetes-engine
標記搜尋類似問題,向社群尋求支援。你也可以加入#kubernetes-engine
Slack 頻道,取得更多社群支援。 - 使用公開問題追蹤工具回報錯誤或提出功能要求。