×

本文档描述了替换单个不健康 etcd 成员的过程。

此过程取决于 etcd 成员不健康的原因是机器未运行或节点未就绪,还是因为 etcd Pod 处于 CrashLoopBackOff 状态。

如果您丢失了大部分控制平面主机,请按照灾难恢复过程恢复到之前的集群状态,而不是此过程。

如果要替换的成员上的控制平面证书无效,则必须按照以下过程从过期的控制平面证书中恢复,而不是此过程。

如果控制平面节点丢失并创建了新的节点,etcd 集群运算符将负责生成新的 TLS 证书并将节点添加为 etcd 成员。

前提条件

  • 在替换不健康的 etcd 成员之前,请备份 etcd

识别不健康的 etcd 成员

您可以识别集群中是否存在不健康的 etcd 成员。

先决条件
  • 以具有 `cluster-admin` 角色的用户身份访问集群。

步骤
  1. 使用以下命令检查 `EtcdMembersAvailable` 状态条件的状态

    $ oc get etcd -o=jsonpath='{range .items[0].status.conditions[?(@.type=="EtcdMembersAvailable")]}{.message}{"\n"}'
  2. 查看输出

    2 of 3 members are available, ip-10-0-131-183.ec2.internal is unhealthy

    此示例输出显示 `ip-10-0-131-183.ec2.internal` etcd 成员不健康。

确定不健康 etcd 成员的状态

替换不健康 etcd 成员的步骤取决于您的 etcd 成员处于以下哪种状态

  • 机器未运行或节点未就绪

  • etcd Pod 处于 CrashLoopBackOff 状态

此过程确定您的 etcd 成员处于何种状态。这使您可以知道要遵循哪个过程来替换不健康的 etcd 成员。

如果您知道机器未运行或节点未就绪,但您预计它很快就会恢复到健康状态,则无需执行替换 etcd 成员的过程。当机器或节点恢复到健康状态时,etcd 集群运算符将自动同步。

先决条件
  • 您可以以具有 `cluster-admin` 角色的用户身份访问集群。

  • 您已识别出不健康的 etcd 成员。

步骤
  1. 确定**机器是否未运行**

    $ oc get machines -A -ojsonpath='{range .items[*]}{@.status.nodeRef.name}{"\t"}{@.status.providerStatus.instanceState}{"\n"}' | grep -v running
    示例输出
    ip-10-0-131-183.ec2.internal  stopped (1)
    
    1 此输出列出了节点以及节点机器的状态。如果状态不是 `running`,则**机器未运行**。

    如果**机器未运行**,请遵循*替换机器未运行或节点未就绪的不健康 etcd 成员*过程。

  2. 确定**节点是否未就绪**。

    如果以下任一场景为真,则**节点未就绪**。

    • 如果机器正在运行,请检查节点是否不可访问

      $ oc get nodes -o jsonpath='{range .items[*]}{"\n"}{.metadata.name}{"\t"}{range .spec.taints[*]}{.key}{" "}' | grep unreachable
      示例输出
      ip-10-0-131-183.ec2.internal	node-role.kubernetes.io/master node.kubernetes.io/unreachable node.kubernetes.io/unreachable (1)
      
      1 如果节点带有 `unreachable` 污点,则**节点未就绪**。
    • 如果节点仍然可访问,请检查节点是否列为 `NotReady`

      $ oc get nodes -l node-role.kubernetes.io/master | grep "NotReady"
      示例输出
      ip-10-0-131-183.ec2.internal   NotReady   master   122m   v1.30.3 (1)
      
      1 如果节点列为 `NotReady`,则**节点未就绪**。

    如果**节点未就绪**,请遵循*替换机器未运行或节点未就绪的不健康 etcd 成员*过程。

  3. 确定**etcd Pod 是否处于 CrashLoopBackOff 状态**。

    如果机器正在运行并且节点已就绪,请检查 etcd Pod 是否处于 CrashLoopBackOff 状态。

    1. 验证所有控制平面节点是否都列为 `Ready`

      $ oc get nodes -l node-role.kubernetes.io/master
      示例输出
      NAME                           STATUS   ROLES    AGE     VERSION
      ip-10-0-131-183.ec2.internal   Ready    master   6h13m   v1.30.3
      ip-10-0-164-97.ec2.internal    Ready    master   6h13m   v1.30.3
      ip-10-0-154-204.ec2.internal   Ready    master   6h13m   v1.30.3
    2. 检查 etcd Pod 的状态是否为 `Error` 或 `CrashloopBackoff`

      $ oc -n openshift-etcd get pods -l k8s-app=etcd
      示例输出
      etcd-ip-10-0-131-183.ec2.internal                2/3     Error       7          6h9m (1)
      etcd-ip-10-0-164-97.ec2.internal                 3/3     Running     0          6h6m
      etcd-ip-10-0-154-204.ec2.internal                3/3     Running     0          6h6m
      1 由于此 Pod 的状态为错误,因此etcd Pod 处于循环崩溃状态

    如果etcd Pod 处于循环崩溃状态,请按照替换 etcd Pod 处于循环崩溃状态的故障 etcd 成员的过程操作。

替换故障 etcd 成员

根据故障 etcd 成员的状态,使用以下过程之一:

替换其机器未运行或节点未就绪的故障 etcd 成员

此过程详细介绍了替换由于机器未运行或节点未就绪而导致故障的 etcd 成员的步骤。

如果您的集群使用控制平面机器集,请参阅“控制平面机器集故障排除”中的“恢复降级的 etcd 运算符”,了解更简单的 etcd 恢复过程。

先决条件
  • 您已识别出故障的 etcd 成员。

  • 您已验证机器未运行或节点未就绪。

    如果您关闭其他控制平面节点,则必须等待。控制平面节点必须保持关闭状态,直到完成故障 etcd 成员的替换。

  • 您可以以具有 `cluster-admin` 角色的用户身份访问集群。

  • 您已进行了 etcd 备份。

    在执行此过程之前进行 etcd 备份非常重要,以便您在遇到任何问题时可以恢复集群。

步骤
  1. 删除故障成员。

    1. 选择不在受影响节点上的 Pod

      在具有cluster-admin用户权限并可访问集群的终端中,运行以下命令:

      $ oc -n openshift-etcd get pods -l k8s-app=etcd
      示例输出
      etcd-ip-10-0-131-183.ec2.internal                3/3     Running     0          123m
      etcd-ip-10-0-164-97.ec2.internal                 3/3     Running     0          123m
      etcd-ip-10-0-154-204.ec2.internal                3/3     Running     0          124m
    2. 连接到正在运行的 etcd 容器,传入不在受影响节点上的 Pod 的名称。

      在具有cluster-admin用户权限并可访问集群的终端中,运行以下命令:

      $ oc rsh -n openshift-etcd etcd-ip-10-0-154-204.ec2.internal
    3. 查看成员列表。

      sh-4.2# etcdctl member list -w table
      示例输出
      +------------------+---------+------------------------------+---------------------------+---------------------------+
      |        ID        | STATUS  |             NAME             |        PEER ADDRS         |       CLIENT ADDRS        |
      +------------------+---------+------------------------------+---------------------------+---------------------------+
      | 6fc1e7c9db35841d | started | ip-10-0-131-183.ec2.internal | https://10.0.131.183:2380 | https://10.0.131.183:2379 |
      | 757b6793e2408b6c | started |  ip-10-0-164-97.ec2.internal |  https://10.0.164.97:2380 |  https://10.0.164.97:2379 |
      | ca8c2990a0aa29d1 | started | ip-10-0-154-204.ec2.internal | https://10.0.154.204:2380 | https://10.0.154.204:2379 |
      +------------------+---------+------------------------------+---------------------------+---------------------------+

      记下故障 etcd 成员的 ID 和名称,因为这些值在后续过程中需要。$ etcdctl endpoint health 命令将列出已删除的成员,直到替换过程完成并添加新成员。

    4. 通过向etcdctl member remove命令提供 ID 来删除故障 etcd 成员。

      sh-4.2# etcdctl member remove 6fc1e7c9db35841d
      示例输出
      Member 6fc1e7c9db35841d removed from cluster ead669ce1fbfb346
    5. 再次查看成员列表,并验证成员是否已删除。

      sh-4.2# etcdctl member list -w table
      示例输出
      +------------------+---------+------------------------------+---------------------------+---------------------------+
      |        ID        | STATUS  |             NAME             |        PEER ADDRS         |       CLIENT ADDRS        |
      +------------------+---------+------------------------------+---------------------------+---------------------------+
      | 757b6793e2408b6c | started |  ip-10-0-164-97.ec2.internal |  https://10.0.164.97:2380 |  https://10.0.164.97:2379 |
      | ca8c2990a0aa29d1 | started | ip-10-0-154-204.ec2.internal | https://10.0.154.204:2380 | https://10.0.154.204:2379 |
      +------------------+---------+------------------------------+---------------------------+---------------------------+

      您现在可以退出节点 shell。

  2. 通过输入以下命令关闭仲裁保护:

    $ oc patch etcd/cluster --type=merge -p '{"spec": {"unsupportedConfigOverrides": {"useUnsupportedUnsafeNonHANonProductionUnstableEtcd": true}}}'

    此命令确保您可以成功重新创建密钥并推出静态 Pod。

    关闭仲裁保护后,集群在剩余 etcd 实例重新引导以反映配置更改期间,可能会短暂不可访问。

    etcd 在使用两个成员运行时,无法容忍任何其他成员故障。重新启动任何剩余成员都会破坏仲裁,并导致集群停机。仲裁保护保护 etcd 免受可能导致停机的配置更改引起的重启,因此必须禁用它才能完成此过程。

  3. 通过运行以下命令删除受影响的节点:

    $ oc delete node <node_name>
    示例命令:
    $ oc delete node ip-10-0-131-183.ec2.internal
  4. 删除已删除的故障 etcd 成员的旧密钥。

    1. 列出已删除的故障 etcd 成员的密钥。

      $ oc get secrets -n openshift-etcd | grep ip-10-0-131-183.ec2.internal (1)
      1 传入您在此过程前面记下的故障 etcd 成员的名称。

      如下所示,存在对等方、服务和指标密钥:

      示例输出
      etcd-peer-ip-10-0-131-183.ec2.internal              kubernetes.io/tls                     2      47m
      etcd-serving-ip-10-0-131-183.ec2.internal           kubernetes.io/tls                     2      47m
      etcd-serving-metrics-ip-10-0-131-183.ec2.internal   kubernetes.io/tls                     2      47m
    2. 删除已删除的故障 etcd 成员的密钥。

      1. 删除对等方密钥。

        $ oc delete secret -n openshift-etcd etcd-peer-ip-10-0-131-183.ec2.internal
      2. 删除服务密钥。

        $ oc delete secret -n openshift-etcd etcd-serving-ip-10-0-131-183.ec2.internal
      3. 删除指标密钥。

        $ oc delete secret -n openshift-etcd etcd-serving-metrics-ip-10-0-131-183.ec2.internal
  5. 删除并重新创建控制平面机器。重新创建此机器后,将强制执行新的修订版,并且 etcd 将自动扩展。有关详细信息,请参阅“替换其机器未运行或节点未就绪的故障 etcd 成员”。

    如果您正在运行安装程序预配的基础设施,或者您使用 Machine API 创建了机器,请按照以下步骤操作。否则,您必须使用最初创建它的相同方法来创建新的主节点。

    1. 获取故障成员的机器。

      在具有cluster-admin用户权限并可访问集群的终端中,运行以下命令:

      $ oc get machines -n openshift-machine-api -o wide
      示例输出
      NAME                                        PHASE     TYPE        REGION      ZONE         AGE     NODE                           PROVIDERID                              STATE
      clustername-8qw5l-master-0                  Running   m4.xlarge   us-east-1   us-east-1a   3h37m   ip-10-0-131-183.ec2.internal   aws:///us-east-1a/i-0ec2782f8287dfb7e   stopped (1)
      clustername-8qw5l-master-1                  Running   m4.xlarge   us-east-1   us-east-1b   3h37m   ip-10-0-154-204.ec2.internal   aws:///us-east-1b/i-096c349b700a19631   running
      clustername-8qw5l-master-2                  Running   m4.xlarge   us-east-1   us-east-1c   3h37m   ip-10-0-164-97.ec2.internal    aws:///us-east-1c/i-02626f1dba9ed5bba   running
      clustername-8qw5l-worker-us-east-1a-wbtgd   Running   m4.large    us-east-1   us-east-1a   3h28m   ip-10-0-129-226.ec2.internal   aws:///us-east-1a/i-010ef6279b4662ced   running
      clustername-8qw5l-worker-us-east-1b-lrdxb   Running   m4.large    us-east-1   us-east-1b   3h28m   ip-10-0-144-248.ec2.internal   aws:///us-east-1b/i-0cb45ac45a166173b   running
      clustername-8qw5l-worker-us-east-1c-pkg26   Running   m4.large    us-east-1   us-east-1c   3h28m   ip-10-0-170-181.ec2.internal   aws:///us-east-1c/i-06861c00007751b0a   running
      1 这是故障节点的控制平面机器,ip-10-0-131-183.ec2.internal
    2. 删除故障成员的机器。

      $ oc delete machine -n openshift-machine-api clustername-8qw5l-master-0 (1)
      1 指定故障节点的控制平面机器的名称。

      删除故障成员的机器后,将自动预配一台新机器。

    3. 验证是否已创建新机器。

      $ oc get machines -n openshift-machine-api -o wide
      示例输出
      NAME                                        PHASE          TYPE        REGION      ZONE         AGE     NODE                           PROVIDERID                              STATE
      clustername-8qw5l-master-1                  Running        m4.xlarge   us-east-1   us-east-1b   3h37m   ip-10-0-154-204.ec2.internal   aws:///us-east-1b/i-096c349b700a19631   running
      clustername-8qw5l-master-2                  Running        m4.xlarge   us-east-1   us-east-1c   3h37m   ip-10-0-164-97.ec2.internal    aws:///us-east-1c/i-02626f1dba9ed5bba   running
      clustername-8qw5l-master-3                  Provisioning   m4.xlarge   us-east-1   us-east-1a   85s     ip-10-0-133-53.ec2.internal    aws:///us-east-1a/i-015b0888fe17bc2c8   running (1)
      clustername-8qw5l-worker-us-east-1a-wbtgd   Running        m4.large    us-east-1   us-east-1a   3h28m   ip-10-0-129-226.ec2.internal   aws:///us-east-1a/i-010ef6279b4662ced   running
      clustername-8qw5l-worker-us-east-1b-lrdxb   Running        m4.large    us-east-1   us-east-1b   3h28m   ip-10-0-144-248.ec2.internal   aws:///us-east-1b/i-0cb45ac45a166173b   running
      clustername-8qw5l-worker-us-east-1c-pkg26   Running        m4.large    us-east-1   us-east-1c   3h28m   ip-10-0-170-181.ec2.internal   aws:///us-east-1c/i-06861c00007751b0a   running
      1 新机器clustername-8qw5l-master-3正在创建中,一旦阶段从预配中变为运行中,即表示已就绪。

      创建新机器可能需要几分钟时间。机器或节点恢复到健康状态后,etcd 集群运算符将自动同步。

  6. 通过输入以下命令重新打开仲裁保护:

    $ oc patch etcd/cluster --type=merge -p '{"spec": {"unsupportedConfigOverrides": null}}'
  7. 您可以通过输入此命令来验证unsupportedConfigOverrides部分是否已从对象中删除:

    $ oc get etcd/cluster -oyaml
  8. 如果您使用的是单节点 OpenShift,请重新启动节点。否则,您可能会在 etcd 集群运算符中遇到以下错误:

    示例输出
    EtcdCertSignerControllerDegraded: [Operation cannot be fulfilled on secrets "etcd-peer-sno-0": the object has been modified; please apply your changes to the latest version and try again, Operation cannot be fulfilled on secrets "etcd-serving-sno-0": the object has been modified; please apply your changes to the latest version and try again, Operation cannot be fulfilled on secrets "etcd-serving-metrics-sno-0": the object has been modified; please apply your changes to the latest version and try again]
