本页面介绍如何手动创建和恢复 GKE On-Prem 管理员集群和用户集群的 etcd 键值对存储区。此页面还提供了一个脚本,可用于自动备份集群的 etcd 存储区。
您应该创建备份,以便从可能会破坏 etcd 数据和 Secret 的可预见灾难中恢复数据。请务必将备份存储在集群之外的位置,并且该位置不依赖于集群的操作。如果您想要保证安全,也可以考虑创建备份的副本。
虽然每个集群中运行的 etcd 事件 pod 对恢复用户集群并不重要,但您可以按照类似的过程进行备份。另请注意,此过程仅备份 etcd 存储区;本指南不包括备份 PersistentVolume,您应为其规划其他备份和恢复过程。
限制
- 备份应用专用数据超出了此功能的范围。
- 在您手动轮替之前,Secret 将一直有效。
- 创建备份后安排的工作负载不会随该备份一起恢复。
- 目前,您无法从失败的集群升级中恢复数据。
- 此过程不适用于恢复已删除的集群。
已知问题
运行 sudo
命令时,您可能会遇到以下错误:
sudo: unable to resolve host gke-admin-master-[CLUSTER_ID]
如果遇到该错误,请将以下行添加到 /etc/hosts
文件中:
127.0.0.1 gke-admin-master-[CLUSTER_ID]
用户集群备份
用户集群备份包含用户集群的 etcd 快照。集群的 etcd 包含所有 Kubernetes 对象以及管理集群状态所需的任何自定义对象等内容。此快照包含重新创建集群组件和工作负载所需的数据。
备份用户集群
用户集群的 etcd 存储在其控制层面节点中,您可以使用管理员集群的 kubeconfig 进行访问。
要创建 etcd 的快照,请执行以下步骤:
通过 shell 进入 kube-etcd 容器:
kubectl --kubeconfig [ADMIN_CLUSTER_KUBECONFIG] exec \ -it -n [USER_CLUSTER_NAME] kube-etcd-0 -c \ kube-etcd -- bin/sh
其中:
- [ADMIN_CLUSTER_KUBECONFIG] 是管理员集群的 kubeconfig 文件。
- [USER_CLUSTER_NAME] 是用户集群的名称。具体来说,您是在管理员集群中传入一个以用户集群命名的命名空间。
在 shell 中,使用
etcdctl
在本地目录中创建一个名为snapshot.db
的备份: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 snapshot.db
退出该容器:
exit
使用
kubectl cp
从 kube-etcd 容器中复制备份:kubectl --kubeconfig [ADMIN_CLUSTER_KUBECONFIG] cp \ [USER_CLUSTER_NAME]/kube-etcd-0:snapshot.db [DIRECTORY] -c kube-etcd
其中,[RELATIVE_DIRECTORY] 是存储备份的路径。
恢复用户集群备份
在恢复备份之前,请务必诊断集群并解决现有问题。将备份恢复到有问题的集群可能会重新创建或加剧问题。请联系 GKE On-Prem 支持团队,以获取有关恢复集群的更多帮助。
如果您创建了一个高可用性用户集群,则应为每一个 etcd 集群成员运行一次这些步骤。您可以在恢复每个 etcd 成员时使用相同的快照。除非所有 etcd pod 都崩溃循环,否则请勿执行这些步骤:这表示存在数据损坏。
etcd pod 崩溃循环
以下说明介绍在用户集群的 etcd 数据已损坏且其 etcd pod 出现崩溃循环时如何恢复备份。要进行恢复,您可以将 etcd pod 部署到现有 pod 的卷,然后使用备份覆盖损坏的数据,假设用户集群的 API 服务器正在运行并且可以安排新的 pod。
在填充以下占位值后,将下面的 etcd pod 规范复制到文件
restore-etcd.yaml
中:- [MEMBER_NUMBER] 是您要恢复的已编号的 pod。
- [NODE_NAME] 是运行 [MEMBER_NUMBER[ pod 的节点。
- [ADMIN_CLUSTER_KUBECONFIG] 是管理员集群的 kubeconfig 文件。
- [USER_CLUSTER_NAME] 是用户集群的名称。
[DEFAULT_TOKEN] 用于身份验证。您可以通过运行以下命令找到此值:
kubectl --kubeconfig [ADMIN_CLUSTER_KUBECONFIG] \ -n [USER_CLUSTER_NAME] get pods kube-etcd-0 \ -o yaml | grep default-token
restore-etcd.yaml
apiVersion: v1 kind: Pod metadata: labels: Component: restore-etcd-[MEMBER_NUMBER] name: restore-etcd-0 namespace: [USER_CLUSTER_NAME] spec: restartPolicy: Never containers: - command: ["/bin/sh"] args: ["-ec", "while :; do echo '.'; sleep 5 ; done"] image: gcr.io/gke-on-prem-release/etcd:v3.2.24-1-gke.0 imagePullPolicy: IfNotPresent name: restore-etcd terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /var/lib/etcd name: data - mountPath: /etcd.local.config/certificates name: etcd-certs - mountPath: /var/run/secrets/kubernetes.io/serviceaccount name: [DEFAULT_TOKEN] readOnly: true dnsPolicy: ClusterFirst hostname: restore-etcd-0 imagePullSecrets: - name: private-registry-creds nodeSelector: kubernetes.googleapis.com/cluster-name: [USER_CLUSTER_NAME] kubernetes.io/hostname: [NODE_NAME] priority: 0 restartPolicy: Always schedulerName: default-scheduler securityContext: {} serviceAccount: default serviceAccountName: default subdomain: restore-etcd terminationGracePeriodSeconds: 30 tolerations: - effect: NoExecute key: node.kubernetes.io/not-ready operator: Exists tolerationSeconds: 300 - effect: NoExecute key: node.kubernetes.io/unreachable operator: Exists tolerationSeconds: 300 volumes: - name: data persistentVolumeClaim: claimName: data-kube-etcd-[MEMBER_NUMBER] - name: etcd-certs secret: defaultMode: 420 secretName: kube-etcd-certs - name: [DEFAULT_TOKEN] secret: defaultMode: 420 secretName: [DEFAULT_TOKEN]
部署 pod:
kubectl --kubeconfig [ADMIN_CLUSTER_KUBECONFIG] \ -n [USER_CLUSTER_NAME] create -f restore-etcd.yaml
将 etcd 的备份文件
snapshot.db
复制到新的 pod。snapshot.db
位于您创建备份的相对目录中:kubectl --kubeconfig [ADMIN_CLUSTER_KUBECONFIG] \ cp [RELATIVE_DIRECTORY]/snapshot.db \ [USER_CLUSTER_NAME]/restore-etcd-0:snapshot.db
通过 shell 进入
restore-etcd
pod:kubectl --kubeconfig [ADMIN_CLUSTER_KUBECONFIG] \ -it -n [USER_CLUSTER_NAME] exec restore-etcd-0 -- bin/sh
运行以下命令以创建包含备份的新 default.etcd 文件夹:
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 restore snapshot.db
使用备份覆盖已损坏的 etcd 数据:
rm -r var/lib/etcd/*; cp -r default.etcd/* var/lib/etcd/
退出该容器:
exit
删除崩溃的 etcd pod:
kubectl --kubeconfig [ADMIN_CLUSTER_KUBECONFIG] \ -n [USER_CLUSTER_NAME] delete pod kube-etcd-0
验证 etcd pod 是否不再崩溃。
移除
restore-etcd.yaml
并删除restore-etcd
pod:rm restore-etcd.yaml; kubectl --kubeconfig [ADMIN_CLUSTER_KUBECONFIG] \ -n [USER_CLUSTER_NAME] delete pod restore-etcd-0
管理员集群备份
管理员集群备份包含以下内容:
- 管理员集群的 etcd 快照。
- 管理员控制层面的 Secret,这是向管理员集群和用户集群进行身份验证所必需的。
在创建管理员集群备份前,请完成以下步骤:
找到管理员集群的外部 IP 地址(用于通过 SSH 连接到管理员集群控制层面):
kubectl --kubeconfig [ADMIN_KUBECONFIG] get nodes -n kube-system -o wide | grep master
其中,[ADMIN_CLUSTER_KUBECONFIG] 是管理员集群的 kubeconfig 文件。
从管理员集群的私钥创建一个名为
vsphere_tmp
的 SSH 密钥。您可以从管理员集群 Secret 中找到私钥:
kubectl --kubeconfig [ADMIN_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 及其控制层面的 Secret。
etcd
要备份管理员集群的 etcd,请执行以下操作:
获取 etcd pod 的名称:
kubectl --kubeconfig [ADMIN_KUBECONFIG] get pods \ -n kube-system | grep etcd-gke-admin-master
通过 shell 进入 pod 的 kube-etcd 容器:
kubectl --kubeconfig [ADMIN_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 snapshot.db
退出该容器:
exit
使用
kubectl cp
从 kube-etcd 容器中复制备份:kubectl --kubeconfig [ADMIN_CLUSTER_KUBECONFIG] cp \ kube-system/[ADMIN_ETCD_POD]:snapshot.db [RELATIVE_DIRECTORY]
其中,[RELATIVE_DIRECTORY] 是存储备份的路径。
Secret
要备份管理员控制层面的 Secret,请执行以下操作:
通过 shell 进入管理员控制层面节点:
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 +rw 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 地址。
运行
kubeadm reset
。这将停止仍在管理员集群中运行的任何内容,删除所有 etcd 数据,并删除/etc/kubernetes/pki/
中的 Secret:sudo kubeadm reset --ignore-preflight-errors=all
将备份 Secret 复制到
/etc/kubernetes/pki/
:sudo cp -r backup/* /etc/kubernetes/pki/
使用 Docker 运行
etcdctl restore
:sudo docker run --rm \ -v '/mnt:/backup' \ -v '/var/lib/etcd:/var/lib/etcd' --env ETCDCTL_API=3 'k8s.gcr.io/etcd-amd64:3.1.12' /bin/sh -c "etcdctl snapshot restore '/backup/snapshot.db'; mv /default.etcd/member/ /var/lib/etcd/"
运行
kubeadm init
。这会重复使用所有备份 Secret 并使用已恢复的快照重新启动 etcd:sudo kubeadm init --config /etc/kubernetes/kubeadm_config.yaml --ignore-preflight-errors=DirAvailable--var-lib-etcd
退出管理员控制层面:
exit
从管理员节点复制新生成的 kubeconfig 文件:
sudo scp -i vsphere_tmp ubuntu@[EXTERNAL_IP]:[HOME]/.kube/config kubeconfig
其中:
- [EXTERNAL_IP] 是管理员控制层面的外部 IP 地址。
- [HOME] 是管理员节点上的主目录。
现在,您可以使用这一新的 kubeconfig 文件访问恢复的集群。
备份脚本
您可以使用此处提供的示例脚本自动备份集群。请注意,以下脚本不受支持,仅供参考,您应在此基础上编写更好、更可靠且更完善的脚本。在运行脚本之前,请在脚本开头填写五个变量的值:
- 将
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.
if [ -e ${BACKUP_DIR} ]
then
echo "Error: Backup directory $BACKUP_DIR exists already."
exit 1
fi
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 ${USER_CLUSTER_NAMESPACE}_snapshot.db"
kubectl --kubeconfig=${ADMIN_CLUSTER_KUBECONFIG} cp ${USER_CLUSTER_NAMESPACE}/kube-etcd-0:${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 +rw /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 -o=name | grep etcd | cut -c 5-)
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 admin_snapshot.db"
kubectl --kubeconfig=${ADMIN_CLUSTER_KUBECONFIG} cp -n kube-system ${admin_etcd}/admin_snapshot.db $BACKUP_DIR/admin-cluster_snapshot.db
问题排查
如需了解详情,请参阅问题排查。
使用 gkectl
诊断集群问题
使用 gkectl diagnose
命令识别集群问题并与 Google 共享集群信息。请参阅诊断集群问题。
以 verbose 模式运行 gkectl
命令
-v5
将 gkectl
错误记录到 stderr
--alsologtostderr
在管理员工作站中查找 gkectl
日志
即使未传入其调试标志,您也可以在以下管理员工作站目录中查看 gkectl
日志:
/home/ubuntu/.config/gke-on-prem/logs
在管理员集群中查找 Cluster API 日志
如果虚拟机在管理员控制层面启动后无法启动,您可以通过在管理员集群中检查 Cluster API 控制器的日志来尝试进行调试:
在
kube-system
命名空间中找到 Cluster API 控制器 pod 的名称,其中 [ADMIN_CLUSTER_KUBECONFIG] 是管理员集群的 kubeconfig 文件的路径:kubectl --kubeconfig [ADMIN_CLUSTER_KUBECONFIG] -n kube-system get pods | grep clusterapi-controllers
打开 pod 的日志,其中 [POD_NAME] 是 pod 的名称。您可以选择使用
grep
或类似工具来搜索错误:kubectl --kubeconfig [ADMIN_CLUSTER_KUBECONFIG] -n kube-system logs [POD_NAME] vsphere-controller-manager
后续步骤
- 了解如何诊断集群问题
- 了解 augur,这是一个用于从 etcd 备份中恢复单个对象的开源工具。