将节点置于维护模式

如果您需要修复或维护节点,则应首先将节点置于维护模式。这样会正常排空现有 Pod 和工作负载,不包括 API 服务器等关键系统 Pod。维护模式还会阻止节点接收新的 Pod 分配。在维护模式下,您可以在节点上工作,而不会有中断 Pod 流量的风险。

工作原理

Google Distributed Cloud 提供了一种将节点置于维护模式的方法。此方法可让其他集群组件正确知道节点处于维护模式。将节点置于维护模式时,无法在节点上安排其他 pod,并且现有 pod 会停止。

您可以在特定节点上手动使用 Kubernetes 命令(例如 kubectl cordonkubectl drain),而不是使用维护模式。

当您使用维护模式流程时,Google Distributed Cloud 会执行以下操作:

1.29

  • Google Distributed Cloud 会向指定节点添加 baremetal.cluster.gke.io/maintenance:NoSchedule 污点,以防止在节点上调度新的 Pod。

  • Google Distributed Cloud 使用 Eviction API 逐出每个 Pod。这种排空节点的方法遵循 PodDisruptionBudget (PDB)。您可以使用字段 minAvailablemaxUnavailable 为一组 Pod 指定可接受的中断级别,以配置 PDB 以保护您的工作负载。以这种方式排空节点可以更好地防止工作负载中断。基于逐出的节点排空已作为正式版 1.29 版提供。

  • 系统会强制执行 20 分钟的超时,以确保节点不会因等待 Pod 停止而停滞。如果 Pod 被配置为容忍所有污点或具有终结器,则其可能不会停止。Google Distributed Cloud 会尝试停止所有 Pod,但如果超过超时时间,节点会进入维护模式。此超时可防止正在运行的 Pod 阻止升级。

1.28 及更低版本

  • Google Distributed Cloud 会向指定节点添加 baremetal.cluster.gke.io/maintenance:NoSchedule 污点,以防止在节点上调度新的 Pod。

  • Google Distributed Cloud 添加了 baremetal.cluster.gke.io/maintenance:NoExecute 污点。根据 NoExecute 污点,Google Distributed Cloud kube-scheduler 会停止 Pod 并排空节点。这种排空节点的方法不支持 PDB。

  • 系统会强制执行 20 分钟的超时,以确保节点不会因等待 Pod 停止而停滞。如果 Pod 被配置为容忍所有污点或具有终结器,则其可能不会停止。Google Distributed Cloud 会尝试停止所有 Pod,但如果超过超时时间,节点会进入维护模式。此超时可防止正在运行的 Pod 阻止升级。

基于逐出的排空

从基于污点的排空切换到基于逐出的节点排空,并没有相关的任何流程变化。此开关只会影响协调逻辑。

此功能并非在所有受支持的版本都处于相同的发布阶段:

  • 1.29:正式版
  • 1.28:不可用
  • 1.16:不可用

排空顺序

在 1.29 版之前,由 Google Distributed Cloud kube-scheduler 执行的基于污点的节点排空不会采用特定算法从节点中排空 Pod。使用基于逐出的节点排空功能,可以根据优先级以特定顺序逐出 Pod。逐出优先级与特定的 Pod 条件相关联,如下表所示:

排空顺序 Pod 条件(必须全部匹配)和
1

将逐出符合以下条件的 Pod:

  • 没有 spec.prorityClassName 的 Pod
  • 与任何已知容器存储接口 (CSI) 名称都不匹配的 Pod
  • 不属于 DaemonSet 的 Pod
2

将逐出符合以下条件的 Pod:

  • 属于 DaemonSet 的 Pod
  • Pod 没有 PriorityClass
  • 与任何已知容器存储接口 (CSI) 名称都不匹配的 Pod
3

将逐出符合以下条件的 Pod:

  • 具有 Spec.ProrityClassName 的 Pod
  • 与任何已知容器存储接口 (CSI) 名称都不匹配的 Pod

匹配 Pod 的逐出顺序基于 PriorityClass.value(从低到高)。

4

等待 CSI 在 Pod 都被逐出后清理 PV/PVC 装载。使用 Node.Status.VolumesInUse 表示所有卷均已清理。

5

将逐出符合以下条件的 Pod:

  • 与已知容器存储接口 (CSI) 名称匹配的 Pod

这些 Pod 仍需要排空,因为 kubelet 不提供就地升级兼容性。

由于基于逐出的节点排空遵循 PDB,因此在某些情况下,PDB 设置可能会阻止节点排空。如需了解节点池排空方面的问题排查信息,请参阅检查节点长时间处于排空状态的原因

停用基于逐出的节点排空

对于次要版本 1.29 的集群或要升级到次要版本 1.29 的集群,系统会默认启用基于逐出的节点排空。如果基于逐出的节点排空导致集群升级或集群维护出现问题,您可以通过向集群资源添加 baremetal.cluster.gke.io/maintenance-mode-ignore-pdb: true 注解来还原为基于污点的节点排空。

