如何确保节点组内每个节点至少运行1个Pod?
问题描述
我们拥有一个节点组,组内每个节点均带有相同标签acme/node-type: worker,该节点组包含2个Spot实例节点。
我们部署了一个副本数为3的Deployment,通过nodeAffinity配置将其调度到该节点组,配置如下:
spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: acme/node-type operator: In values: - worker
当某个Spot实例被回收后,所有Pod都会迁移到第二个节点;在2个节点都可用时,所有Pod集中在单个节点的情况并不理想。我们希望这3个副本的Deployment能够分布在2个节点上,确保节点组内每个节点至少运行1个Pod,请问是否可行?
尝试的方案1
topologySpreadConstraints: - maxSkew: 1 topologyKey: acme/node-type whenUnsatisfiable: ScheduleAnyway labelSelector: matchLabels: acme/node-type: worker
解决方案
可行,但你当前的topologySpreadConstraints配置不对,达不到预期效果,问题出在这几点:
topologyKey用了acme/node-type,但这个标签是所有worker节点共有的,Kubernetes会把这些节点当成同一个拓扑组,根本没法实现节点级的Pod分布。labelSelector匹配的是节点标签acme/node-type: worker,但拓扑分布约束里的labelSelector应该匹配你这个Deployment的Pod自己带的标签,不是节点标签。
你需要调整成下面的正确配置:
首先,确保你的Deployment的Pod模板有专属标签(比如app: my-worker-app,这个标签用来标识属于当前Deployment的Pod):
spec: replicas: 3 selector: matchLabels: app: my-worker-app template: metadata: labels: app: my-worker-app spec: # 保留原来的nodeAffinity配置 affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: acme/node-type operator: In values: - worker # 新增正确的拓扑分布约束 topologySpreadConstraints: - maxSkew: 1 topologyKey: kubernetes.io/hostname # 用节点的主机名作为拓扑区分依据,每个节点是独立的拓扑域 whenUnsatisfiable: DoNotSchedule # 不满足分布要求就不调度,避免Pod全堆在一个节点 labelSelector: matchLabels: app: my-worker-app # 匹配当前Deployment的Pod标签
配置说明
topologyKey: kubernetes.io/hostname:每个节点的主机名都是唯一的,Kubernetes会以此为依据,把Pod分散到不同节点上。maxSkew: 1:要求任意两个节点上的Pod数量差不超过1。3个副本配2个节点,自然会分成2个和1个,保证每个节点至少有1个Pod。whenUnsatisfiable: DoNotSchedule:如果只剩1个节点(比如某个Spot实例被回收),就暂时不调度多余的Pod;等新的worker节点可用时,Kubernetes会自动把Pod调度过去,恢复分布状态。
要是你希望节点不足时也能运行所有Pod(比如只剩1个节点时仍跑3个Pod),可以把whenUnsatisfiable改成ScheduleAnyway,等节点恢复后,Kubernetes会自动调整Pod的分布。
内容的提问来源于stack exchange,提问作者Kay
相关产品推荐
相关产品推荐

