本頁說明如何解決 Google Distributed Cloud 的 Kubernetes 排程器 (kube-scheduler
) 問題。
Kubernetes 一律會將 Pod 排程至同一組節點
這個錯誤可能會以幾種不同的方式呈現:
叢集使用率不平衡。您可以使用
kubectl top nodes
指令,檢查每個節點的叢集用量。以下誇大的範例輸出內容顯示特定節點的使用率明顯偏高:NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% XXX.gke.internal 222m 101% 3237Mi 61% YYY.gke.internal 91m 0% 2217Mi 0% ZZZ.gke.internal 512m 0% 8214Mi 0%
要求數量過多。如果您一次在同一個節點上排定大量 Pod,且這些 Pod 會發出 HTTP 要求,節點可能會受到速率限制。在這種情況下,伺服器通常會傳回
429 Too Many Requests
錯誤。服務無法使用。舉例來說,如果 Node 上的網路伺服器負載過高,可能會對所有要求傳回
503 Service Unavailable
錯誤,直到負載降低為止。
如要檢查是否有 Pod 一律排定在相同節點上,請按照下列步驟操作:
執行下列
kubectl
指令,查看 Pod 的狀態:kubectl get pods -o wide -n default
如要查看 Pod 在節點間的分布情形,請檢查輸出內容中的
NODE
欄。在下列範例輸出中,所有 Pod 都排定在同一個節點上:NAME READY STATUS RESTARTS AGE IP NODE nginx-deployment-84c6674589-cxp55 1/1 Running 0 55s 10.20.152.138 10.128.224.44 nginx-deployment-84c6674589-hzmnn 1/1 Running 0 55s 10.20.155.70 10.128.226.44 nginx-deployment-84c6674589-vq4l2 1/1 Running 0 55s 10.20.225.7 10.128.226.44
Pod 提供多項功能,可供您微調排程行為。這些功能包括拓撲擴散限制和反親和性規則。您可以擇一或任意搭配使用這些功能。您定義的要求會由 kube-scheduler
連結在一起。
在預設記錄細項等級下,系統不會擷取排程器記錄。如需排程器記錄檔進行疑難排解,請按照下列步驟擷取排程器記錄檔:
提高記錄詳細程度:
編輯
kube-scheduler
Deployment:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \ -n USER_CLUSTER_NAMESPACE
在
spec.containers.command
區段下方新增--v=5
標記:containers: - command: - kube-scheduler - --profiling=false - --kubeconfig=/etc/kubernetes/scheduler.conf - --leader-elect=true - --v=5
完成疑難排解後,請將詳細程度重設回預設層級:
編輯
kube-scheduler
Deployment:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \ -n USER_CLUSTER_NAMESPACE
將詳細程度設回預設值:
containers: - command: - kube-scheduler - --profiling=false - --kubeconfig=/etc/kubernetes/scheduler.conf - --leader-elect=true
拓撲分散限制
拓撲分散限制可用於根據節點的 zones
、regions
、node
或其他自訂拓撲,在節點之間平均分配 Pod。
以下資訊清單範例顯示 Deployment,該 Deployment 會使用拓撲散布限制,在所有可排程的節點之間平均散布副本:
apiVersion: apps/v1
kind: Deployment
metadata:
name: topology-spread-deployment
labels:
app: myapp
spec:
replicas: 30
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
topologySpreadConstraints:
- maxSkew: 1 # Default. Spreads evenly. Maximum difference in scheduled Pods per Node.
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule # Default. Alternatively can be ScheduleAnyway
labelSelector:
matchLabels:
app: myapp
matchLabelKeys: # beta in 1.27
- pod-template-hash
containers:
# pause is a lightweight container that simply sleeps
- name: pause
image: registry.k8s.io/pause:3.2
使用拓撲分散限制時,請注意下列事項:
- Pod 的
labels.app: myapp
會與限制的labelSelector
相符。 topologyKey
會指定kubernetes.io/hostname
。這個標籤會自動附加至所有節點,並填入節點的主機名稱。matchLabelKeys
可防止新 Deployment 推出時,在計算 Pod 的排程位置時,將舊修訂版本的 Pod 納入考量。Deployment 會自動填入pod-template-hash
標籤。
Pod 反相依性
Pod 反相依性可讓您定義限制,說明哪些 Pod 可以共用同一節點。
以下資訊清單範例顯示的 Deployment 使用反相依性,將副本限制為每個節點一個 Pod:
apiVersion: apps/v1
kind: Deployment
metadata:
name: pod-affinity-deployment
labels:
app: myapp
spec:
replicas: 30
selector:
matchLabels:
app: myapp
template:
metadata:
name: with-pod-affinity
labels:
app: myapp
spec:
affinity:
podAntiAffinity:
# requiredDuringSchedulingIgnoredDuringExecution
# prevents Pod from being scheduled on a Node if it
# does not meet criteria.
# Alternatively can use 'preferred' with a weight
# rather than 'required'.
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp
# Your nodes might be configured with other keys
# to use as `topologyKey`. `kubernetes.io/region`
# and `kubernetes.io/zone` are common.
topologyKey: kubernetes.io/hostname
containers:
# pause is a lightweight container that simply sleeps
- name: pause
image: registry.k8s.io/pause:3.2
這個 Deployment 範例指定了 30
個副本,但只會擴充至叢集中的可用節點數量。
使用 Pod 反相依性時,請注意下列事項:
- Pod 的
labels.app: myapp
會與限制的labelSelector
相符。 topologyKey
會指定kubernetes.io/hostname
。這個標籤會自動附加至所有節點,並填入節點的主機名稱。如果叢集支援其他標籤,您可以選擇使用這些標籤,例如region
或zone
。
預先提取容器映像檔
如果沒有其他限制,根據預設,kube-scheduler
會優先將 Pod 排程到已下載容器映像檔的節點上。如果叢集較小,且沒有其他排程設定,可能就會需要這種行為,因為這樣就能在每個節點上都下載映像檔。不過,這項概念應視為最後手段。更好的解決方法是使用 nodeSelector
、拓撲擴散限制,或親和性 / 反親和性。詳情請參閱「將 Pod 指派給節點」。
如要確保容器映像檔預先提取至所有節點,可以使用 DaemonSet
,例如:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: prepulled-images
spec:
selector:
matchLabels:
name: prepulled-images
template:
metadata:
labels:
name: prepulled-images
spec:
initContainers:
- name: prepulled-image
image: IMAGE
# Use a command the terminates immediately
command: ["sh", "-c", "'true'"]
containers:
# pause is a lightweight container that simply sleeps
- name: pause
image: registry.k8s.io/pause:3.2
Pod 在所有節點上 Running
後,請再次重新部署 Pod,確認容器現在是否平均分配到各個節點。
後續步驟
如需其他協助,請與 Cloud Customer Care 團隊聯絡。
如要進一步瞭解支援資源,包括下列項目,請參閱「取得支援」: