如何在K8s中添加节点故障迁移规则及实现Pod跨节点分布
这是K8s调度里很常见的场景,咱们先从排查原因到解决一步步来:
先排查为什么Pod都集中在node2
首先得搞清楚根因,执行下面几个命令看看:
1. 检查节点资源是否充足
先看看node1的资源是不是被占满了,导致调度器没法把Pod调度过去:
kubectl describe nodes node1 | grep -A 20 "Allocated resources"
看Allocated resources下面的Requests和Limits,如果CPU、内存的请求已经接近node1的Allocatable值,那调度器会优先选资源充足的node2。
2. 检查节点是否有污点
如果node1被加了污点(Taints),而你的api-server Pod没有对应的容忍度(Tolerations),调度器就不会把Pod调度到node1上:
kubectl describe node node1 | grep -A 10 "Taints"
如果输出里有类似NoSchedule或NoExecute的污点,那就是这个问题。
3. 检查Deployment的亲和性配置
看看你的api-server Deployment是不是特意配置了节点亲和性,强制要求Pod只能跑在node2上:
kubectl get deployment api-server -o yaml | grep -A 30 "affinity"
如果看到nodeAffinity里指定了node2的标签,那就是这个原因。
针对性解决方法
方法1:添加Pod反亲和性(最常用的解决方案)
给api-server的Deployment配置Pod反亲和性,让调度器尽量把同一个Deployment的Pod分布到不同节点。这是最通用的方法,即使只有2个节点,3个副本也会至少分到两个节点(2个在node2,1个在node1,或者反过来)。
编辑你的api-server Deployment:
kubectl edit deployment api-server
在spec.template.spec下面添加以下配置(注意values里的标签要和你的api-server Pod的app标签一致,可先用kubectl get pods api-server-xxx --show-labels确认):
affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - api-server topologyKey: kubernetes.io/hostname
保存退出后,Deployment会滚动更新,Pod会重新调度,实现跨节点分布。
小贴士:如果要强制要求Pod必须分布在不同节点(但你的集群只有2个节点,3个副本的话会有一个Pod处于Pending状态,所以不建议),可以把
preferredDuringSchedulingIgnoredDuringExecution换成requiredDuringSchedulingIgnoredDuringExecution。
方法2:移除节点污点(如果有)
如果node1有污点,比如不小心加上的NoSchedule污点,执行下面的命令移除(把<污点键>和<污点值>换成你查到的内容):
kubectl taint node node1 <污点键>:<污点值>-
比如查到的污点是node.kubernetes.io/unreachable:NoSchedule,就执行:
kubectl taint node node1 node.kubernetes.io/unreachable:NoSchedule-
方法3:调整节点资源或Pod资源请求
如果node1资源不足,要么给node1扩容(在AWS上就是调整EC2实例规格),要么修改Pod的资源请求,降低对CPU/内存的要求:
编辑Deployment:
kubectl edit deployment api-server
在spec.template.spec.containers.resources里调整requests的值:
resources: requests: cpu: "100m" # 原来如果是500m,改成更小的值 memory: "256Mi" # 原来如果是1Gi,改成更小的值
方法4:移除错误的节点亲和性配置
如果Deployment里配置了强制调度到node2的节点亲和性,直接删除那部分配置即可,保存后Pod会重新调度。
内容的提问来源于stack exchange,提问作者Ravichandra

