
# 如何让多个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运行。
![](https://support.huaweicloud.com/cce_faq/zh-cn_image_0000002486119872.png "点击放大")
 #### 方案二：使用Pod拓扑分布约束（Topology Spread Constraints）控制Pod分布
Pod拓扑分布约束（Topology Spread Constraints）是比亲和性更强大的均匀调度方案，可以控制Pod在不同拓扑域（例如可用区、节点或其他用户自定义拓扑域）之间的分布，并可直接指定每个拓扑域（如节点）的Pod数量差异不超过N，如果配合节点亲和性一起使用可以精确实现指定节点范围内的Pod均匀分布。更多详细信息请参见[Pod拓扑分布约束](https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/topology-spread-constraints/)。
**示例：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之间已均匀调度。
![](https://support.huaweicloud.com/cce_faq/zh-cn_image_0000002518192993.png "点击放大")