验证
  1. 验证所有 etcd Pod 是否正在正常运行。

    在具有cluster-admin用户权限并可访问集群的终端中,运行以下命令:

    $ oc -n openshift-etcd get pods -l k8s-app=etcd
    示例输出
    etcd-ip-10-0-133-53.ec2.internal                 3/3     Running     0          7m49s
    etcd-ip-10-0-164-97.ec2.internal                 3/3     Running     0          123m
    etcd-ip-10-0-154-204.ec2.internal                3/3     Running     0          124m

    如果先前命令的输出仅列出两个 Pod,您可以手动强制 etcd 重新部署。在具有cluster-admin用户权限并可访问集群的终端中,运行以下命令:

    $ oc patch etcd cluster -p='{"spec": {"forceRedeploymentReason": "recovery-'"$( date --rfc-3339=ns )"'"}}' --type=merge (1)
    1 forceRedeploymentReason值必须唯一,这就是附加时间戳的原因。
  2. 验证是否恰好有三个 etcd 成员。

    1. 连接到正在运行的 etcd 容器,传入不在受影响节点上的 Pod 的名称。

      在具有cluster-admin用户权限并可访问集群的终端中,运行以下命令:

      $ oc rsh -n openshift-etcd etcd-ip-10-0-154-204.ec2.internal
    2. 查看成员列表。

      sh-4.2# etcdctl member list -w table
      示例输出
      +------------------+---------+------------------------------+---------------------------+---------------------------+
      |        ID        | STATUS  |             NAME             |        PEER ADDRS         |       CLIENT ADDRS        |
      +------------------+---------+------------------------------+---------------------------+---------------------------+
      | 5eb0d6b8ca24730c | started |  ip-10-0-133-53.ec2.internal |  https://10.0.133.53:2380 |  https://10.0.133.53:2379 |
      | 757b6793e2408b6c | started |  ip-10-0-164-97.ec2.internal |  https://10.0.164.97:2380 |  https://10.0.164.97:2379 |
      | ca8c2990a0aa29d1 | started | ip-10-0-154-204.ec2.internal | https://10.0.154.204:2380 | https://10.0.154.204:2379 |
      +------------------+---------+------------------------------+---------------------------+---------------------------+

      如果先前命令的输出列出的 etcd 成员超过三个,则必须小心地删除不需要的成员。

      请务必删除正确的 etcd 成员;删除好的 etcd 成员可能会导致仲裁丢失。

替换 etcd Pod 处于循环崩溃状态的故障 etcd 成员

此过程详细介绍了替换由于 etcd Pod 处于循环崩溃状态而导致故障的 etcd 成员的步骤。

先决条件
  • 您已识别出故障的 etcd 成员。

  • 您已验证 etcd Pod 处于循环崩溃状态。

  • 您可以以具有 `cluster-admin` 角色的用户身份访问集群。

  • 您已进行了 etcd 备份。

    在执行此过程之前进行 etcd 备份非常重要,以便在遇到任何问题时可以恢复集群。

步骤
  1. 停止循环崩溃的 etcd Pod。

    1. 调试正在循环崩溃的节点。

      在具有cluster-admin用户权限并可访问集群的终端中,运行以下命令:

      $ oc debug node/ip-10-0-131-183.ec2.internal (1)
      1 将其替换为故障节点的名称。
    2. 将根目录更改为/host

      sh-4.2# chroot /host
    3. 将现有的 etcd Pod 文件移出 kubelet 清单目录。

      sh-4.2# mkdir /var/lib/etcd-backup
      sh-4.2# mv /etc/kubernetes/manifests/etcd-pod.yaml /var/lib/etcd-backup/
    4. 将 etcd 数据目录移动到其他位置。

      sh-4.2# mv /var/lib/etcd/ /tmp

      您现在可以退出节点 shell。

  2. 删除故障成员。

    1. 选择不在受影响节点上的 Pod。

      在具有cluster-admin用户权限并可访问集群的终端中,运行以下命令:

      $ oc -n openshift-etcd get pods -l k8s-app=etcd
      示例输出
      etcd-ip-10-0-131-183.ec2.internal                2/3     Error       7          6h9m
      etcd-ip-10-0-164-97.ec2.internal                 3/3     Running     0          6h6m
      etcd-ip-10-0-154-204.ec2.internal                3/3     Running     0          6h6m
    2. 连接到正在运行的 etcd 容器,传入不在受影响节点上的 Pod 的名称。

      在具有cluster-admin用户权限并可访问集群的终端中,运行以下命令:

      $ oc rsh -n openshift-etcd etcd-ip-10-0-154-204.ec2.internal
    3. 查看成员列表。

      sh-4.2# etcdctl member list -w table
      示例输出
      +------------------+---------+------------------------------+---------------------------+---------------------------+
      |        ID        | STATUS  |             NAME             |        PEER ADDRS         |       CLIENT ADDRS        |
      +------------------+---------+------------------------------+---------------------------+---------------------------+
      | 62bcf33650a7170a | started | ip-10-0-131-183.ec2.internal | https://10.0.131.183:2380 | https://10.0.131.183:2379 |
      | b78e2856655bc2eb | started |  ip-10-0-164-97.ec2.internal |  https://10.0.164.97:2380 |  https://10.0.164.97:2379 |
      | d022e10b498760d5 | started | ip-10-0-154-204.ec2.internal | https://10.0.154.204:2380 | https://10.0.154.204:2379 |
      +------------------+---------+------------------------------+---------------------------+---------------------------+

      记下故障 etcd 成员的 ID 和名称,因为这些值在后续过程中需要。

    4. 通过向etcdctl member remove命令提供 ID 来删除故障 etcd 成员。

      sh-4.2# etcdctl member remove 62bcf33650a7170a
      示例输出
      Member 62bcf33650a7170a removed from cluster ead669ce1fbfb346
    5. 再次查看成员列表,并验证成员是否已删除。

      sh-4.2# etcdctl member list -w table
      示例输出
      +------------------+---------+------------------------------+---------------------------+---------------------------+
      |        ID        | STATUS  |             NAME             |        PEER ADDRS         |       CLIENT ADDRS        |
      +------------------+---------+------------------------------+---------------------------+---------------------------+
      | b78e2856655bc2eb | started |  ip-10-0-164-97.ec2.internal |  https://10.0.164.97:2380 |  https://10.0.164.97:2379 |
      | d022e10b498760d5 | started | ip-10-0-154-204.ec2.internal | https://10.0.154.204:2380 | https://10.0.154.204:2379 |
      +------------------+---------+------------------------------+---------------------------+---------------------------+

      您现在可以退出节点 shell。

  3. 通过输入以下命令关闭仲裁保护:

    $ oc patch etcd/cluster --type=merge -p '{"spec": {"unsupportedConfigOverrides": {"useUnsupportedUnsafeNonHANonProductionUnstableEtcd": true}}}'

    此命令确保您可以成功重新创建密钥并推出静态 Pod。

  4. 删除已删除的故障 etcd 成员的旧密钥。

    1. 列出已删除的故障 etcd 成员的密钥。

      $ oc get secrets -n openshift-etcd | grep ip-10-0-131-183.ec2.internal (1)
      1 传入您在此过程前面记下的故障 etcd 成员的名称。

      如下所示,存在对等方、服务和指标密钥:

      示例输出
      etcd-peer-ip-10-0-131-183.ec2.internal              kubernetes.io/tls                     2      47m
      etcd-serving-ip-10-0-131-183.ec2.internal           kubernetes.io/tls                     2      47m
      etcd-serving-metrics-ip-10-0-131-183.ec2.internal   kubernetes.io/tls                     2      47m
    2. 删除已删除的故障 etcd 成员的密钥。

      1. 删除对等方密钥。

        $ oc delete secret -n openshift-etcd etcd-peer-ip-10-0-131-183.ec2.internal
      2. 删除服务密钥。

        $ oc delete secret -n openshift-etcd etcd-serving-ip-10-0-131-183.ec2.internal
      3. 删除指标密钥。

        $ oc delete secret -n openshift-etcd etcd-serving-metrics-ip-10-0-131-183.ec2.internal
  5. 强制 etcd 重新部署。

    在具有cluster-admin用户权限并可访问集群的终端中,运行以下命令:

    $ oc patch etcd cluster -p='{"spec": {"forceRedeploymentReason": "single-master-recovery-'"$( date --rfc-3339=ns )"'"}}' --type=merge (1)
    1 forceRedeploymentReason值必须唯一,这就是附加时间戳的原因。

    当 etcd 集群运算符执行重新部署时,它确保所有控制平面节点都具有功能正常的 etcd Pod。

  6. 通过输入以下命令重新打开仲裁保护:

    $ oc patch etcd/cluster --type=merge -p '{"spec": {"unsupportedConfigOverrides": null}}'
  7. 您可以通过输入此命令来验证unsupportedConfigOverrides部分是否已从对象中删除:

    $ oc get etcd/cluster -oyaml
  8. 如果您使用的是单节点 OpenShift,请重新启动节点。否则,您可能会在 etcd 集群运算符中遇到以下错误:

    示例输出
    EtcdCertSignerControllerDegraded: [Operation cannot be fulfilled on secrets "etcd-peer-sno-0": the object has been modified; please apply your changes to the latest version and try again, Operation cannot be fulfilled on secrets "etcd-serving-sno-0": the object has been modified; please apply your changes to the latest version and try again, Operation cannot be fulfilled on secrets "etcd-serving-metrics-sno-0": the object has been modified; please apply your changes to the latest version and try again]
验证
  • 验证新成员是否可用且健康。

    1. 再次连接到正在运行的 etcd 容器。

      在具有集群管理员用户权限的终端中,运行以下命令

      $ oc rsh -n openshift-etcd etcd-ip-10-0-154-204.ec2.internal
    2. 验证所有成员是否健康

      sh-4.2# etcdctl endpoint health
      示例输出
      https://10.0.131.183:2379 is healthy: successfully committed proposal: took = 16.671434ms
      https://10.0.154.204:2379 is healthy: successfully committed proposal: took = 16.698331ms
      https://10.0.164.97:2379 is healthy: successfully committed proposal: took = 16.621645ms

替换机器未运行或节点未就绪的不健康裸机 etcd 成员

此过程详细介绍了替换不健康裸机 etcd 成员的步骤,不健康的原因可能是机器未运行或节点未就绪。

如果您正在运行安装程序配置的基础架构,或者使用 Machine API 创建您的机器,请按照以下步骤操作。否则,您必须使用最初创建它的相同方法创建新的控制平面节点。

先决条件
  • 您已识别出不健康的裸机 etcd 成员。

  • 您已验证机器未运行或节点未就绪。

  • 您可以以具有 `cluster-admin` 角色的用户身份访问集群。

  • 您已进行了 etcd 备份。

    在执行此过程之前,您必须进行 etcd 备份,以便在遇到任何问题时可以恢复集群。

步骤
  1. 验证并删除不健康的成员。

    1. 选择不在受影响节点上的 Pod

      在具有cluster-admin用户权限并可访问集群的终端中,运行以下命令:

      $ oc -n openshift-etcd get pods -l k8s-app=etcd -o wide
      示例输出
      etcd-openshift-control-plane-0   5/5   Running   11   3h56m   192.168.10.9   openshift-control-plane-0  <none>           <none>
      etcd-openshift-control-plane-1   5/5   Running   0    3h54m   192.168.10.10   openshift-control-plane-1   <none>           <none>
      etcd-openshift-control-plane-2   5/5   Running   0    3h58m   192.168.10.11   openshift-control-plane-2   <none>           <none>
    2. 连接到正在运行的 etcd 容器,传入不在受影响节点上的 Pod 的名称。

      在具有cluster-admin用户权限并可访问集群的终端中,运行以下命令:

      $ oc rsh -n openshift-etcd etcd-openshift-control-plane-0
    3. 查看成员列表。

      sh-4.2# etcdctl member list -w table
      示例输出
      +------------------+---------+--------------------+---------------------------+---------------------------+---------------------+
      | ID               | STATUS  | NAME                      | PEER ADDRS                  | CLIENT ADDRS                | IS LEARNER |
      +------------------+---------+--------------------+---------------------------+---------------------------+---------------------+
      | 7a8197040a5126c8 | started | openshift-control-plane-2 | https://192.168.10.11:2380/ | https://192.168.10.11:2379/ | false |
      | 8d5abe9669a39192 | started | openshift-control-plane-1 | https://192.168.10.10:2380/ | https://192.168.10.10:2379/ | false |
      | cc3830a72fc357f9 | started | openshift-control-plane-0 | https://192.168.10.9:2380/ | https://192.168.10.9:2379/   | false |
      +------------------+---------+--------------------+---------------------------+---------------------------+---------------------+

      记下不健康 etcd 成员的 ID 和名称,因为这些值在后面的过程中需要。在替换过程完成并添加新成员之前,etcdctl endpoint health 命令将列出已删除的成员。

    4. 通过向etcdctl member remove命令提供 ID 来删除故障 etcd 成员。

      请务必删除正确的 etcd 成员;删除好的 etcd 成员可能会导致仲裁丢失。

      sh-4.2# etcdctl member remove 7a8197040a5126c8
      示例输出
      Member 7a8197040a5126c8 removed from cluster b23536c33f2cdd1b
    5. 再次查看成员列表,并验证成员是否已删除。

      sh-4.2# etcdctl member list -w table
      示例输出
      +------------------+---------+--------------------+---------------------------+---------------------------+-------------------------+
      | ID               | STATUS  | NAME                      | PEER ADDRS                  | CLIENT ADDRS                | IS LEARNER |
      +------------------+---------+--------------------+---------------------------+---------------------------+-------------------------+
      | cc3830a72fc357f9 | started | openshift-control-plane-2 | https://192.168.10.11:2380/ | https://192.168.10.11:2379/ | false |
      | 8d5abe9669a39192 | started | openshift-control-plane-1 | https://192.168.10.10:2380/ | https://192.168.10.10:2379/ | false |
      +------------------+---------+--------------------+---------------------------+---------------------------+-------------------------+

      您现在可以退出节点 shell。

      删除成员后,集群可能在剩余的 etcd 实例重新启动期间短暂不可访问。

  2. 通过输入以下命令关闭仲裁保护:

    $ oc patch etcd/cluster --type=merge -p '{"spec": {"unsupportedConfigOverrides": {"useUnsupportedUnsafeNonHANonProductionUnstableEtcd": true}}}'

    此命令确保您可以成功重新创建密钥并推出静态 Pod。

  3. 运行以下命令删除已删除的不健康 etcd 成员的旧密钥。

    1. 列出已删除的故障 etcd 成员的密钥。

      $ oc get secrets -n openshift-etcd | grep openshift-control-plane-2

      传入您在此过程前面记下的故障 etcd 成员的名称。

      如下所示,存在对等方、服务和指标密钥:

      etcd-peer-openshift-control-plane-2             kubernetes.io/tls   2   134m
      etcd-serving-metrics-openshift-control-plane-2  kubernetes.io/tls   2   134m
      etcd-serving-openshift-control-plane-2          kubernetes.io/tls   2   134m
    2. 删除已删除的故障 etcd 成员的密钥。

      1. 删除对等方密钥。

        $ oc delete secret etcd-peer-openshift-control-plane-2 -n openshift-etcd
        
        secret "etcd-peer-openshift-control-plane-2" deleted
      2. 删除服务密钥。

        $ oc delete secret etcd-serving-metrics-openshift-control-plane-2 -n openshift-etcd
        
        secret "etcd-serving-metrics-openshift-control-plane-2" deleted
      3. 删除指标密钥。

        $ oc delete secret etcd-serving-openshift-control-plane-2 -n openshift-etcd
        
        secret "etcd-serving-openshift-control-plane-2" deleted
  4. 获取故障成员的机器。

    在具有cluster-admin用户权限并可访问集群的终端中,运行以下命令:

    $ oc get machines -n openshift-machine-api -o wide
    示例输出
    NAME                              PHASE     TYPE   REGION   ZONE   AGE     NODE                               PROVIDERID                                                                                              STATE
    examplecluster-control-plane-0    Running                          3h11m   openshift-control-plane-0   baremetalhost:///openshift-machine-api/openshift-control-plane-0/da1ebe11-3ff2-41c5-b099-0aa41222964e   externally provisioned (1)
    examplecluster-control-plane-1    Running                          3h11m   openshift-control-plane-1   baremetalhost:///openshift-machine-api/openshift-control-plane-1/d9f9acbc-329c-475e-8d81-03b20280a3e1   externally provisioned
    examplecluster-control-plane-2    Running                          3h11m   openshift-control-plane-2   baremetalhost:///openshift-machine-api/openshift-control-plane-2/3354bdac-61d8-410f-be5b-6a395b056135   externally provisioned
    examplecluster-compute-0          Running                          165m    openshift-compute-0         baremetalhost:///openshift-machine-api/openshift-compute-0/3d685b81-7410-4bb3-80ec-13a31858241f         provisioned
    examplecluster-compute-1          Running                          165m    openshift-compute-1         baremetalhost:///openshift-machine-api/openshift-compute-1/0fdae6eb-2066-4241-91dc-e7ea72ab13b9         provisioned
    1 这是不健康节点的控制平面机器,examplecluster-control-plane-2
  5. 通过运行以下命令确保 Bare Metal Operator 可用

    $ oc get clusteroperator baremetal
    示例输出
    NAME        VERSION   AVAILABLE   PROGRESSING   DEGRADED   SINCE   MESSAGE
    baremetal   4.17.0    True        False         False      3d15h
  6. 运行以下命令删除旧的 BareMetalHost 对象

    $ oc delete bmh openshift-control-plane-2 -n openshift-machine-api
    示例输出
    baremetalhost.metal3.io "openshift-control-plane-2" deleted
  7. 运行以下命令删除不健康成员的机器

    $ oc delete machine -n openshift-machine-api examplecluster-control-plane-2

    删除 BareMetalHostMachine 对象后,Machine 控制器会自动删除 Node 对象。

    如果由于任何原因机器删除延迟,或命令被阻塞和延迟,您可以通过删除机器对象的 finalizer 字段来强制删除。

    不要按 Ctrl+c 中断机器删除。您必须允许命令继续执行到完成。打开一个新的终端窗口来编辑和删除 finalizer 字段。

    删除故障成员的机器后,将自动预配一台新机器。

    1. 运行以下命令编辑机器配置

      $ oc edit machine -n openshift-machine-api examplecluster-control-plane-2
    2. 删除 Machine 自定义资源中的以下字段,然后保存更新后的文件

      finalizers:
      - machine.machine.openshift.io
      示例输出
      machine.machine.openshift.io/examplecluster-control-plane-2 edited
  8. 运行以下命令验证机器是否已删除

    $ oc get machines -n openshift-machine-api -o wide
    示例输出
    NAME                              PHASE     TYPE   REGION   ZONE   AGE     NODE                                 PROVIDERID                                                                                       STATE
    examplecluster-control-plane-0    Running                          3h11m   openshift-control-plane-0   baremetalhost:///openshift-machine-api/openshift-control-plane-0/da1ebe11-3ff2-41c5-b099-0aa41222964e   externally provisioned
    examplecluster-control-plane-1    Running                          3h11m   openshift-control-plane-1   baremetalhost:///openshift-machine-api/openshift-control-plane-1/d9f9acbc-329c-475e-8d81-03b20280a3e1   externally provisioned
    examplecluster-compute-0          Running                          165m    openshift-compute-0         baremetalhost:///openshift-machine-api/openshift-compute-0/3d685b81-7410-4bb3-80ec-13a31858241f         provisioned
    examplecluster-compute-1          Running                          165m    openshift-compute-1         baremetalhost:///openshift-machine-api/openshift-compute-1/0fdae6eb-2066-4241-91dc-e7ea72ab13b9         provisioned
  9. 运行以下命令验证节点是否已删除

    $ oc get nodes
    
    NAME                     STATUS ROLES   AGE   VERSION
    openshift-control-plane-0 Ready master 3h24m v1.30.3
    openshift-control-plane-1 Ready master 3h24m v1.30.3
    openshift-compute-0       Ready worker 176m v1.30.3
    openshift-compute-1       Ready worker 176m v1.30.3
  10. 创建新的 BareMetalHost 对象和用于存储 BMC 凭据的密钥

    $ cat <<EOF | oc apply -f -
    apiVersion: v1
    kind: Secret
    metadata:
      name: openshift-control-plane-2-bmc-secret
      namespace: openshift-machine-api
    data:
      password: <password>
      username: <username>
    type: Opaque
    ---
    apiVersion: metal3.io/v1alpha1
    kind: BareMetalHost
    metadata:
      name: openshift-control-plane-2
      namespace: openshift-machine-api
    spec:
      automatedCleaningMode: disabled
      bmc:
        address: redfish://10.46.61.18:443/redfish/v1/Systems/1
        credentialsName: openshift-control-plane-2-bmc-secret
        disableCertificateVerification: true
      bootMACAddress: 48:df:37:b0:8a:a0
      bootMode: UEFI
      externallyProvisioned: false
      online: true
      rootDeviceHints:
        deviceName: /dev/disk/by-id/scsi-<serial_number>
      userData:
        name: master-user-data-managed
        namespace: openshift-machine-api
    EOF

    用户名和密码可以从其他裸机主机的密钥中找到。bmc:address 中使用的协议可以从其他 bmh 对象中获取。

    如果重用现有控制平面主机的 BareMetalHost 对象定义,请不要将 externallyProvisioned 字段设置为 true

    如果现有控制平面 BareMetalHost 对象是由 OpenShift Container Platform 安装程序配置的,则其 externallyProvisioned 标志可能设置为 true

    检查完成后,BareMetalHost 对象将被创建并可供配置。

  11. 使用可用的 BareMetalHost 对象验证创建过程

    $ oc get bmh -n openshift-machine-api
    
    NAME                      STATE                  CONSUMER                      ONLINE ERROR   AGE
    openshift-control-plane-0 externally provisioned examplecluster-control-plane-0 true         4h48m
    openshift-control-plane-1 externally provisioned examplecluster-control-plane-1 true         4h48m
    openshift-control-plane-2 available              examplecluster-control-plane-3 true         47m
    openshift-compute-0       provisioned            examplecluster-compute-0       true         4h48m
    openshift-compute-1       provisioned            examplecluster-compute-1       true         4h48m
    1. 验证是否已创建新机器。

      $ oc get machines -n openshift-machine-api -o wide
      示例输出
      NAME                                   PHASE     TYPE   REGION   ZONE   AGE     NODE                              PROVIDERID                                                                                            STATE
      examplecluster-control-plane-0         Running                          3h11m   openshift-control-plane-0   baremetalhost:///openshift-machine-api/openshift-control-plane-0/da1ebe11-3ff2-41c5-b099-0aa41222964e   externally provisioned (1)
      examplecluster-control-plane-1         Running                          3h11m   openshift-control-plane-1   baremetalhost:///openshift-machine-api/openshift-control-plane-1/d9f9acbc-329c-475e-8d81-03b20280a3e1   externally provisioned
      examplecluster-control-plane-2         Running                          3h11m   openshift-control-plane-2   baremetalhost:///openshift-machine-api/openshift-control-plane-2/3354bdac-61d8-410f-be5b-6a395b056135   externally provisioned
      examplecluster-compute-0               Running                          165m    openshift-compute-0         baremetalhost:///openshift-machine-api/openshift-compute-0/3d685b81-7410-4bb3-80ec-13a31858241f         provisioned
      examplecluster-compute-1               Running                          165m    openshift-compute-1         baremetalhost:///openshift-machine-api/openshift-compute-1/0fdae6eb-2066-4241-91dc-e7ea72ab13b9         provisioned
      1 新的机器 clustername-8qw5l-master-3 正在创建中,在阶段从 Provisioning 变为 Running 后即可使用。

      创建新机器可能需要几分钟时间。当机器或节点恢复到健康状态时,etcd 集群 Operator 将自动同步。

    2. 运行以下命令验证裸机主机是否已配置以及是否未报告任何错误

      $ oc get bmh -n openshift-machine-api
      示例输出
      $ oc get bmh -n openshift-machine-api
      NAME                      STATE                  CONSUMER                       ONLINE ERROR AGE
      openshift-control-plane-0 externally provisioned examplecluster-control-plane-0 true         4h48m
      openshift-control-plane-1 externally provisioned examplecluster-control-plane-1 true         4h48m
      openshift-control-plane-2 provisioned            examplecluster-control-plane-3 true          47m
      openshift-compute-0       provisioned            examplecluster-compute-0       true         4h48m
      openshift-compute-1       provisioned            examplecluster-compute-1       true         4h48m
    3. 运行此命令验证新节点是否已添加并处于就绪状态

      $ oc get nodes
      示例输出
      $ oc get nodes
      NAME                     STATUS ROLES   AGE   VERSION
      openshift-control-plane-0 Ready master 4h26m v1.30.3
      openshift-control-plane-1 Ready master 4h26m v1.30.3
      openshift-control-plane-2 Ready master 12m   v1.30.3
      openshift-compute-0       Ready worker 3h58m v1.30.3
      openshift-compute-1       Ready worker 3h58m v1.30.3
  12. 通过输入以下命令重新打开仲裁保护:

    $ oc patch etcd/cluster --type=merge -p '{"spec": {"unsupportedConfigOverrides": null}}'
  13. 您可以通过输入此命令来验证unsupportedConfigOverrides部分是否已从对象中删除:

    $ oc get etcd/cluster -oyaml
  14. 如果您使用的是单节点 OpenShift,请重新启动节点。否则,您可能会在 etcd 集群运算符中遇到以下错误:

    示例输出
    EtcdCertSignerControllerDegraded: [Operation cannot be fulfilled on secrets "etcd-peer-sno-0": the object has been modified; please apply your changes to the latest version and try again, Operation cannot be fulfilled on secrets "etcd-serving-sno-0": the object has been modified; please apply your changes to the latest version and try again, Operation cannot be fulfilled on secrets "etcd-serving-metrics-sno-0": the object has been modified; please apply your changes to the latest version and try again]
验证
  1. 验证所有 etcd Pod 是否正在正常运行。

    在具有cluster-admin用户权限并可访问集群的终端中,运行以下命令:

    $ oc -n openshift-etcd get pods -l k8s-app=etcd
    示例输出
    etcd-openshift-control-plane-0      5/5     Running     0     105m
    etcd-openshift-control-plane-1      5/5     Running     0     107m
    etcd-openshift-control-plane-2      5/5     Running     0     103m

    如果先前命令的输出仅列出两个 Pod,您可以手动强制 etcd 重新部署。在具有cluster-admin用户权限并可访问集群的终端中,运行以下命令:

    $ oc patch etcd cluster -p='{"spec": {"forceRedeploymentReason": "recovery-'"$( date --rfc-3339=ns )"'"}}' --type=merge (1)
    1 forceRedeploymentReason值必须唯一,这就是附加时间戳的原因。

    要验证是否存在三个 etcd 成员,请连接到正在运行的 etcd 容器,传入未在受影响节点上的 pod 的名称。在具有集群管理员用户权限的终端中,运行以下命令

    $ oc rsh -n openshift-etcd etcd-openshift-control-plane-0
  2. 查看成员列表。

    sh-4.2# etcdctl member list -w table
    示例输出
    +------------------+---------+--------------------+---------------------------+---------------------------+-----------------+
    |        ID        | STATUS  |        NAME        |        PEER ADDRS         |       CLIENT ADDRS        |    IS LEARNER    |
    +------------------+---------+--------------------+---------------------------+---------------------------+-----------------+
    | 7a8197040a5126c8 | started | openshift-control-plane-2 | https://192.168.10.11:2380 | https://192.168.10.11:2379 |   false |
    | 8d5abe9669a39192 | started | openshift-control-plane-1 | https://192.168.10.10:2380 | https://192.168.10.10:2379 |   false |
    | cc3830a72fc357f9 | started | openshift-control-plane-0 | https://192.168.10.9:2380 | https://192.168.10.9:2379 |     false |
    +------------------+---------+--------------------+---------------------------+---------------------------+-----------------+

    如果先前命令的输出列出的 etcd 成员超过三个,则必须小心地删除不需要的成员。

  3. 运行以下命令验证所有 etcd 成员是否健康

    # etcdctl endpoint health --cluster
    示例输出
    https://192.168.10.10:2379 is healthy: successfully committed proposal: took = 8.973065ms
    https://192.168.10.9:2379 is healthy: successfully committed proposal: took = 11.559829ms
    https://192.168.10.11:2379 is healthy: successfully committed proposal: took = 11.665203ms
  4. 运行以下命令验证所有节点是否处于最新版本

    $ oc get etcd -o=jsonpath='{range.items[0].status.conditions[?(@.type=="NodeInstallerProgressing")]}{.reason}{"\n"}{.message}{"\n"}'
    AllNodesAtLatestRevision