將工作負載分散到節點和可用區域 - AWS 方案指引

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

將工作負載分散到節點和可用區域

在可用區域和節點等故障網域之間分配工作負載可改善元件可用性,並降低水平擴展應用程式的故障機率。下列各節介紹將工作負載分散到節點和可用區域的方法。

使用 Pod 拓撲分散限制條件

Kubernetes Pod 拓撲分散限制,指示 Kubernetes 排程器將由 ReplicaSet 或 StatefulSet 管理的 Pod 分散到不同的故障網域 (可用區域、節點和硬體類型)。當您使用 Pod 拓撲分散限制時,您可以執行下列動作:

  • 根據應用程式需求,將 Pod 分散或集中於不同的故障網域。例如,您可以分發 Pod 以實現彈性,也可以集中 Pod 以實現網路效能。

  • 結合不同的條件,例如跨可用區域分佈和跨節點分佈。

  • 如果無法滿足條件,請指定偏好的動作:

    • 使用 whenUnsatisfiable: DoNotSchedule搭配 maxSkew和 的組合minDomains來建立排程器的硬性需求。

    • 使用 whenUnsatisfiable: ScheduleAnyway 減少 maxSkew

如果故障區域無法使用,則該區域中的 Pod 會變得運作狀態不佳。Kubernetes 會重新排程 Pod,同時盡可能遵守分散限制條件。

Pod 拓撲分散限制條件

下列程式碼顯示使用 Pod 拓撲跨可用區域或跨節點分散限制的範例:

... spec: selector: matchLabels: app: <your-app-label> replicas: 3 template: metadata: labels: <your-app-label> spec: serviceAccountName: <ServiceAccountName> ... topologySpreadConstraints: - labelSelector: matchLabels: app: <your-app-label> maxSkew: 1 topologyKey: topology.kubernetes.io/zone # <---spread those pods evenly over all availability zones whenUnsatisfiable: ScheduleAnyway - labelSelector: matchLabels: app: <your-app-label> maxSkew: 1 topologyKey: kubernetes.io/hostname # <---spread those pods evenly over all nodes whenUnsatisfiable: ScheduleAnyway

預設的叢集整體拓撲分散限制條件

Kubernetes 現成提供一組預設的拓撲分散限制,用於跨節點和可用區域分佈 Pod:

defaultConstraints: - maxSkew: 3 topologyKey: "kubernetes.io/hostname" whenUnsatisfiable: ScheduleAnyway - maxSkew: 5 topologyKey: "topology.kubernetes.io/zone" whenUnsatisfiable: ScheduleAnyway
注意

需要不同類型的拓撲限制的應用程式可以覆寫叢集層級政策。

預設限制條件會設定較高的 maxSkew,這不適用於具有少量 Pod 的部署。截至目前為止, KubeSchedulerConfiguration 無法在 Amazon EKS 中變更。如果您需要強制執行其他一組拓撲分散限制,請考慮使用變動許可控制器,如以下章節所示。如果您執行替代排程器,也可以控制預設拓撲分散限制條件。不過,管理自訂排程器會增加複雜性,並可能影響叢集彈性和 HA。基於這些原因,我們不建議僅針對拓撲分散限制使用替代排程器。

拓撲分散限制的 Gatekeeper 政策

強制執行拓撲分散限制的另一個選項是使用 Gatekeeper 專案的政策。Gatekeeper 政策是在應用程式層級定義。

下列程式碼範例顯示使用Gatekeeper OPA政策進行部署。您可以根據您的需求修改政策。例如,僅將政策套用到具有標籤 的部署HA=true,或使用不同的政策控制器撰寫類似的政策。

第一個範例顯示與 ConstraintTemplate搭配使用k8stopologyspreadrequired_template.yml

apiVersion: templates.gatekeeper.sh/v1 kind: ConstraintTemplate metadata: name: k8stopologyspreadrequired spec: crd: spec: names: kind: K8sTopologySpreadRequired validation: openAPIV3Schema: type: object properties: message: type: string targets: - target: admission.k8s.gatekeeper.sh rego: | package k8stopologyspreadrequired get_message(parameters, _default) =3D msg { not parameters.message msg :=_default } get_message(parameters, _default) =3D msg { msg := parameters.message } violation[{"msg": msg}] { input.review.kind.kind ="Deployment" not input.review.object.spec.template.spec.topologySpreadConstraint def_msg :"Pod Topology Spread Constraints are required for Deployments" msg :get_message(input.parameters, def_msg) }

