本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
将工作负载分散到节点和可用区中
在可用区和节点等故障域
使用 pod 拓扑分布约束
Kubernetes 容器拓扑分布约束
-
根据应用程序要求将容器分布或集中到不同的故障域中。例如,您可以分发 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 提供了一组默认的拓扑分布约束
defaultConstraints: - maxSkew: 3 topologyKey: "kubernetes.io/hostname" whenUnsatisfiable: ScheduleAnyway - maxSkew: 5 topologyKey: "topology.kubernetes.io/zone" whenUnsatisfiable: ScheduleAnyway
注意
需要不同类型拓扑约束的应用程序可以覆盖集群级别的策略。
默认约束设置得很高maxSkew
,这对于拥有少量 pod 的部署没有用。到目前为止,KubeSchedulerConfiguration
无法在 Amazon EKS 中进行更改
拓扑分布限制的网守策略
强制执行拓扑分布限制的另一种选择是使用 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 数据库或缓存)
-
带有备用副本的应用程序(例如控制器)
例如,可用于水平可扩展场景的系统组件包括以下组件:
-
集群自动扩缩器和 Karpent
er (使用和) replicaCount > 1
leader-elect = true
Pod 亲和力和反亲和力
在某些情况下,确保一个节点上运行的特定类型的 pod 不超过一个是有益的。例如,为了避免在同一个节点上调度多个网络密集型的 Pod,您可以使用带有或标签的反关联性规则。Ingress
Network-heavy
使用时anti-affinity
,您还可以使用以下各项的组合:
-
网络优化节点上的污点
-
对网络密集型 pod 的相应容忍度
-
节点亲和性或节点选择器,用于确保网络密集型的 Pod 使用网络优化的实例
以网络密集型的 pod 为例。您可能有不同的要求,例如 GPU、内存或本地存储。有关其他用法示例和配置选项,请参阅 Kubernetes 文档
重新平衡吊舱
本节讨论在 Kubernetes 集群中重新平衡 Pod 的两种方法。第一个使用了 Kubernetes 的解调器。Descheduler 通过强制执行策略来移除违反拓扑分布限制或反关联性规则的 pod,从而帮助维持 pod 分布。第二种方法使用 Karpenter 合并和装箱功能。整合通过将工作负载整合到更少、打包效率更高的节点上,持续评估和优化资源使用情况。
如果你不使用 Karpenter,我们建议你使用 Descheduler。如果您同时使用 Karpenter 和 Cluster Autoscaler,则可以将 Descheduler 与 Cluster Autoscaler 一起用于节点组。
无组节点的解调器
移除 pod 后,无法保证拓扑约束仍然得到满足。例如,缩小部署规模可能会导致 Pod 分布不平衡。但是,由于 Kubernetes 仅在调度阶段使用 pod 拓扑分布约束,因此 Pod 在故障域中处于不平衡状态。
为了在这种情况下保持平衡的容器分布,你可以使用适用于 Kubernetes 的 Descheduler
Karpenter 整合和装箱功能
对于使用 Karpenter 的工作负载,您可以使用整合和垃圾箱打包功能来优化资源利用率并降低 Kubernetes 集群的成本。Karpenter 会持续评估 pod 的放置位置和节点利用率,并尽可能将工作负载整合到数量更少、打包效率更高的节点上。此过程包括分析资源需求,考虑 Pod 亲和性规则等限制,以及可能在节点之间移动 Pod 以提高集群的整体效率。以下代码提供了一个示例:
apiVersion: karpenter.sh/v1beta1 kind: NodePool metadata: name: default spec: disruption: consolidationPolicy: WhenUnderutilized expireAfter: 720h
对于consolidationPolicy
,你可以使用WhenUnderutilized
或WhenEmpty
:
-
当设置
consolidationPolicy
为时WhenUnderutilized
,Karpenter 会考虑所有节点进行合并。当 Karpenter 发现一个空的节点或未充分利用时,Karpenter 会尝试移除或替换该节点以降低成本。 -
当设置
consolidationPolicy
为时WhenEmpty
,Karpenter 只考虑不包含工作负载 Pod 的节点进行整合。
Karpenter 整合决策不仅仅基于您在监控工具中可能看到的 CPU 或内存利用率百分比。相反,Karpenter 使用更复杂的算法,该算法基于 pod 资源请求和潜在的成本优化。有关更多信息,请参阅 Karpenter