本文档介绍了如何为使用 Google Distributed Cloud for VMware(纯软件)创建的管理员集群备份和恢复 etcd 存储区。此文档还提供了一个脚本,您可以使用该脚本自动备份集群的 etcd 存储区。您还可以使用 gkectl 命令行工具备份和恢复管理员集群。
您可以创建备份文件,以便从可能会破坏集群的 etcd 数据的意外灾难中恢复数据。请将备份文件存储在集群外部且不依赖于集群操作的位置。
限制
本文档中介绍的备份和恢复过程存在以下限制:
- 此过程不会备份应用特定的数据。 
- 此过程不会备份 PersistentVolume。 
- 创建备份后安排的工作负载不会随该备份一起恢复。 
- 升级失败后,您无法恢复集群。 
- 此过程不适用于恢复已删除的集群。 
- 请勿对启用了高级集群的集群使用此过程。请改为参阅使用 gkectl 备份和恢复高级集群。 
如需详细了解限制,请参阅基础设施不兼容性。
备份管理员集群
管理员集群备份包含以下内容:
- 管理员集群的 etcd 快照。
- 管理员控制层面的 Secret,这是向管理员集群和用户集群进行身份验证所必需的。
在创建管理员集群备份前,请完成以下步骤:
- 找到管理员集群的外部 IP 地址(用于通过 SSH 连接到管理员集群控制平面): - kubectl --kubeconfig [ADMIN_CLUSTER_KUBECONFIG] get nodes -n kube-system -o wide | grep master - 其中,[ADMIN_CLUSTER_KUBECONFIG] 是管理员集群的 kubeconfig 文件。 
- 从管理员集群的私钥创建一个名为 - vsphere_tmp的 SSH 密钥。- 您可以从管理员集群 Secret 中找到私钥: - kubectl --kubeconfig [ADMIN_CLUSTER_KUBECONFIG] get secrets sshkeys -n kube-system -o yaml - 在命令输出中,您可以在 - vsphere_tmp字段中找到私钥。- 将私钥复制到 - vsphere_tmp:- echo "[PRIVATE_KEY]" | base64 -d > vsphere_tmp; chmod 600 vsphere_tmp 
- 检查您是否可以使用此私钥通过 shell 进入管理员控制平面: - ssh -i vsphere_tmp ubuntu@[EXTERNAL_IP] 
- 退出该容器: - exit 
备份管理员集群的 etcd 存储区
要备份管理员集群的 etcd 存储区,请执行以下操作:
- 获取 etcd pod 的名称: - kubectl --kubeconfig [ADMIN_CLUSTER_KUBECONFIG] get pods \ -n kube-system -l component=etcd,tier=control-plane -ojsonpath='{$.items[*].metadata.name}{"\n"}'
- 通过 shell 进入 pod 的 kube-etcd 容器: - kubectl --kubeconfig [ADMIN_CLUSTER_KUBECONFIG] exec -it \ -n kube-system [ADMIN_ETCD_POD] -- bin/sh- 其中,[ADMIN_ETCD_POD] 是 etcd pod 的名称。 
- 在 Shell 中,使用 - etcdctl在本地目录中创建一个名为- snapshot.db的备份:- ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \ --key=/etc/kubernetes/pki/etcd/healthcheck-client.key snapshot save /tmp/snapshot.db
- 退出该容器: - exit 
- 使用 - kubectl cp从 kube-etcd 容器中复制备份:- kubectl --kubeconfig [ADMIN_CLUSTER_KUBECONFIG] cp \ kube-system/[ADMIN_ETCD_POD]:tmp/snapshot.db [RELATIVE_DIRECTORY] - 其中,[RELATIVE_DIRECTORY] 是存储备份的路径。 
备份管理员集群的 Secret
要备份管理员控制层面的 Secret,请执行以下操作:
- 使用 SSH 连接到管理员控制平面节点: - ssh -i vsphere_tmp ubuntu@EXTERNAL_IP - 将 - EXTERNAL_IP替换为您之前记下的管理员控制层面的外部 IP 地址。
- 创建本地备份目录是可选步骤,但我们强烈建议您执行。 - 您需要更改备份 Secret 的权限,以将其复制到节点之外。 - mkdir backup 
- 在本地将 Secret 复制到本地备份目录: - sudo cp -r /etc/kubernetes/pki/* backup/ 
- 更改备份 Secret 的权限: - sudo chmod -R a+rX backup/ 
- 退出管理员控制平面节点: - exit 
- 运行 - scp从管理员控制平面节点复制备份文件夹:- sudo scp -r -i vsphere_tmp ubuntu@EXTERNAL_IP:backup/ RELATIVE_DIRECTORY - 将 - RELATIVE_DIRECTORY替换为您要用于存储备份的路径。
恢复管理员集群
以下过程会重新创建备份管理员集群以及创建 etcd 快照时其管理的所有用户控制层面。
- 运行 - scp以将- snapshot.db复制到管理员控制平面:- sudo scp -i vsphere_tmp snapshot.db ubuntu@[EXTERNAL_IP]: - 其中,[EXTERNAL_IP] 是您之前收集的管理员控制层面的外部 IP 地址。 
- 通过 shell 进入管理员控制平面: - sudo ssh -i vsphere_tmp ubuntu@[EXTERNAL_IP] 
- 将 - snapshot.db/复制到- /mnt:- sudo cp snapshot.db /mnt/ 
- 设置临时目录,例如 - backup:- mkdir backup 
- 退出管理员控制平面: - exit 
- 将证书复制到 - backup/:- sudo scp -r -i vsphere_tmp [BACKUP_CERT_FILE] ubuntu@[EXTERNAL_IP]:backup/ 
- 通过 shell 进入管理员控制平面节点: - ssh -i vsphere_tmp ubuntu@[EXTERNAL_IP] - 其中,[EXTERNAL_IP] 是您之前收集的管理员控制层面的外部 IP 地址。 
- 停止 - kube-etcd和- kube-apiserver。- sudo mv /etc/kubernetes/manifests/etcd.yaml /tmp/etcd.yaml - sudo mv /etc/kubernetes/manifests/kube-apiserver.yaml /tmp/kube-apiserver.yaml 
- 将备份 Secret 复制到 - /etc/kubernetes/pki/:- sudo cp -r backup/* /etc/kubernetes/pki/ 
- 运行 - etcdctl restore:- ETCDCTL_API=3 sudo etcdctl snapshot restore /backup/snapshot.db sudo rm -r /var/lib/etcd/* sudo mv /default.etcd/member/ /var/lib/etcd/ 
- 重启 - kube-etcd和- kube-apiserver。- sudo mv /tmp/etcd.yaml /etc/kubernetes/manifests/etcd.yaml - sudo mv /tmp/kube-apiserver.yaml /etc/kubernetes/manifests/kube-apiserver.yaml 
- 验证 - kube-etcd和- kube-apiserver已启动。- sudo crictl ps -a 
- 将 - /etc/kubernetes/admin.conf复制到- .kube文件夹,以便从管理员工作站访问:- mkdir -p [HOME]/.kube - sudo cp -i /etc/kubernetes/admin.conf [HOME]/.kube/config - sudo chown $(id -u):$(id -g) $HOME/.kube/config 
- 退出管理员控制平面: - exit 
- 从管理员节点复制新生成的 kubeconfig 文件: - sudo scp -i vsphere_tmp ubuntu@[EXTERNAL_IP]:[HOME]/.kube/config kubeconfig - sudo chown $(id -u):$(id -g) kubeconfig - 其中: - [EXTERNAL_IP] 是管理员控制层面的外部 IP 地址。
- [HOME] 是管理员节点上的主目录。
 - 现在,您可以使用这一新的 kubeconfig 文件访问恢复的集群。 
排查管理员集群恢复问题
如果您在恢复管理员集群时遇到问题,则必须与 Google 支持团队联系以解决管理员集群相关问题。
在此期间,您可以查看以下各项以进一步进行问题排查。
- 找到 etcd 容器 ID - sudo crictl ps -a | grep [ADMIN_ETCD_POD] - 其中,[ADMIN_ETCD_POD] 是 etcd pod 的名称。 
- 检查来自 etc 容器的日志 - sudo crictl logs [ETCD_CONTAINER_ID] - 其中,[ETCD_CONTAINER_ID] 是 etcd 容器的 ID。 
- 查找如下权限遭拒的日志消息 - etcdserver: create snapshot directory error:mkdir /var/lib/etcd/member/snap: permission denied
- 如果找到权限遭拒的消息,请更新 /opt/data/var/lib/etcd/ 的所有权 - sudo chown -R 2001:2001 /opt/data/var/lib/etcd/ 
- 验证 - kube-etcd和- kube-apiserver已启动。- sudo crictl ps 
自动备份集群
您可以使用此处提供的示例脚本自动备份集群。请注意,以下脚本不受支持,仅供参考,您应在此基础上编写更好、更可靠且更完善的脚本。在运行脚本之前,请在脚本开头填写五个变量的值:
- 将 BACKUP_DIR设置为您要存储管理员集群和用户集群备份的路径。此路径不应存在。
- 将 ADMIN_CLUSTER_KUBECONFIG设置为管理员集群的 kubeconfig 文件的路径。
- 将 USER_CLUSTER_NAMESPACE设置为您的用户集群的名称。用户集群的名称是管理员集群中的命名空间。
- 将 EXTERNAL_IP设置为您为管理员控制平面服务预留的 VIP。
- 将 SSH_PRIVATE_KEY设置为 SSH 密钥的路径。
- 如果您使用的是专用网络,请将 JUMP_IP设置为该网络的跳转服务器的 IP 地址。
#!/usr/bin/env bash
# Automates manual steps for taking backups of user and admin clusters.
# Fill in the variables below before running the script.
BACKUP_DIR=""                       # path to store user and admin cluster backups
ADMIN_CLUSTER_KUBECONFIG=""         # path to admin cluster kubeconfig
USER_CLUSTER_NAMESPACE=""           # user cluster namespace
EXTERNAL_IP=""                      # admin control plane node external ip - follow steps in documentation
SSH_PRIVATE_KEY=""                  # path to vsphere_tmp ssh private key - follow steps in documentation
JUMP_IP=""                          # network jump server IP - leave empty string if not using private network.
mkdir -p $BACKUP_DIR
mkdir $BACKUP_DIR/pki
# USER CLUSTER BACKUP
# Snapshot user cluster etcd
kubectl --kubeconfig=${ADMIN_CLUSTER_KUBECONFIG} exec -it -n ${USER_CLUSTER_NAMESPACE} kube-etcd-0 -c kube-etcd -- /bin/sh -ec "export ETCDCTL_API=3; etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etcd.local.config/certificates/etcdCA.crt --cert=/etcd.local.config/certificates/etcd.crt --key=/etcd.local.config/certificates/etcd.key snapshot save /tmp/${USER_CLUSTER_NAMESPACE}_snapshot.db"
kubectl --kubeconfig=${ADMIN_CLUSTER_KUBECONFIG} cp ${USER_CLUSTER_NAMESPACE}/kube-etcd-0:tmp/${USER_CLUSTER_NAMESPACE}_snapshot.db $BACKUP_DIR/user-cluster_${USER_CLUSTER_NAMESPACE}_snapshot.db 
# ADMIN CLUSTER BACKUP
# Set up ssh options
SSH_OPTS=(-oStrictHostKeyChecking=no -i ${SSH_PRIVATE_KEY})
if [ "${JUMP_IP}" != "" ]; then
    SSH_OPTS+=(-oProxyCommand="ssh -oStrictHostKeyChecking=no -i ${SSH_PRIVATE_KEY} -W %h:%p ubuntu@${JUMP_IP}")
fi
# Copy admin certs
ssh "${SSH_OPTS[@]}" ubuntu@${EXTERNAL_IP} 'sudo chmod -R a+rX /etc/kubernetes/pki/*'
scp -r "${SSH_OPTS[@]}" ubuntu@${EXTERNAL_IP}:/etc/kubernetes/pki/* ${BACKUP_DIR}/pki/
# Snapshot admin cluster etcd
admin_etcd=$(kubectl --kubeconfig=${ADMIN_CLUSTER_KUBECONFIG} get pods -n kube-system -l component=etcd,tier=control-plane -ojsonpath='{$.items[*].metadata.name}{"\n"}')
kubectl --kubeconfig=${ADMIN_CLUSTER_KUBECONFIG} exec -it -n kube-system ${admin_etcd} -- /bin/sh -ec "export ETCDCTL_API=3; etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt --key=/etc/kubernetes/pki/etcd/healthcheck-client.key snapshot save /tmp/admin_snapshot.db"
kubectl --kubeconfig=${ADMIN_CLUSTER_KUBECONFIG} cp -n kube-system ${admin_etcd}:tmp/admin_snapshot.db $BACKUP_DIR/admin-cluster_snapshot.db