移除被 pod 中断预算阻止的节点

在某些情况下,Pod 中断预算 (PDB) 政策可以阻止节点成功地从节点池中移除。在这些情况下,尽管节点被移除,但节点状态仍会报告 Ready,SchedulingDisabled

Pod 中断预算与可用 Pod 数量冲突

PDB 政策通过阻止在更改系统的同时同时关闭 Pod 来确保应用的性能。因此,PDB 政策会限制复制应用中同时不可用的 Pod 的数量。

但是,PDB 政策有时可能会阻止您要执行的节点删除操作(如果移除节点,您会违反该政策)。

例如,PDB 政策可以定义系统中应始终有两个 Pod 可用(.spec.minAvailable 为 2)。但是,如果您只有两个 Pod,并且尝试移除包含其中一个 Pod 的节点,则 PDB 政策将会生效并阻止移除该节点。

同样,当 PDB 政策定义不应使用任何 Pod 时(.spec.maxUnavailable 为 0),此政策还会阻止删除任何关联的节点。即使您一次尝试移除一个 Pod,PDB 政策也会阻止删除受影响的节点。

解决方法:停用和重新启用 PDB 政策

如需解决此冲突,请备份 PDB 政策,然后将其移除。成功删除 PDB 后,节点将排空并且关联的 Pod 会被移除。完成所需的更改后,您可以重新启用 PDB 政策。

以下示例展示了如何在此情况下删除节点,这可能会影响所有类型的 GKE on Bare Metal 集群:管理员集群、混合集群、独立集群和用户集群。

相同的常规流程适用于所有集群类型。但是,从管理员集群节点池(对于管理员集群、混合集群或独立集群)中删除节点所使用的特定命令与从用户集群节点池中删除节点所使用的命令略有不同。

不同集群类型的命令差异

为了方便阅读,请注意以下命令中的占位符 ${KUBECONFIG}。根据集群类型,将管理员集群 kubeconfig (ADMIN_KUBECONFIG) 或用户集群 kubeconfig (USER_CLUSTER_CONFIG) 路径导出到 $(KUBECONFIG) 并按照以下步骤操作。

  • 如需从用户集群中删除节点池,请运行 export KUBECONFIG=USER_CLUSTER_CONFIG
  • 如需从管理员集群中删除节点,请运行 export KUBECONFIG=ADMIN_KUBECONFIG
  1. (可选):如果您要从用户集群节点池中删除节点,则执行以下命令来提取用户集群 kubeconfig 文件。请注意,变量 ADMIN_KUBECONFIG 指定管理员集群 kubeconfig 的路径,变量 USER_CLUSTER_NAME 指定集群的名称:

    kubectl --kubeconfig ADMIN_KUBECONFIG -n cluster-USER_CLUSTER_NAME  \
    get secret USER_CLUSTER_NAME-kubeconfig  \
    -o 'jsonpath={.data.value}' | base64 -d > USER_CLUSTER_CONFIG
    
  2. 从节点池中移除节点后,请检查节点状态。受影响的节点会报告 Ready, SchedulingDisabled

    kubectl get nodes --kubeconfig ${KUBECONFIG}
    

    节点状态会类似于以下内容:

    NAME        STATUS                    ROLES      AGE      VERSION
    abmnewCP2   Ready                     Master     11m      v.1.18.6-gke.6600
    abmnewCP3   Ready,SchedulingDisabled  <none>     9m22s    v.1.18.6-gke.6600
    abmnewCP4   Ready                     <none>     9m18s    v.1.18.6-gke.6600
    
  3. 检查集群中的 PDB:

    kubectl get pdb --kubeconfig ${KUBECONFIG} -A
    

    系统会报告如下所示的 PDB:

    NAMESPACE     NAME             MIN AVAILABLE    MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
    gke-system    istio-ingress    1                N/A               1                     19m
    gke-system    istiod           1                N/A               1                     19m
    kube-system   coredns          1                N/A               0                     19m
    kube-system   log-aggregator   N/A              0                 0                     19m
    kube-system   prometheus       N/A              0                 0                     19m
     ```
    
  4. 检查 PDB。您需要在 PDB 中的 Pod 标签与节点中匹配的 Pod 之间查找匹配项。此匹配可确保您停用正确的 PDB 来成功移除节点:

    kubectl --kubeconfig ${KUBECONFIG} get pdb log-aggregator -n kube-system -o 'jsonpath={.spec}'
    

    系统会在 PDB 政策中返回匹配的标签结果:

    {"maxUnavailable":0,"selector":{"matchLabels":{"app":"stackdriver-log-aggregator"}}}
    
  5. 找到与 PDB 政策标签匹配的 Pod:

    kubectl --kubeconfig ${KUBECONFIG} get pods -A --selector=app=stackdriver-log-aggregator  \
    -o=jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.nodeName}{"\n"}{end}'
    

    该命令会返回与 PDB 标签匹配的 Pod 列表,并验证您需要移除的 PDB 政策:

    stackdriver-log-aggregator-0    abmnewCP3
    stackdriver-log-aggregator-1    abmnewCP3
    
  6. 确认受影响的 Pod 后,请备份 PDB 政策的备份(在本示例中为 log-aggregator 政策):

    kubectl get pdb log-aggregator --kubeconfig ${KUBECONFIG} -n kube-system  \
    -o yaml >> log-aggregator.yaml
    
  7. 删除特定 PDB 政策(在本示例中为 log-aggregator 政策):

    kubectl delete pdb log-aggregator --kubeconfig ${KUBECONFIG} -n kube-system
    

    删除 PDB 政策后,节点将继续排空。但是,节点可能需要一段时间(最多 30 分钟)才能完全删除,因此请继续检查节点状态。

    请注意,如果要永久移除节点,同时移除与该节点关联的存储资源,则可以在恢复 PDB 政策之前执行此操作。请参阅移除存储资源

  8. 从副本中恢复 PDB 政策:

    kubectl apply -f log-aggregator.yaml --kubeconfig ${KUBECONFIG}
    
  9. 验证是否已成功创建删除的 Pod。在此示例中,如果已有两个 stackdriver-log-aggregator-x Pod,则表示已重新创建 Pod:

    kubectl get pods -o wide --kubeconfig ${KUBECONFIG} -A
    

若要恢复节点,请修改相应的节点池配置并恢复节点 IP 地址。

从永久删除的节点中移除存储资源

如果您永久删除了节点,但不想将其恢复到您的系统中,则还可以删除与该节点关联的存储资源。

在以下命令中,请注意以下变量:

  • ADMIN-KUBECONFIG 指定管理员集群的路径
  • USER_CLUSTER_CONFIG 指定集群配置 YAML 文件的路径。
  1. 查看并获取与节点关联的永久性卷 (PV) 的名称:

    kubectl get pv --kubeconfig ${KUBECONFIG}  \
    -A -o=jsonpath='{range .items[*]}{"\n"}{.metadata.name}{":\t"}{.spec.claimRef.name}{":\t}  \
    {.spec.nodeAffinity.required.nodeSelectorTerms[0].matchExpressions[0].values}{"\n"}{end}'
    
  2. 删除与节点关联的 PV:

    kubectl delete pv PV_NAME --kubeconfig ${KUBECONFIG}