5.3.2.2. 恢复到一个以前的集群状态

您可以使用已保存的 etcd 备份来恢复以前的集群状态,或者恢复丢失了大多数 control plane 主机(也称为 master 主机)的集群。

重要

恢复集群时,必须使用同一 z-stream 发行版本中获取的 etcd 备份。例如,OpenShift Container Platform 4.6.2 集群必须使用从 4.6.2 进行的 etcd 备份。

先决条件

  • 使用具有 cluster-admin 角色的用户访问集群。
  • 用作恢复主机的健康 control plane 主机。
  • SSH 对 control plane 主机的访问。
  • 包含从同一备份中获取的 etcd 快照和静态 pod 资源的备份目录。该目录中的文件名必须采用以下格式: snapshot_<datetimestamp>.db 和 static_kuberesources_<datetimestamp>.tar.gz
重要

对于非恢复 control plane 节点,不需要建立 SSH 连接或停止静态 pod。您可以逐个删除并重新创建其他非恢复 control plane 机器。

步骤

  1. 选择一个要用作恢复主机的 control plane 主机。这是您要在其中运行恢复操作的主机。
  2. 建立到每个 control plane 节点(包括恢复主机)的 SSH 连接。

    恢复过程启动后,Kubernetes API 服务器将无法访问,因此您无法访问 control plane 节点。因此,建议在一个单独的终端中建立到每个control plane 主机的 SSH 连接。

    重要

    如果没有完成这个步骤,将无法访问 control plane 主机来完成恢复过程,您将无法从这个状态恢复集群。

  3. 将 etcd 备份目录复制复制到恢复 control plane 主机上。

    此流程假设您将 backup 目录(其中包含 etcd 快照和静态 pod 资源)复制到恢复 control plane 主机的 /home/core/ 目录中。

  4. 在任何其他 control plane 节点上停止静态 pod。

    注意

    不需要手动停止恢复主机上的 pod。恢复脚本将停止恢复主机上的 pod。

    1. 访问不是恢复主机的 control plane 主机。
    2. 将现有 etcd pod 文件从 Kubelet 清单目录中移出:

      $ sudo mv /etc/kubernetes/manifests/etcd-pod.yaml /tmp
    3. 验证 etcd pod 是否已停止。

      $ sudo crictl ps | grep etcd | grep -v operator

      命令输出应该为空。如果它不是空的,请等待几分钟后再重新检查。

    4. 将现有 Kubernetes API 服务器 pod 文件移出 kubelet 清单目录中:

      $ sudo mv /etc/kubernetes/manifests/kube-apiserver-pod.yaml /tmp
    5. 验证 Kubernetes API 服务器 pod 是否已停止。

      $ sudo crictl ps | grep kube-apiserver | grep -v operator

      命令输出应该为空。如果它不是空的,请等待几分钟后再重新检查。

    6. 将 etcd 数据目录移到不同的位置:

      $ sudo mv /var/lib/etcd/ /tmp
    7. 在其他不是恢复主机的 control plane 主机上重复此步骤。
  5. 访问恢复 control plane 主机。
  6. 如果启用了集群范围的代理,请确定已导出了 NO_PROXYHTTP_PROXYHTTPS_PROXY 环境变量。

    提示

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

  7. 在恢复 control plane 主机上运行恢复脚本,提供到 etcd 备份目录的路径:

    $ sudo -E /usr/local/bin/cluster-restore.sh /home/core/backup

    脚本输出示例

    ...stopping kube-scheduler-pod.yaml
    ...stopping kube-controller-manager-pod.yaml
    ...stopping etcd-pod.yaml
    ...stopping kube-apiserver-pod.yaml
    Waiting for container etcd to stop
    .complete
    Waiting for container etcdctl to stop
    .............................complete
    Waiting for container etcd-metrics to stop
    complete
    Waiting for container kube-controller-manager to stop
    complete
    Waiting for container kube-apiserver to stop
    ..........................................................................................complete
    Waiting for container kube-scheduler to stop
    complete
    Moving etcd data-dir /var/lib/etcd/member to /var/lib/etcd-backup
    starting restore-etcd static pod
    starting kube-apiserver-pod.yaml
    static-pod-resources/kube-apiserver-pod-7/kube-apiserver-pod.yaml
    starting kube-controller-manager-pod.yaml
    static-pod-resources/kube-controller-manager-pod-7/kube-controller-manager-pod.yaml
    starting kube-scheduler-pod.yaml
    static-pod-resources/kube-scheduler-pod-8/kube-scheduler-pod.yaml

    注意

    如果在最后的 etcd 备份后更新节点,恢复过程可能会导致节点进入 NotReady 状态。

  8. 检查节点以确保它们处于 Ready 状态。

    1. 运行以下命令:

      $ oc get nodes -w

      输出示例

      NAME                STATUS  ROLES          AGE     VERSION
      host-172-25-75-28   Ready   master         3d20h   v1.23.3+e419edf
      host-172-25-75-38   Ready   infra,worker   3d20h   v1.23.3+e419edf
      host-172-25-75-40   Ready   master         3d20h   v1.23.3+e419edf
      host-172-25-75-65   Ready   master         3d20h   v1.23.3+e419edf
      host-172-25-75-74   Ready   infra,worker   3d20h   v1.23.3+e419edf
      host-172-25-75-79   Ready   worker         3d20h   v1.23.3+e419edf
      host-172-25-75-86   Ready   worker         3d20h   v1.23.3+e419edf
      host-172-25-75-98   Ready   infra,worker   3d20h   v1.23.3+e419edf

      所有节点都可能需要过几分钟时间才能报告其状态。

    2. 如果有任何节点处于 NotReady 状态,请登录节点,并从每个节点上的 /var/lib/kubelet/pki 目录中删除所有 PEM 文件。您可以 SSH 到节点,或使用 web 控制台中的终端窗口。

      $  ssh -i <ssh-key-path> core@<master-hostname>

      pki 目录示例

      sh-4.4# pwd
      /var/lib/kubelet/pki
      sh-4.4# ls
      kubelet-client-2022-04-28-11-24-09.pem  kubelet-server-2022-04-28-11-24-15.pem
      kubelet-client-current.pem              kubelet-server-current.pem

  9. 在所有 control plane 主机上重启 kubelet 服务。

    1. 在恢复主机中运行以下命令:

      $ sudo systemctl restart kubelet.service
    2. 在所有其他 control plane 主机上重复此步骤。
  10. 批准待处理的 CSR:

    1. 获取当前 CSR 列表。

      $ oc get csr

      输出示例

      NAME        AGE    SIGNERNAME                                    REQUESTOR                                                                   CONDITION
      csr-2s94x   8m3s   kubernetes.io/kubelet-serving                 system:node:<node_name>                                                     Pending 1
      csr-4bd6t   8m3s   kubernetes.io/kubelet-serving                 system:node:<node_name>                                                     Pending 2
      csr-4hl85   13m    kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Pending 3
      csr-zhhhp   3m8s   kubernetes.io/kube-apiserver-client-kubelet   system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Pending 4
      ...

      1 2
      一个待处理的 kubelet 服务 CSR(用于用户置备的安装)。
      3 4
      一个待处理的 node-bootstrapper CSR。
    2. 查看一个 CSR 的详细信息以验证其是否有效:

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

      $ oc adm certificate approve <csr_name>
    4. 对于用户置备的安装,请批准每个有效的 kubelet 服务 CSR:

      $ oc adm certificate approve <csr_name>
  11. 确认单个成员 control plane 已被成功启动。

    1. 从恢复主机上,验证 etcd 容器是否正在运行。

      $ sudo crictl ps | grep etcd | grep -v operator

      输出示例

      3ad41b7908e32       36f86e2eeaaffe662df0d21041eb22b8198e0e58abeeae8c743c3e6e977e8009                                                         About a minute ago   Running             etcd                                          0                   7c05f8af362f0

    2. 从恢复主机上,验证 etcd pod 是否正在运行。

      $ oc get pods -n openshift-etcd | grep -v etcd-quorum-guard | grep etcd
      注意

      如果您试图在运行这个命令前运行 oc login 并接收以下错误,请等待一些时间以便身份验证控制器启动并再次尝试。

      Unable to connect to the server: EOF

      输出示例

      NAME                                             READY   STATUS      RESTARTS   AGE
      etcd-ip-10-0-143-125.ec2.internal                1/1     Running     1          2m47s

      如果状态是 Pending,或者输出中列出了多个正在运行的 etcd pod,请等待几分钟,然后再次检查。

  12. 强制 etcd 重新部署。

    在一个终端中使用 cluster-admin 用户连接到集群,运行以下命令:

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

    当 etcd cluster Operator 执行重新部署时,现有节点开始使用与初始 bootstrap 扩展类似的新 pod。

  13. 验证所有节点是否已更新至最新的修订版本。

    在一个终端中使用 cluster-admin 用户连接到集群,运行以下命令:

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

    查看 etcd 的NodeInstallerProgressing 状态条件,以验证所有节点是否处于最新的修订。在更新成功后,输出会显示 AllNodesAtLatestRevision

    AllNodesAtLatestRevision
    3 nodes are at revision 7 1
    1
    在本例中,最新的修订版本号是 7

    如果输出包含多个修订号,如 2 个节点为修订版本 6;1 个节点为修订版本 7,这意味着更新仍在进行中。等待几分钟后重试。

  14. 在重新部署 etcd 后,为 control plane 强制进行新的 rollout。由于 kubelet 使用内部负载平衡器连接到 API 服务器,因此 Kubernetes API 将在其他节点上重新安装自己。

    在一个终端中使用 cluster-admin 用户连接到集群,运行以下命令。

    1. 为 Kubernetes API 服务器强制进行新的推出部署:

      $ oc patch kubeapiserver cluster -p='{"spec": {"forceRedeploymentReason": "recovery-'"$( date --rfc-3339=ns )"'"}}' --type=merge

      验证所有节点是否已更新至最新的修订版本。

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

      查看 NodeInstallerProgressing 状态条件,以验证所有节点是否处于最新版本。在更新成功后,输出会显示 AllNodesAtLatestRevision

      AllNodesAtLatestRevision
      3 nodes are at revision 7 1
      1
      在本例中,最新的修订版本号是 7

      如果输出包含多个修订号,如 2 个节点为修订版本 6;1 个节点为修订版本 7,这意味着更新仍在进行中。等待几分钟后重试。

    2. 为 Kubernetes 控制器管理器强制进行新的推出部署:

      $ oc patch kubecontrollermanager cluster -p='{"spec": {"forceRedeploymentReason": "recovery-'"$( date --rfc-3339=ns )"'"}}' --type=merge

      验证所有节点是否已更新至最新的修订版本。

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

      查看 NodeInstallerProgressing 状态条件,以验证所有节点是否处于最新版本。在更新成功后,输出会显示 AllNodesAtLatestRevision

      AllNodesAtLatestRevision
      3 nodes are at revision 7 1
      1
      在本例中,最新的修订版本号是 7

      如果输出包含多个修订号,如 2 个节点为修订版本 6;1 个节点为修订版本 7,这意味着更新仍在进行中。等待几分钟后重试。

    3. 为 Kubernetes 调度程序强制进行新的推出部署:

      $ oc patch kubescheduler cluster -p='{"spec": {"forceRedeploymentReason": "recovery-'"$( date --rfc-3339=ns )"'"}}' --type=merge

      验证所有节点是否已更新至最新的修订版本。

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

      查看 NodeInstallerProgressing 状态条件,以验证所有节点是否处于最新版本。在更新成功后,输出会显示 AllNodesAtLatestRevision

      AllNodesAtLatestRevision
      3 nodes are at revision 7 1
      1
      在本例中,最新的修订版本号是 7

      如果输出包含多个修订号,如 2 个节点为修订版本 6;1 个节点为修订版本 7,这意味着更新仍在进行中。等待几分钟后重试。

  15. 验证所有 control plane 主机是否已启动并加入集群。

    在一个终端中使用 cluster-admin 用户连接到集群,运行以下命令:

    $ oc get pods -n openshift-etcd | grep -v etcd-quorum-guard | grep etcd

    输出示例

    etcd-ip-10-0-143-125.ec2.internal                2/2     Running     0          9h
    etcd-ip-10-0-154-194.ec2.internal                2/2     Running     0          9h
    etcd-ip-10-0-173-171.ec2.internal                2/2     Running     0          9h

为确保所有工作负载在恢复过程后返回到正常操作,请重启存储 Kubernetes API 信息的每个 pod。这包括 OpenShift Container Platform 组件,如路由器、Operator 和第三方组件。

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