更新时间:2025-04-25 GMT+08:00
节点标签更新导致的Pod容器退出问题
问题现象
工作负载通过节点标签调度到节点运行后,如果更新节点标签,然后修改节点的kubelet配置参数导致kubelet组件重启。kubelet组件重启后约30s,查看工作负载状态,会出现异常事件“Predicate NodeAffinity failed”,原Pod状态变成Completed,并且新Pod将会重新调度。如果不存在其他符合指定标签的节点,新Pod也会调度失败。
问题原因
工作负载设置指定标签亲和后,Pod只能调度到存在指定标签的节点上。如果调度成功后修改节点标签,Pod仍可以在原节点上运行,但是重启kubelet后,kubelet会检查一次节点上的Pod亲和策略是否与节点匹配,不匹配的话会将原Pod状态设置为Completed,并会新建一个Pod重新调度。
该问题根因是Kubernetes的原生机制,为了保证Pod可以稳定运行,建议保持已运行Pod的亲和策略中指定的标签与所在节点的标签一致,避免kubelet重启后由于亲和策略检查不通过导致Pod容器退出,或者Pod重新部署后由于亲和策略不匹配节点标签导致Pod无法在原节点启动。
解决方案
- 如果您仅需要新增节点或节点池的K8S标签,建议不要删除节点或节点池上原有的K8S标签,使节点保持满足节点上已运行Pod的亲和策略。
- 如果您需要修改或删除某节点或某节点池的K8S标签,且修改后的K8S标签不满足该节点上已运行Pod的亲和策略,请根据以下步骤排查节点上是否存在配置亲和性调度的Pod,否则可能会导致Pod被重新调度。
- 查找节点上的工作负载是否配置亲和策略。
- 如果节点为默认节点池(DefaultPool)中的节点,请执行以下命令,其中“节点IP”为实际的节点IP。
nodeIP='节点IP' && kubectl get pod --all-namespaces -o=custom-columns=nodeIP:'status.hostIP',nodeAffinity:'spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms' | sed '1d' | grep $nodeIP | awk '{print substr($0, index($0,$2))}' | grep matchExpressions | uniq
- 如果节点为自定义节点池中的节点,请执行以下命令,其中“节点池名称”为实际的节点池名称。
nodeIPs=$(kubectl get nodes -l cce.cloud.com/cce-nodepool=节点池名称 -o=custom-columns=IP:'metadata.annotations.alpha\.kubernetes\.io\/provided-node-ip' | sed '1d' | tr '\n' '|' | sed 's/|$//') && kubectl get pod --all-namespaces -o=custom-columns=nodeIP:'status.hostIP',nodeAffinity:'spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms' | sed '1d' | grep -E $nodeIPs | awk '{print substr($0, index($0,$2))}' | grep matchExpressions | uniq
- 如果节点为默认节点池(DefaultPool)中的节点,请执行以下命令,其中“节点IP”为实际的节点IP。
- 查询亲和策略关联的所有负载,其中“亲和策略”为上一步中查询出的亲和策略。
match='亲和策略' && kubectl get deployment,statefulset,daemonset,job,cronjob --all-namespaces -o=custom-columns=kind:'kind',name:'metadata.namespace',namespace:'metadata.name',nodeAffinity:'spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms' | grep -F "$match" | awk '{print "kind:" $1 ",namespace:" $2 ",name:" $3}'
如下图所示,查询出配置了tag1=value1标签亲和策略的工作负载。
- 请谨慎评估该工作负载重启对业务的影响,再修改节点或节点池标签。
您也可以修改该工作负载的亲和策略,将其亲和调度到其他节点,详情请参见设置节点亲和调度(nodeAffinity)。等待Pod重新正常运行后,再修改该节点标签。
- 查找节点上的工作负载是否配置亲和策略。