如何让多个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之间尽量“互斥”,这样就能尽量均匀分布在各节点上。
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之间已均匀调度。
