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

为了将集群还原到以前的状态,您必须已通过创建快照备份了 etcd 数据 。您将需要使用此快照来还原集群状态。

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

您可以使用已保存的 etcd 备份恢复到先前的集群状态。您可以使用 etcd 备份来恢复单个 master 主机。然后,etcd cluster Operator 会处理剩余的 master 主机的扩展。

重要

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

先决条件

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

流程

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

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

    重要

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

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

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

  4. 在所有其他 master 节点上停止静态 pod。

    注意

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

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

      [core@ip-10-0-154-194 ~]$ sudo mv /etc/kubernetes/manifests/etcd-pod.yaml /tmp
    3. 验证 etcd pod 是否已停止。

      [core@ip-10-0-154-194 ~]$ sudo crictl ps | grep etcd | grep -v operator

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

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

      [core@ip-10-0-154-194 ~]$ sudo mv /etc/kubernetes/manifests/kube-apiserver-pod.yaml /tmp
    5. 验证 Kubernetes API 服务器 pod 是否已停止。

      [core@ip-10-0-154-194 ~]$ sudo crictl ps | grep kube-apiserver | grep -v operator

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

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

      [core@ip-10-0-154-194 ~]$ sudo mv /var/lib/etcd/ /tmp
    7. 在其他不是恢复主机的 master 主机上重复这个步骤。
  5. 访问恢复 master 主机。
  6. 如果启用了集群范围的代理,请确定已导出了 NO_PROXYHTTP_PROXYHTTPS_PROXY 环境变量。

    提示

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

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

    [core@ip-10-0-143-125 ~]$ 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
  8. 在所有 master 主机上重启 kubelet 服务。

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

      [core@ip-10-0-143-125 ~]$ sudo systemctl restart kubelet.service
    2. 在所有其他 master 主机上重复此步骤。
  9. 确认单个成员 control plane 已被成功启动。

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

      [core@ip-10-0-143-125 ~]$ sudo crictl ps | grep etcd | grep -v operator
      3ad41b7908e32       36f86e2eeaaffe662df0d21041eb22b8198e0e58abeeae8c743c3e6e977e8009                                                         About a minute ago   Running             etcd                                          0                   7c05f8af362f0
    2. 从恢复主机上,验证 etcd pod 是否正在运行。

      [core@ip-10-0-143-125 ~]$ oc get pods -n openshift-etcd | grep etcd
      
      NAME                                             READY   STATUS      RESTARTS   AGE
      etcd-ip-10-0-143-125.ec2.internal                1/1     Running     1          2m47s
      注意

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

      Unable to connect to the server: EOF

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

  10. 强制 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。

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

    在一个终端中使用 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 3

    如果输出显示 2 个节点处于修订版本 3,1 个节点处于修订版本 4,这意味着更新仍在进行中。等待几分钟后重试。

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

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

    1. 更新 kubeapiserver:

      $ 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 3
    2. 更新 kubecontrollermanager:

      $ 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 3
    3. 更新 kubescheduler

      $ 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 3
  13. 验证所有 master 主机已启动并加入集群。

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

    $ oc get pods -n openshift-etcd | 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

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