将节点置于维护模式

选择要在集群配置文件的 maintenanceBlocks 下,通过指定选择节点的 IP 地址范围,选择要进入维护模式的节点。您选择的节点必须处于就绪状态且在集群中正常运行。

如需将节点置于维护模式,请执行以下操作:

  1. 修改集群配置文件以选择要置于维护模式的节点。

    您可以使用自己选择的编辑器修改配置文件,也可以运行以下命令直接修改集群自定义资源:

    kubectl -n CLUSTER_NAMESPACE edit cluster CLUSTER_NAME
    

    请替换以下内容:

    • CLUSTER_NAMESPACE:集群的命名空间。
    • CLUSTER_NAME:集群的名称。
  2. maintenanceBlocks 部分添加到集群配置文件,以指定要置于维护模式的节点的单个 IP 地址或地址范围。

    以下示例展示了如何通过指定 IP 地址范围来选择多个节点:

    metadata:
      name: my-cluster
      namespace: cluster-my-cluster
    spec:
      maintenanceBlocks:
        cidrBlocks:
        - 172.16.128.1-172.16.128.64
    
  3. 保存并应用更新后的集群配置。

    Google Distributed Cloud 开始将节点置于维护模式。

  4. 运行以下命令以获取集群中节点的状态:

    kubectl get nodes --kubeconfig=KUBECONFIG
    

    输出类似于以下内容:

    NAME                       STATUS   ROLES           AGE     VERSION
    user-anthos-baremetal-01   Ready    control-plane   2d22h   v1.27.4-gke.1600
    user-anthos-baremetal-04   Ready    worker          2d22h   v1.27.4-gke.1600
    user-anthos-baremetal-05   Ready    worker          2d22h   v1.27.4-gke.1600
    user-anthos-baremetal-06   Ready    worker          2d22h   v1.27.4-gke.1600
    

    请注意,节点仍然可调度,但污点会阻止任何 Pod(没有适当的容忍设置)被调度到节点上。

  5. 运行以下命令以获取维护模式下的节点数:

    kubectl get nodepools --kubeconfig ADMIN_KUBECONFIG 
    

    响应应类似于以下示例:

    NAME   READY   RECONCILING   STALLED   UNDERMAINTENANCE   UNKNOWN
    np1    3       0             0         1                  0
    

    此示例中的此 UNDERMAINTENANCE 列显示了一个节点处于维护模式。

    当节点进入维护模式时,Google Distributed Cloud 还会向节点添加以下污点:

    • baremetal.cluster.gke.io/maintenance:NoExecute
    • baremetal.cluster.gke.io/maintenance:NoSchedule

从维护模式中移除节点

如需从维护模式中移除节点,请执行以下操作:

  1. 修改集群配置文件以清除要从维护模式中移除的节点。

    您可以使用自己选择的编辑器修改配置文件,也可以运行以下命令直接修改集群自定义资源:

    kubectl -n CLUSTER_NAMESPACE edit cluster CLUSTER_NAME
    

    请替换以下内容:

    • CLUSTER_NAMESPACE:集群的命名空间。
    • CLUSTER_NAME:集群的名称。
  2. 修改 IP 地址以从维护模式中移除特定节点,或者移除 maintenanceBlocks 部分从维护模式中移除所有操作。

  3. 保存并应用更新后的集群配置。

  4. 使用 kubectl 命令检查节点的状态。

关闭并重启集群

如果必须关闭整个集群,请按照以下部分中的操作说明关闭集群并安全恢复集群。

关停集群