下列程式碼顯示 constraints YAML 資訊清單 k8stopologyspreadrequired_constraint.yml

apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sTopologySpreadRequired metadata: name: require-topologyspread-for-deployments spec: match: kinds: - apiGroups: ["apps"] kinds: ["Deployment"] namespaces: ## Without theses two lines will apply to the whole cluster - "example"

何時使用拓撲分散限制條件

考慮在下列案例中使用拓撲分散限制條件:

  • 任何水平擴展的應用程式 (例如,無狀態 Web 服務)

  • 具有主動-主動或主動-被動複本的應用程式 (例如,NoSQL 資料庫或快取)

  • 具有待命複本的應用程式 (例如,控制器)

可用於水平擴展案例的系統元件,例如,包括下列項目:

Pod 親和性與反親和性

在某些情況下,確保節點上執行的特定類型不超過一個 Pod 是有益的。例如,若要避免在相同節點上排程多個網路密集型 Pod,您可以使用反親和性規則搭配 標籤IngressNetwork-heavy。使用 時anti-affinity,您也可以使用下列的組合:

  • 網路最佳化節點上的標記

  • 網路密集型 Pod 上的對應公差

  • 節點親和性或節點選擇器,以確保網路密集型 Pod 使用網路最佳化執行個體

使用網路密集型 Pod 做為範例。您可能有不同的需求,例如 GPU、記憶體或本機儲存。如需其他使用範例和組態選項,請參閱 Kubernetes 文件

重新平衡 Pod

本節討論在 Kubernetes 叢集中重新平衡 Pod 的兩種方法。第一個 使用適用於 Kubernetes 的 Descheduler。Descheduler 透過強制執行策略來移除違反拓撲分散限制或反親和性規則的 Pod,協助維護 Pod 分佈。第二個方法使用 Karpenter 整合和 bin-packing 功能。合併透過將工作負載合併到較少、更有效率的封裝節點上,持續評估和最佳化資源用量。

如果您不使用 Karpenter,建議使用 Descheduler。如果您同時使用 Karpenter 和 Cluster Autoscaler,則可以將 Descheduler 與 Cluster Autoscaler 用於節點群組。

無群組節點的排程器

移除 Pod 時,無法保證拓撲限制仍滿足。例如,縮減部署規模可能會導致 Pod 分佈不平衡。不過,由於 Kubernetes 僅在排程階段使用 Pod 拓撲分散限制,因此 Pod 在故障網域中會保持不平衡。

若要在這類情況下維持平衡的 Pod 分佈,您可以使用 Descheduler for Kubernetes。Descheduler 是一種實用的工具,可用於多種用途,例如強制執行最長 Pod 存留期或存留時間 (TTL),或改善基礎設施的使用。在彈性和高可用性 (HA) 的情況下,請考慮下列 Descheduler 策略:

Karpenter 整合和 bin-packing 功能

對於使用 Karpenter 的工作負載,您可以使用整合和 bin-packing 功能來最佳化資源使用率,並降低 Kubernetes 叢集中的成本。Karpenter 會持續評估 Pod 置放和節點使用率,並盡可能嘗試將工作負載合併到較少、更有效率的封裝節點。此程序涉及分析資源需求、考慮 Pod 親和性規則等限制條件,以及在節點之間移動 Pod 以改善整體叢集效率。下列程式碼提供範例:

apiVersion: karpenter.sh/v1beta1 kind: NodePool metadata: name: default spec: disruption: consolidationPolicy: WhenUnderutilized expireAfter: 720h

對於 consolidationPolicy,您可以使用 WhenUnderutilizedWhenEmpty

  • consolidationPolicy 設定為 時WhenUnderutilized,Karpenter 會將所有節點視為合併。當 Karpenter 發現節點為空或未使用時,Karpenter 會嘗試移除或取代節點以降低成本。

  • consolidationPolicy 設為 時WhenEmpty,Karpenter 會考慮僅整合不包含工作負載 Pod 的節點。

Karpenter 整合決策並非僅根據您在監控工具中可能看到的 CPU 或記憶體使用率百分比。反之,Karpenter 會根據 Pod 資源請求和潛在的成本最佳化,使用更複雜的演算法。如需詳細資訊,請參閱 Karpenter 文件。