本頁說明如何找出及排解 Google Distributed Cloud 環境中的資源爭用問題。
總覽
有時 Google Distributed Cloud 可能會發生資源爭用情形,導致容器速度變慢、效能不佳或遭到終止。這可能是因為容器的 CPU 或記憶體用量過高。
CPU 和記憶體管理機制
CPU:
- 系統會根據 Pod 中容器指定的 CPU 要求,將 Pod 排程至節點。
- Pod 中的容器使用的 CPU 數量不得超過容器指定的限制
- 容器的 CPU 使用量受到 CPU 限制的節流。
- 如果節點層級的 CPU 使用率受到節流,系統會自動為容器指派與要求成比例的 CPU 週期。
進一步瞭解如何排定資源要求 Pod 的時間。
記憶體使用量:
- 系統會根據 Pod 中容器指定的記憶體要求,將 Pod 排定至節點。
- 容器使用的記憶體不得超過容器指定的上限。
- 如果未指定記憶體限制,容器可能會耗用節點上的所有可用記憶體。系統可能會觸發 OOM-Killer (記憶體不足終止工具),並逐出低優先順序的 Pod。
如要瞭解詳情,請參考下列資源:
問題
容器速度變慢
CPU 爭用問題可能會導致容器速度變慢。可能原因如下:
容器的 CPU 使用率偏高:
如果容器未取得與 CPU 要求成比例的 CPU 週期,或是 CPU 要求設定低於容器需求,容器可能會變慢。因此請檢查容器的 CPU 限制與 CPU 使用率比率。
在 Google Cloud 控制台 >「監控」 >「指標探索工具」的 MQL 編輯器中,執行下列查詢:
fetch k8s_container
| metric 'kubernetes.io/anthos/container/cpu/limit_utilization'
| group_by 1m, [value_limit_utilization_mean: mean(value.limit_utilization)]
| filter resource.cluster_name == 'CLUSTER_NAME'
| filter resource.container_name == 'CONTAINER_NAME'
| filter resource.pod_name == 'POD_NAME'
| filter resource.namespace_name == 'NAMESPACE_NAME'
| every 1m
然後執行下列其中一項操作:
- 如果這個比率偏高 (>=0.8),表示容器的 CPU 限制偏低,Kubernetes 會節流容器的 CPU 週期,讓 CPU 使用率維持在限制範圍內。如要解決這個問題,請提高容器的 CPU 限制。
- 如果這個比率不高 (低於 0.8),請檢查節點的 CPU 使用率是否偏高。
節點的 CPU 使用率偏高
如果 Pod 中任何個別容器的 CPU 限制與使用率比率不高,可能是節點沒有足夠的 CPU 週期可分配給節點上執行的容器集。因此,請按照下列步驟檢查節點上實際 CPU 用量與可分配 CPU 的比率:
取得運作緩慢的 Pod 節點:
kubectl get pod –kubeconfig CLUSTER_KUBECONFIG --namespace NAMESPACE POD --output wide
在 Google Cloud 控制台 >「監控」 >「指標探索工具」的 MQL 編輯器中,執行下列查詢:
fetch k8s_node | metric 'kubernetes.io/anthos/node/cpu/allocatable_utilization' | group_by 1m, [value_allocatable_utilization_mean: mean(value.allocatable_utilization)] | filter resource.cluster_name == 'CLUSTER_NAME' | filter resource.node_name == 'NODE_NAME' | every 1m
如果這個比率偏高 (>=0.8),表示節點的 CPU 週期不足,且超額訂閱。因此請按照下列步驟檢查該節點上所有其他 Pod 的 CPU 使用率,並調查是否有其他容器使用更多 CPU。
- 取得節點上的所有 Pod:
kubectl get pods --all-namespaces -o wide --field-selector spec.nodeName=NODE_NAME
- 檢查每個容器的 CPU 使用率:
fetch k8s_container | metric 'kubernetes.io/anthos/container/cpu/limit_utilization' | group_by 1m, [value_limit_utilization_mean: mean(value.limit_utilization)] | filter resource.cluster_name == 'CLUSTER_NAME' | filter resource.container_name == 'CONTAINER_NAME' | filter resource.pod_name == 'POD_NAME' | filter resource.namespace_name == 'NAMESPACE_NAME' | every 1m
如果節點上有其他容器使用大量 CPU,請提高運作緩慢容器的 CPU 要求和限制。這會在另一個節點上重新建立 Pod,以取得所需的 CPU 週期。
如果速度緩慢的是系統 Pod,請與 Google 支援團隊聯絡。
vSphere 層級的 CPU 超額預訂
如果節點或 Pod 的 CPU 耗用量不高,但容器仍緩慢,則 VM 可能在 vSphere 層級過度訂閱。因此節點無法從基礎虛擬化取得預期的 CPU 週期。
請按照這些步驟檢查 VM 是否過度訂閱。如果系統偵測到超額訂閱,請嘗試下列做法:
- 將部分 VM 移至其他主機。
- 評估並減少主機上每個 VM 的 vCPU 數量。
- 為叢集 VM 分配更多資源。
- 增加容器的 CPU 要求和限制。這會在另一個節點上重新建立 Pod,以取得所需的 CPU 週期。
Pod 因記憶體不足而遭終止
Pod 可能會因記憶體洩漏或容器的記憶體要求和限制設定不當而遭到 OOMKilled。可能原因如下:
容器記憶體用量偏高
如果 Pod 中的任何容器過度耗用分配到的總記憶體,Pod 就可能會遭到 OOM 終止。因此請檢查容器的記憶體要求與記憶體限制比例。
在 Google Cloud 控制台 >「監控」 >「指標探索工具」的 MQL 編輯器中,執行下列查詢:
fetch k8s_container
| metric 'kubernetes.io/anthos/container/memory/limit_utilization'
| filter (metric.memory_type == 'non-evictable')
| group_by 1m, [value_limit_utilization_mean: mean(value.limit_utilization)]
| filter resource.cluster_name == 'CLUSTER_NAME'
| filter resource.container_name == 'CONTAINER_NAME'
| filter resource.pod_name == 'POD_NAME'
| filter resource.namespace_name == 'NAMESPACE_NAME'
| every 1m
然後執行下列其中一項操作:
- 如果這個比率很高 (大於或等於 0.8),請提高容器的記憶體限制。
- 如果這個比率不高 (低於 0.8),請檢查節點的記憶體用量是否偏高。
節點的記憶體用量偏高
如果節點上所有 Pod 的記憶體用量超過可用記憶體,Pod 就可能遭到 OOM 終止。因此請檢查節點上的 MemoryPressure
條件是否為 True
。
執行下列指令並檢查
Conditions
區段:kubectl describe nodes --kubeconfig CLUSTER_KUBECONFIG NODE-NAME
如果
MemoryPressure
條件為True
,請檢查節點的記憶體用量:fetch k8s_node | metric 'kubernetes.io/anthos/node/memory/allocatable_utilization' | filter (metric.memory_type == 'non-evictable') | group_by 1m, [value_allocatable_utilization_mean: mean(value.allocatable_utilization)] | filter resource.cluster_name == 'CLUSTER_NAME' | filter resource.node_name = 'NODE_NAME' | every 1m
如果這個比率偏高 (>= 0.8),表示節點沒有足夠的記憶體可分配給 Pod,可能是因為某些程序或其他 Pod 耗用大量記憶體。
在 Google Cloud 控制台 >「監控」 >「指標探索工具」的 MQL 編輯器中,執行下列查詢,檢查節點上容器的記憶體用量:
fetch k8s_node | metric 'kubernetes.io/anthos/container_memory_usage_bytes' | filter resource.cluster_name == 'CLUSTER_NAME' | filter resource.node_name == 'NODE_NAME' | group_by 1m, [value_container_memory_usage_bytes_mean: mean(value.container_memory_usage_bytes)] | every 1m
如有容器使用大量記憶體,請調查容器的運作情形,或視需要增加容器的記憶體要求。
如果系統 Pod 耗用大量記憶體,請與 Google 支援團隊聯絡。
此外,您可以在 Google Distributed Cloud 中啟用自動調度功能,根據工作負載需求自動擴大及縮小節點集區。
瞭解如何啟用自動調度器。
Etcd 問題
有時,VMware 中的 Anthos 叢集可能會因 etcd 伺服器問題而發生容器故障,您可能會觀察到下列情況:
重複的 API 伺服器記錄,格式如下:
etcdserver: request timed out
和etcdserver: leader changed
重複的 etcd 記錄,格式如下:
W | wal: sync duration of 2.466870869s, expected less than 1s
和W | etcdserver: read-only range request * took too long
可能原因如下:
CPU 節流
etcd 伺服器 Pod 和/或 etcd 伺器執行的節點上,CPU 可能受到節流,導致 etcd 伺服器速度緩慢。請參閱「容器變慢」一節中的步驟,檢查是否有任何 CPU 爭用問題。
如果偵測到 ectd 伺服器 Pod 或節點上的 CPU 爭用情形,請將 CPU 新增至使用者叢集的控制層節點。使用 gkectl update
編輯使用者叢集設定檔中的 cpus
欄位。
Etcd Pod OOMkilled
由於資源爭用問題,etcd Pod 可能會遭到 OOMkill。請參閱「Pod gets OOMkilled (Out of Memory-Killed)」一節中的步驟,檢查 etcd 伺服器 Pod 和/或 etcd 伺服器執行的節點是否有任何記憶體爭用問題。
如果偵測到 etcd Pod 的 OOMkill,請增加使用者叢集控制層節點可用的記憶體。使用 gkectl update
編輯使用者叢集設定檔中的 memoryMB
欄位。
磁碟速度緩慢
如果 etcd 伺服器 Pod 或節點的 CPU 或記憶體用量沒有問題,但基礎資料存放區速度緩慢或受到限制,etcd 可能就會變慢。
檢查是否有下列問題:
如要檢查 etcd 伺服器讀取/寫入基礎磁碟的時間是否過長,請按照下列步驟操作:
擷取 etcd 記錄:
kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG logs -n ETCD_POD_NAMESPACE ETCD_POD
請尋找下列模式的項目,判斷 etcd 從磁碟讀取資料是否耗時過長:
W | etcdserver: read-only range request "key:\"/registry/configmaps/default/clusterapi-vsphere-controller-manager-leader-election\" " with result "range_response_count:1 size:685" took too long (6.893127339s) to execute
如要偵測 etcd 是否花費過多時間寫入磁碟,請尋找下列模式的項目:
W | wal: sync duration of 2.466870869s, expected less than 1s
如果上述任一或兩個記錄模式經常出現在 etcd 記錄中,表示磁碟速度緩慢。然後檢查資料存放區和磁碟的效能。
如要查看 etcd 指標,請執行下列步驟:
擷取 etcd wal 同步延遲:
在 Google Cloud 控制台 >「監控」 >「指標探索工具」的 MQL 編輯器中,執行下列查詢:
fetch k8s_container::kubernetes.io/anthos/etcd_disk_wal_fsync_duration_seconds | every 1m | filter resource.cluster_name == 'CLUSTER_NAME' | filter resource.pod_name == 'POD_NAME' | filter resource.namespace_name == 'NAMESPACE_NAME' | percentile 99
擷取 etcd 寫入延遲時間:
在 Google Cloud 控制台 >「監控」 >「指標探索工具」的 MQL 編輯器中,執行下列查詢:
fetch k8s_container::kubernetes.io/anthos/etcd_disk_backend_commit_duration_seconds | every 1m | filter resource.cluster_name == 'CLUSTER_NAME' | filter resource.pod_name == 'POD_NAME' | filter resource.namespace_name == 'NAMESPACE_NAME' | percentile 99
如果
p99
持續超過 10 毫秒,且/或p99
持續超過 25 毫秒,表示磁碟速度緩慢。etcd_disk_wal_fsync_duration_seconds
etcd_disk_backend_commit_duration_seconds
然後檢查資料存放區和磁碟的效能。
VM 磁碟的讀取/寫入延遲時間
請按照下列步驟,檢查 VM 虛擬磁碟的讀取/寫入延遲時間
找出 etcd Pod 執行緩慢的節點:
kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG get pods -n ETCD_POD_NAMESPACE ETCD_POD -owide
登入 vSphere,然後選取上一步驟中識別的 VM: 在 vSphere 中,依序前往「監控」 >「效能」 >「進階」,然後從「檢視」部分選取「虛擬磁碟」,即可識別虛擬磁碟的讀取和寫入延遲時間。
如果虛擬磁碟讀寫延遲時間過長:
詳情請參閱「資源擴充最佳做法」。
API 伺服器問題
如果 Google Distributed Cloud 中的容器在與 API 伺服器通訊時發生延遲,或 Kubectl 指令失敗或回應時間過長,可能表示 API 伺服器有問題。
可能原因如下:
大量 API 要求
如果 API 伺服器上的要求頻率和數量過高,回應速度可能會變慢。即使 API 伺服器開始節流要求,回應時間緩慢的問題可能仍會持續。因此請檢查 API 伺服器上的 API 要求速率。
在 Google Cloud 控制台 >「監控」 >「指標探索工具」的 MQL 編輯器中,執行下列查詢:
fetch k8s_container::kubernetes.io/anthos/apiserver_request_total
| filter resource.cluster_name == 'CLUSTER_NAME'
| filter resource.pod_name == 'APISERVER_POD_NAME'
| filter resource.namespace_name == 'NAMESPACE_NAME'
| align rate(1m)
| every 1m
| group_by [metric.verb]
如果 API 要求意外增加,請使用 Cloud 稽核記錄找出可能過於頻繁查詢 API 伺服器的 Pod。
- 如果是系統 Pod,請與 Google 支援團隊聯絡。
- 如果是使用者 Pod,請進一步調查,判斷 API 要求是否符合預期。
CPU 節流
API 伺服器的要求頻率過高可能會導致 CPU 節流。接著,API 伺服器 Pod 和/或節點上的 CPU 爭用可能會導致 API 伺服器變慢。
請參閱「容器變慢」一節,檢查 Pod 和/或節點是否有任何 CPU 爭用問題。
API 伺服器 Pod OOMkilled
API 伺服器 Pod 可能會因資源爭用問題而遭到 OOMkill。請參閱「Pod 遭 OOMkilled (記憶體不足而終止) 」一節中的步驟,檢查 Pod 和/或節點是否有任何記憶體爭用問題。
etcd 回應速度緩慢
API 伺服器會與 etcd 叢集通訊,以便處理用戶端的讀取 / 寫入要求。如果 etcd 速度緩慢或沒有回應,API 伺服器也會變慢。
擷取 API 伺服器的記錄,檢查 API 伺服器是否因 etcd 問題而速度緩慢:
kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG logs -n APISERVER_NAMESPACE APISERVER_POD_NAME
如果觀察到重複記錄 (例如 etcdserver: request timedout
或 etcdserver: leader changed
),請按照「Etcd 問題」一文的步驟解決任何磁碟相關問題。
如果叢集未匯出指標
本文先前介紹的技術會將指標從叢集匯出至 Google Cloud 專案。
如果叢集未匯出指標,您可以使用指令列調查資源爭用情形。您可以在管理工作站上執行下列指令,查看指標。
查看節點的指標:
kubectl --kubeconfig CLUSTER_KUBECONFIG get --raw \ /apis/metrics.k8s.io/v1beta1/nodes/NODE_NAME | jq
更改下列內容:
- CLUSTER_KUBECONFIG:叢集 kubeconfig 檔案的路徑
- NODE_NAME:節點名稱
查看 Pod 的指標:
kubectl --kubeconfig CLUSTER_KUBECONFIG get --raw \ /apis/metrics.k8s.io/v1beta1/namespaces/NAMESPACE/pods/POD_NAME | jq
更改下列內容:
- NAMESPACE:Pod 的命名空間
- POD_NAME:Pod 的名稱
查看所有節點的指標:
kubectl --kubeconfig CLUSTER_KUBECONFIG top node
查看命名空間中所有 Pod 的指標:
kubectl --kubeconfig CLUSTER_KUBECONFIG top pod --namespace NAMESPACE
查看命名空間中所有 Pod 內容器的指標:
kubectl --kubeconfig CLUSTER_KUBECONFIG top pod --containers --namespace NAMESPACE
詳情請參閱 kubectl top pod 和 kubectl top node。
您也可以從節點上執行的容器內執行 top 指令。
在容器內執行指令的方法有兩種:
在管理員工作站上執行 kubectl exec,取得容器的殼層。在殼層中執行指令。
取得節點的 SSH 連線。 然後使用 docker exec 取得容器的殼層。在殼層中執行指令。
後續步驟
如需其他協助,請與 Cloud Customer Care 團隊聯絡。
如要進一步瞭解支援資源,包括下列項目,請參閱「取得支援」: