3.2. 恢复丢失的 master 主机

本文档描述了恢复已完全丢失的 master 主机的过程。这包括大多数 master 主机已丢失并导致etcd仲裁(quorum)丢失,并且集群已下线的情况。这个步骤假设至少有一个健康的 master 主机。

总体来说,这个流程将:

  1. 在一个仍存在的 master 主机上恢复etcd仲裁。
  2. 创建新的 master 主机。
  3. 修正DNS和负载均衡器条目。
  4. 将etcd扩展到集群中的所有成员。

如果大多数 master 都已丢失,则需要 etcd 备份来在剩余的 master 主机上恢复 etcd 仲裁。

注意

如果大多数 master 仍可用,且仍有 etcd 仲裁,请按照以下步骤替换单个失败的 master 主机

3.2.1. 恢复丢失的 master 主机

当因为丢失了大多数 master 主机并导致 etcd 仲裁丢失时,按照以下步骤进行恢复。

先决条件

  • 使用具有 cluster-admin 角色的用户访问集群。
  • 可以 SSH 到仍存在的 master 主机。
  • 包含从同一备份中获取的 etcd 快照和静态 Kubernetes API 服务器资源的备份目录。该目录中的文件名必须采用以下格式: snapshot_<datetimestamp>.db 和 static_kuberesources_<datetimestamp>.tar.gz

    注意

    如果 etcd 备份是对 OpenShift Container Platform 4.3.0 或 4.3.1 进行的,那么它会是一个单一的文件,其中包含 etcd 快照和静态 Kubernetes API 服务器资源。etcd-snapshot-restore.sh 可以向后兼容来接受这个单一的文件,它的格式需要是 snapshot_db_kuberesources_<datetimestamp>.tar.gz

流程

  1. 在仍存在的 master 主机上恢复etcd仲裁。

    1. 将 etcd 备份目录复制到仍然存在的 master 主机上。

      此流程假设您将 backup 目录(其中包含 etcd 快照和静态 Kubernetes API 服务器资源)复制到 master 主机的 /home/core/ 目录中。

    2. 访问仍存在的 master 主机。
    3. INITIAL_CLUSTER变量设置为以<name>=<url>格式代表的成员列表。此变量将会被传递给恢复脚本。在此假定此时只有一个成员。

      [core@ip-10-0-143-125 ~]$ export INITIAL_CLUSTER="etcd-member-ip-10-0-143-125.ec2.internal=https://etcd-0.clustername.devcluster.openshift.com:2380"
    4. 如果启用了集群范围的代理,请确定已导出了 NO_PROXYHTTP_PROXYHTTPS_PROXY 环境变量。

      提示

      您可以通过查看 oc get proxy cluster -o yaml 的输出来检查代理是否已启用。如果 httpProxyhttpsProxynoProxy 字段设置了值,则会启用代理。

    5. 运行etcd-snapshot-restore.sh脚本。

      将两个参数传递给etcd-snapshot-restore.sh脚本:etcd 备份目录的路径,成员列表(由INITIAL_CLUSTER变量定义)。

      确保在sudo中使用-E以便将环境变量正确传递给脚本。

      [core@ip-10-0-143-125 ~]$ sudo -E /usr/local/bin/etcd-snapshot-restore.sh /home/core/backup $INITIAL_CLUSTER
      Creating asset directory ./assets
      Downloading etcdctl binary..
      etcdctl version: 3.3.10
      API version: 3.3
      Backing up /etc/kubernetes/manifests/etcd-member.yaml to ./assets/backup/
      Stopping all static pods..
      ..stopping kube-scheduler-pod.yaml
      ..stopping kube-controller-manager-pod.yaml
      ..stopping kube-apiserver-pod.yaml
      ..stopping etcd-member.yaml
      Stopping etcd..
      Waiting for etcd-member to stop
      Stopping kubelet..
      Stopping all containers..
      bd44e4bc942276eb1a6d4b48ecd9f5fe95570f54aa9c6b16939fa2d9b679e1ea
      d88defb9da5ae623592b81619e3690faeb4fa645440e71c029812cb960ff586f
      3920ced20723064a379739c4a586f909497a7b6705a5b3cf367d9b930f23a5f1
      d470f7a2d962c90f3a21bcc021970bde96bc8908f317ec70f1c21720b322c25c
      Backing up etcd data-dir..
      Removing etcd data-dir /var/lib/etcd
      Restoring etcd member etcd-member-ip-10-0-143-125.ec2.internal from snapshot..
      2019-05-15 19:03:34.647589 I | pkg/netutil: resolving etcd-0.clustername.devcluster.openshift.com:2380 to 10.0.143.125:2380
      2019-05-15 19:03:34.883545 I | mvcc: restore compact to 361491
      2019-05-15 19:03:34.915679 I | etcdserver/membership: added member cbe982c74cbb42f [https://etcd-0.clustername.devcluster.openshift.com:2380] to cluster 807ae3bffc8d69ca
      Starting static pods..
      ..starting kube-scheduler-pod.yaml
      ..starting kube-controller-manager-pod.yaml
      ..starting kube-apiserver-pod.yaml
      ..starting etcd-member.yaml
      Starting kubelet..

      一旦etcd-snapshot-restore.sh脚本完成,您的集群将会有带有一个etcd成员的集群,API服务将开始重新启动。这可能需要15分钟。

      在一个已连接到集群的终端中,运行以下命令验证它是否已准备就绪:

      $ oc get nodes -l node-role.kubernetes.io/master
      NAME                                         STATUS   ROLES    AGE   VERSION
      ip-10-0-143-125.us-east-2.compute.internal   Ready    master   46m   v1.16.2
      注意

      确保所有被替换的旧etcd成员都已被关闭。否则,它们可能会尝试连接到新集群,并在日志中报告以下错误:

      2019-05-20 15:33:17.648445 E | rafthttp: request cluster ID mismatch (got 9f5f9f05e4d43b7f want 807ae3bffc8d69ca)
  2. 创建新的 master 主机。

    如果集群启用了 Machine API 且可以正常运行,则当 OpenShift machine-api Operator 被恢复后,它将会创建新的 master。如果未启用machine-api Operator,则必须使用最初创建它们时使用的相同方法创建新的 master。

    您还需要批准这些新 master 主机的证书签名请求(CSR)。为添加到集群中的每个系统生成两个待处理的CSR。

    1. 在一个已连接到集群的终端中,运行以下命令验证来批准 CSR:

      1. 获取当前CSR列表。

        $ oc get csr
      2. 查看CSR的详细信息以验证其是否有效。

        $ oc describe csr <csr_name> 1
        1
        <csr_name>是当前CSR列表中CSR的名称。
      3. 批准每个有效的CSR。

        $ oc adm certificate approve <csr_name>

        确保为添加到集群的每个主服务器批准待处理的客户端和服务器CSR。

    2. 在一个已连接到集群的终端中,运行以下命令验证 master 已准备就绪:

      $ oc get nodes -l node-role.kubernetes.io/master
      NAME                                         STATUS   ROLES    AGE   VERSION
      ip-10-0-143-125.us-east-2.compute.internal   Ready    master   50m   v1.16.2
      ip-10-0-156-255.us-east-2.compute.internal   Ready    master   92s   v1.16.2
      ip-10-0-162-178.us-east-2.compute.internal   Ready    master   70s   v1.16.2
  3. 更正DNS条目。

    1. 在AWS控制台中,查看私有DNS区域中的etcd-0,etcd-1和etcd-2 Route 53记录,如有必要,将值更新为相应的新私有IP地址。详情请参阅AWS文档中的编辑记录部分 。

      在已连接到集群的终端中运行以下命令来获取实例的私有IP地址。

      $ oc get node ip-10-0-143-125.us-east-2.compute.internal -o  jsonpath='{.status.addresses[?(@.type=="InternalIP")].address}{"\n"}'
      10.0.143.125
  4. 更新负载均衡器条目。

    如果您使用由集群管理的负载均衡器,相关条目会被自动更新。如果没有使用由集群管理的负载均衡器,则需要手工为负载均衡器更新 master 主机的信息。

    如果您的负载均衡功能由AWS管理,请参阅AWS文档中的按IP地址注册或取消注册目标部分。

  5. 将etcd扩展到集群中的所有成员。

    1. 在您已恢复etcd的master上设置临时etcd证书 signer 服务。

      1. 访问原始 master,使用以下命令以 cluster-admin用户身份登录到您的集群。

        [core@ip-10-0-143-125 ~]$ sudo oc login https://localhost:6443
        Authentication required for https://localhost:6443 (openshift)
        Username: kubeadmin
        Password:
        Login successful.
      2. 获取kube-etcd-signer-server镜像的pull规范。

        [core@ip-10-0-143-125 ~]$ export KUBE_ETCD_SIGNER_SERVER=$(sudo oc adm release info --image-for kube-etcd-signer-server --registry-config=/var/lib/kubelet/config.json)
      3. 运行tokenize-signer.sh脚本。

        确保在sudo中使用-E以便将环境变量正确传递给脚本。

        [core@ip-10-0-143-125 ~]$ sudo -E /usr/local/bin/tokenize-signer.sh ip-10-0-143-125 1
        Populating template /usr/local/share/openshift-recovery/template/kube-etcd-cert-signer.yaml.template
        Populating template ./assets/tmp/kube-etcd-cert-signer.yaml.stage1
        Tokenized template now ready: ./assets/manifests/kube-etcd-cert-signer.yaml
        1
        刚恢复的原始 master 的主机名,signer 需要在这个主机上部署。
      4. 使用生成的文件创建 signer Pod。

        [core@ip-10-0-143-125 ~]$ sudo oc create -f assets/manifests/kube-etcd-cert-signer.yaml
        pod/etcd-signer created
      5. 确定 signer 在监听 master 节点。

        [core@ip-10-0-143-125 ~]$ ss -ltn | grep 9943
        LISTEN   0         128                       *:9943                   *:*
    2. 将新的 master 主机添加到 etcd 集群。

      1. 访问新 master 主机中的一个,使用以下命令以 cluster-admin用户身份登录集群。

        [core@ip-10-0-156-255 ~]$ sudo oc login https://localhost:6443
        Authentication required for https://localhost:6443 (openshift)
        Username: kubeadmin
        Password:
        Login successful.
      2. 导出etcd-member-recover.sh脚本所需的两个环境变量。

        [core@ip-10-0-156-255 ~]$ export SETUP_ETCD_ENVIRONMENT=$(sudo oc adm release info --image-for machine-config-operator --registry-config=/var/lib/kubelet/config.json)
        [core@ip-10-0-156-255 ~]$ export KUBE_CLIENT_AGENT=$(sudo oc adm release info --image-for kube-client-agent --registry-config=/var/lib/kubelet/config.json)
      3. 运行etcd-member-recover.sh脚本。

        确保在sudo中使用-E以便将环境变量正确传递给脚本。

        [core@ip-10-0-156-255 ~]$ sudo -E /usr/local/bin/etcd-member-recover.sh 10.0.143.125 etcd-member-ip-10-0-156-255.ec2.internal 1
        Downloading etcdctl binary..
        etcdctl version: 3.3.10
        API version: 3.3
        etcd-member.yaml found in ./assets/backup/
        etcd.conf backup upready exists ./assets/backup/etcd.conf
        Trying to backup etcd client certs..
        etcd client certs already backed up and available ./assets/backup/
        Stopping etcd..
        Waiting for etcd-member to stop
        etcd data-dir backup found ./assets/backup/etcd..
        etcd TLS certificate backups found in ./assets/backup..
        Removing etcd certs..
        Populating template /usr/local/share/openshift-recovery/template/etcd-generate-certs.yaml.template
        Populating template ./assets/tmp/etcd-generate-certs.stage1
        Populating template ./assets/tmp/etcd-generate-certs.stage2
        Starting etcd client cert recovery agent..
        Waiting for certs to generate..
        Waiting for certs to generate..
        Waiting for certs to generate..
        Waiting for certs to generate..
        Stopping cert recover..
        Waiting for generate-certs to stop
        Patching etcd-member manifest..
        Updating etcd membership..
        Member 249a4b9a790b3719 added to cluster 807ae3bffc8d69ca
        
        ETCD_NAME="etcd-member-ip-10-0-156-255.ec2.internal"
        ETCD_INITIAL_CLUSTER="etcd-member-ip-10-0-143-125.ec2.internal=https://etcd-0.clustername.devcluster.openshift.com:2380,etcd-member-ip-10-0-156-255.ec2.internal=https://etcd-1.clustername.devcluster.openshift.com:2380"
        ETCD_INITIAL_ADVERTISE_PEER_URLS="https://etcd-1.clustername.devcluster.openshift.com:2380"
        ETCD_INITIAL_CLUSTER_STATE="existing"
        Starting etcd..
        1
        指定 signer 服务器运行的原始 master 的 IP 地址和新成员的 etcd 名称。
      4. 验证新 master 主机已被添加到etcd成员列表中。

        1. 访问原始 master,连接到正在运行的etcd容器。

          [core@ip-10-0-143-125 ~] id=$(sudo crictl ps --name etcd-member | awk 'FNR==2{ print $1}') && sudo crictl exec -it $id /bin/sh
        2. 在 etcd 容器中,导出连接到 etcd 所需的变量。

          sh-4.3# export ETCDCTL_API=3 ETCDCTL_CACERT=/etc/ssl/etcd/ca.crt ETCDCTL_CERT=$(find /etc/ssl/ -name *peer*crt) ETCDCTL_KEY=$(find /etc/ssl/ -name *peer*key)
        3. 在etcd容器中,执行etcdctl member list并确定列出了新成员。

          sh-4.3#  etcdctl member list -w table
          
          +------------------+---------+------------------------------------------+----------------------------------------------------------------+---------------------------+
          |        ID        | STATUS  |                   NAME                   |                           PEER ADDRS                           |       CLIENT ADDRS        |
          +------------------+---------+------------------------------------------+----------------------------------------------------------------+---------------------------+
          |  cbe982c74cbb42f | started |  etcd-member-ip-10-0-156-255.ec2.internal | https://etcd-0.clustername.devcluster.openshift.com:2380 |  https://10.0.156.255:2379 |
          | 249a4b9a790b3719 | started | etcd-member-ip-10-0-143-125.ec2.internal | https://etcd-1.clustername.devcluster.openshift.com:2380 | https://10.0.143.125:2379 |
          +------------------+---------+------------------------------------------+----------------------------------------------------------------+---------------------------+

          请注意,新成员最多可能需要 20 分钟才能启动。

      5. 重复这些步骤以添加其他新的 master 主机,直到完成所有的 etcd 成员。
    3. 当所有成员都被恢复后,请删除 signer pod,因为不再需要它。

      在一个已连接到集群的终端中,运行以下命令:

      $ oc delete pod -n openshift-config etcd-signer

请注意,在完成这个过程后,可能需要几分钟才能恢复所有服务。例如,在重启 OAuth 服务器 Pod 前,使用 oc login 进行身份验证可能无法立即正常工作。