
# 节点标签更新导致的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被重新调度。
  1. 查找节点上的工作负载是否配置亲和策略。
     - 如果节点为默认节点池（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
       ```
       - 如果输出为空，则说明节点中当前运行的负载没有配置亲和策略，不涉及该问题。
       
       - 如果输出不为空，例如下图所示，则说明节点中存在配置了亲和tag1=value1标签的工作负载。 ![](https://support.huaweicloud.com/cce_faq/zh-cn_image_0000002200996113.png "点击放大")
         
        
     
     - 如果节点为自定义节点池中的节点，请执行以下命令，其中"节点池名称"为实际的节点池名称。
       ```
       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
       ```
       - 如果输出为空，则说明节点池中当前运行的负载没有配置亲和策略，不涉及该问题。
       
       - 如果输出不为空，例如下图所示，则说明节点池中存在配置了亲和tag1=value1标签的工作负载。 ![](https://support.huaweicloud.com/cce_faq/zh-cn_image_0000002192800073.png "点击放大")
         
        
      
  
  2. 查询亲和策略关联的所有负载，其中"亲和策略"为上一步中查询出的亲和策略。
     ```
     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标签亲和策略的工作负载。
     ![](https://support.huaweicloud.com/cce_faq/zh-cn_image_0000002157508524.png "点击放大")
     
  
  3. 请谨慎评估该工作负载重启对业务的影响，再修改节点或节点池标签。 您也可以修改该工作负载的亲和策略，将其亲和调度到其他节点，详情请参见[设置节点亲和调度（nodeAffinity）](https://support.huaweicloud.com/usermanual-cce/cce_10_0892.html)。等待Pod重新正常运行后，再修改该节点标签。
     
   
 
