文档首页/ 云容器引擎 CCE/ 常见问题/ 工作负载/ 调度策略/ 如何让多个Pod均匀部署到各个节点上?
更新时间:2025-11-26 GMT+08:00
分享

如何让多个Pod均匀部署到各个节点上?

在Kubernetes中,如果需要让多个Pod均匀部署到各个节点,可以通过配置调度策略控制kube-scheduler的决策,结合Pod亲和性、Pod拓扑分布约束等机制实现。

  • 方案一:使用Pod反亲和性分散Pod:该方案适用于粗略分散,本质是将Pod分散至不同的拓扑域,但无法精确控制每个域有多少个Pod,不能严格意义上实现均分。例如,在节点资源不均匀且需要调度Pod数量大于节点数量的情况下,在满足Pod反亲和的前提下,即所有节点上均已运行1个Pod,调度器可能会选择剩余资源较多的节点优先调度。
  • 方案二:使用Pod拓扑分布约束(Topology Spread Constraints)控制Pod分布:Pod拓扑分布约束是比亲和性更强大的均匀调度方案,可以实现Pod在拓扑域(例如可用区、节点或其他用户自定义拓扑域)中的数量分布均衡,精确控制每个拓扑域的Pod数量上限或差异。

方案一:使用Pod反亲和性分散Pod

如果您想要让多个Pod尽可能的均匀分布在各个节点上,可以考虑使用工作负载反亲和特性,让Pod之间尽量“互斥”,这样就能尽量均匀分布在各节点上。

示例:Deployment配置Pod反亲和性
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 8  
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app  # Pod的标签,用于反亲和性匹配
    spec:
      affinity:
        podAntiAffinity: # 工作负载反亲和
          preferredDuringSchedulingIgnoredDuringExecution:  # 优先满足(软约束)
          - weight: 100 # 使用尽量满足策略时可设置优先级,取值为1-100,数值越大优先级越高
            podAffinityTerm:
              labelSelector: # 选择Pod的标签,与工作负载本身反亲和
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - my-app  # 匹配相同的Pod标签
              topologyKey: "kubernetes.io/hostname"
      containers:
      - name: my-app
        image: nginx:alpine
      imagePullSecrets:
        - name: default-secret

关键参数说明:

  • preferredDuringSchedulingIgnoredDuringExecution:软约束,Pod调度时会尽量满足设置的调度条件,但不会出现因为调度条件不满足而调度失败的情况。
  • topologyKey:取值为节点标签的键。如果节点使用该标签键并且具有相同的标签值, 则将这些节点视为处于同一拓扑域中。

    kubernetes.io/hostname:K8s内置节点标签,节点的唯一标识。使用该标签键时,每个节点均有唯一的标签值,即每个节点视为一个拓扑域,可用于按节点维度分散。

执行结果

“工作负载”页面,单击目标Deployment名称,在“实例列表”页签,可以看到同一个应用的Pod之间已实现反亲和调度,4个节点上均存在Pod运行。

方案二:使用Pod拓扑分布约束(Topology Spread Constraints)控制Pod分布

Pod拓扑分布约束(Topology Spread Constraints)是比亲和性更强大的均匀调度方案,可以控制Pod在不同拓扑域(例如可用区、节点或其他用户自定义拓扑域)之间的分布,并可直接指定每个拓扑域(如节点)的Pod数量差异不超过N,如果配合节点亲和性一起使用可以精确实现指定节点范围内的Pod均匀分布。更多详细信息请参见Pod拓扑分布约束

示例:Deployment配置拓扑分布约束

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 6
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      topologySpreadConstraints:
      - maxSkew: 1  # 节点间Pod数量差≤1
        topologyKey: kubernetes.io/hostname  # 按节点维度分布
        whenUnsatisfiable: ScheduleAnyway  # 若无法满足(如节点不足)仍进行调度
        labelSelector:
          matchLabels:
            app: my-app  # 仅匹配同应用的 Pod
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: role
                operator: In
                values:
                - app  # 仅调度到有 role=app 标签的节点
      containers:
      - name: my-app
        image: nginx:alpine
      imagePullSecrets:
        - name: default-secret

关键参数说明:

  • maxSkew:允许的最大Pod数量差异(如3个节点,6个Pod,理想每个节点调度2个Pod,如果差异≤1则允许Pod数量为3/2/1分布到各个节点)。
  • topologyKey:取值为节点标签的键。如果节点使用该标签键并且具有相同的标签值, 则将这些节点视为处于同一拓扑域中。
    • kubernetes.io/hostname:K8s内置节点标签,节点的唯一标识。使用该标签键时,每个节点均有唯一的标签值,即每个节点视为一个拓扑域,可用于按节点维度分散。
  • whenUnsatisfiable:
    • ScheduleAnyway:优先满足分布均衡,若无法满足(如节点数少于replicas),则放弃均衡,继续调度(避免Pod无法启动)。
    • DoNotSchedule:若无法满足(如节点数少于replicas),则不再继续调度。
  • labelSelector:仅统计匹配该标签的Pod(确保只计算同应用Pod,避免其他应用干扰)。

执行结果

“工作负载”页面,单击目标Deployment名称,在“实例列表”页签,可以看到同一个应用的Pod之间已均匀调度。

相关文档