将节点置于维护模式

如果您需要修复或维护节点,则应首先将节点置于维护模式。这会正常排空现有 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:GA
  • 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
  • 没有 PriorityClass 的 Pod
  • 与任何已知容器存储接口 (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 文件的路径。