如果要关停管理用户集群的集群,您必须先关停所有受管理的用户集群。以下说明适用于所有 Google Distributed Cloud 集群类型。

  1. 检查所有集群节点的状态:

    kubectl get nodes --kubeconfig CLUSTER_KUBECONFIG
    

    CLUSTER_KUBECONFIG 替换为集群的 kubeconfig 文件的路径。

    输出类似于以下内容:

    NAME        STATUS   ROLES           AGE    VERSION
    control-0   Ready    control-plane   202d   v1.27.4-gke.1600
    control-1   Ready    control-plane   202d   v1.27.4-gke.1600
    control-2   Ready    control-plane   202d   v1.27.4-gke.1600
    worker-0    Ready    worker          202d   v1.27.4-gke.1600
    worker-1    Ready    worker          202d   v1.27.4-gke.1600
    worker-2    Ready    worker          202d   v1.27.4-gke.1600
    worker-3    Ready    worker          202d   v1.27.4-gke.1600
    worker-4    Ready    worker          154d   v1.27.4-gke.1600
    worker-5    Ready    worker          154d   v1.27.4-gke.1600
    worker-6    Ready    worker          154d   v1.27.4-gke.1600
    worker-7    Ready    worker          154d   v1.27.4-gke.1600
    worker-8    Ready    worker          154d   v1.27.4-gke.1600
    worker-9    Ready    worker          154d   v1.27.4-gke.1600
    

    如果某个节点的 STATUS 不是 Ready,我们强烈建议您对该节点进行问题排查,并且仅在所有节点均为 Ready 时再继续。

  2. 如果您要关停用户集群,请检查管理员集群节点的状态:

    kubectl get nodes --kubeconfig ADMIN_KUBECONFIG
    

    ADMIN_KUBECONFIG 替换为管理集群的 kubeconfig 文件的路径。

    后续步骤依赖于管理员集群。如果某个节点的 STATUS 不是 Ready,我们强烈建议您对该节点进行问题排查,仅在所有节点都处于 Ready 时再继续。

  3. 检查要关停的集群的健康状况:

    bmctl check cluster -c CLUSTER_NAME --kubeconfig ADMIN_KUBECONFIG
    

    请替换以下内容:

    • CLUSTER_NAME:您要检查的集群的名称。

    • ADMIN_KUBECONFIG:管理集群的 kubeconfig 文件的路径。

    请先更正报告的所有问题,然后再继续。

  4. 对于要关停的集群,请确保所有 etcd Pod 都在运行:

    kubectl get pods --kubeconfig CLUSTER_KUBECONFIG -A \
        -l component=etcd
    

    CLUSTER_KUBECONFIG 替换为集群的 kubeconfig 文件的路径。

    输出类似于以下内容:

    NAMESPACE     NAME                   READY   STATUS    RESTARTS   AGE
    kube-system   etcd-control-0-admin   1/1     Running   0          2d22h
    kube-system   etcd-control-1-admin   1/1     Running   0          2d22h
    kube-system   etcd-control-2-admin   1/1     Running   0          2d22h
    

    如果某个 Pod 的 STATUS 不是 Running,我们强烈建议您对 Pod 进行问题排查,仅在所有 Pod 都为 Running 时再继续。

  5. 按照备份集群中的说明执行备份。

    请务必在关闭集群之前进行 etcd 备份,以便在重启集群时遇到任何问题时可以恢复集群。Etcd 损坏、节点硬件故障、网络连接问题以及其他潜在情况都可能会阻止集群正确重启。

  6. 如果您要关停包含工作器节点的集群,请将工作器节点置于维护模式下。

    此步骤可最大限度地减少写入 etcd 的内容,从而降低在重启集群时需要协调大量 etcd 写入的可能性。

  7. 将控制平面节点置于维护模式

    此步骤可防止在节点关闭期间对有状态工作负载执行损坏的写入。

  8. 按以下顺序关闭集群节点:

    1. 工作器节点
    2. 控制平面负载均衡器节点
    3. 控制平面节点,从 etcd 关注者开始,以 etcd 主副本结尾

      如果您有高可用性 (HA) 集群,则可以使用 SSH 连接到每个控制平面节点并运行以下 etcdctl 命令来查找 etcd 主集群:

      ETCDCTL_API=3 etcdctl \
          --cacert /etc/kubernetes/pki/etcd/ca.crt \
          --cert /etc/kubernetes/pki/etcd/server.crt \
          --key /etc/kubernetes/pki/etcd/server.key \
          --write-out=table endpoint status
      

      响应包括 IS LEADER 列,如果节点是 etcd 主节点,则返回 true

此时,您的集群已完全关停。在执行任何必要的维护后,您可以按照下一部分中的说明重启集群。

重启集群

请按照以下步骤重启已完全关闭的集群。

  1. 按照关机序列的反向顺序开启节点机器。

  2. 从维护模式中移除控制平面节点。

    如需了解相关说明,请参阅从维护模式中移除节点

  3. 从维护模式中移除工作器节点。

  4. 运行集群健康检查,确保集群正常运行:

    bmctl check cluster -c CLUSTER_NAME --kubeconfig ADMIN_KUBECONFIG
    
  5. 如果问题(例如 etcd 崩溃循环)导致集群无法正确重启,请尝试从最近一次的已知良好备份中恢复集群。如需了解相关说明,请参阅恢复集群

结算和维护模式

Google Distributed Cloud 的费用取决于您的集群针对能够运行工作负载的节点的 vCPU 数量。将节点置于维护模式时,NoExecuteNoSchedule 污点将添加到节点,但它们不会停用结算功能。将节点置于维护模式后,封锁节点 (kubectl cordon NODE_NAME) 以将其标记为无法安排。将节点标记为无法安排后,该节点及其关联的 vCPU 将从结算中排除。

价格页面中所述,您可以使用 kubectl 查看每个用户集群的 vCPU 容量(用于结算)。该命令不考虑节点是否可调度,它仅提供每个节点的 vCPU 数量。

要确定用户集群的每个节点的 vCPU 数量,请使用以下代码:

kubectl get nodes \
    --kubeconfig USER_KUBECONFIG \
    -o=jsonpath="{range .items[*]}{.metadata.name}{\"\t\"} \
    {.status.capacity.cpu}{\"\n\"}{end}"

USER_KUBECONFIG 替换为用户集群的 kubeconfig 文件的路径。