本页面介绍如何备份和恢复集群的 etcd 存储区。此页面还提供了一个脚本,您可以使用该脚本自动备份集群的 etcd 存储区。
您可以创建备份文件,以便从可能会破坏集群的 etcd 数据的可预见灾难中恢复数据。请将备份文件存储在集群外部且不依赖于集群操作的位置。
限制
此过程不会备份应用特定的数据。
此过程不会备份您的 PersistentVolume。
创建备份后安排的工作负载不会随该备份一起恢复。
升级失败后,您无法恢复集群。
此过程不适用于恢复已删除的集群。
备份用户集群
用户集群备份是用户集群的 etcd 存储区的快照。 etcd 存储区包含管理集群状态所需的所有 Kubernetes 对象和自定义对象。快照包含重新创建集群组件和工作负载所需的数据。
如需创建 etcd 存储区的快照,请执行以下步骤:
通过 shell 进入
kube-etcd
容器:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG exec -it \ kube-etcd-0 --container kube-etcd --namespace USER_CLUSTER_NAME \ -- bin/sh
其中:
- ADMIN_CLUSTER_KUBECONFIG 是管理员集群的 kubeconfig 文件。
- USER_CLUSTER_NAME 是用户集群的名称。
在 shell 的根目录中,创建名为
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
在 shell 中,输入
exit
以退出 shell。将
snapshot.db
从kube-etcd
容器复制到当前目录:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG cp \ USER_CLUSTER_NAME/kube-etcd-0:snapshot.db \ --container kube-etcd snapshot.db
从备份恢复用户集群(非 HA)
在使用备份文件恢复用户集群的 etcd 存储区之前,请先诊断集群并解决现有问题。使用备份来恢复有问题的集群可能会重新创建或加剧问题。请联系 Anthos Clusters on VMware 支持团队,以获取有关恢复集群的更多帮助。
以下说明介绍了在集群的 etcd 数据已损坏且用户集群的 etcd pod 出现崩溃循环时,如何使用备份文件恢复用户集群。
您可以部署一个实用程序 pod(使用备份覆盖已损坏的数据)来恢复 etcd 数据。管理员集群的 API 服务器必须正在运行,并且管理员集群的调度器必须能够安排新的 pod。
将以下 pod 清单复制到名为
etcd-utility.yaml
的文件中。将这些占位符替换为值:NODE_NAME
:运行kube-etcd-0
pod 的节点。ADMIN_CLUSTER_KUBECONFIG
:管理员集群的 kubeconfig 文件。USER_CLUSTER_NAME
:用户集群的名称。GKE_ON_PREM_VERSION
:要在其中执行 etcd 恢复的集群版本(例如 1.5.0-gke.0)。
apiVersion: v1 kind: Pod metadata: name: etcd-utility-0 namespace: USER_CLUSTER_NAME spec: containers: - command: ["/bin/sh"] args: ["-ec", "while :; do echo '.'; sleep 5 ; done"] image: gcr.io/gke-on-prem-release/etcd-util:GKE_ON_PREM_VERSION name: etcd-utility volumeMounts: - mountPath: /var/lib/etcd name: data - mountPath: /etcd.local.config/certificates name: etcd-certs nodeSelector: kubernetes.googleapis.com/cluster-name: USER_CLUSTER_NAME kubernetes.io/hostname: NODE_NAME tolerations: - effect: NoExecute key: node.kubernetes.io/not-ready operator: Exists tolerationSeconds: 300 - effect: NoExecute key: node.kubernetes.io/unreachable operator: Exists tolerationSeconds: 300 - effect: NoSchedule key: node.kubernetes.io/unschedulable operator: Exists volumes: - name: data persistentVolumeClaim: claimName: data-kube-etcd-0 - name: etcd-certs secret: defaultMode: 420 secretName: kube-etcd-certs
部署实用程序 pod:
kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG \ create -f etcd-utility.yaml --namespace USER_CLUSTER_NAME
将
snapshot.db
从当前目录复制到实用程序 pod 的根目录:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG cp snapshot.db \ USER_CLUSTER_NAME/etcd-utility-0:snapshot.db --container etcd-utility
通过 shell 进入
etcd-utility
容器:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG exec it \ etcd-utility-0 --container etcd-utility --namespace USER_CLUSTER_NAME \ -- bin/sh
在 shell 的根目录中,运行以下命令创建一个包含备份的新文件夹:
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
在 shell 中,删除旧的 etcd 数据:
rm -r var/lib/etcd/*
在 shell 中,将恢复后的 etcd 数据复制到其永久位置:
cp -r default.etcd/* var/lib/etcd/
在 shell 中,输入
exit
以退出 shell。删除崩溃的 etcd pod:
kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG \ delete pod kube-etcd-0 --namespace USER_CLUSTER_NAME
验证 etcd pod 是否不再崩溃。
删除实用程序 pod:
kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG \ delete pod etcd-utility-0 --namespace USER_CLUSTER_NAME
从当前目录中移除
etcd-utility.yaml
:rm etcd-utility.yaml
从备份恢复用户集群 (HA)
本部分介绍如何为高可用性 (HA) 用户集群恢复 etcd 数据。
对于高可用性用户集群,管理员集群中有三个节点作为用户集群的控制层面。这些节点中的每个节点都运行一个 etcd pod,该 pod 维护存储卷上的 etcd 数据。
如果有两个 etcd pod 运行状况良好,并且关联存储卷上的数据保持不变,则无需使用备份文件。这是因为您仍然有一个 etcd 仲裁。
在极少数情况下,如果两个 etcd 存储卷中的数据都损坏,则您需要使用备份文件来恢复 etcd 数据。
要执行本部分中的步骤,您必须已按照备份用户集群中的说明创建了一个 snapshot.db
文件。
列出您的 etcd pod 和节点
列出管理您的用户集群的 etcd 存储区的 etcd pod。这些 pod 在管理员集群中运行:
kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG get pods --namespace USER_CLUSTER_NAME \ --output wide | grep kube-etcd
输出结果会显示 etcd pod 和 pod 运行的节点。输出中显示的节点是管理员集群中作为用户集群控制层面的节点:
NAME ... NODE kube-etcd-0 ... node-xxx kube-etcd-1 ... node-yyy kube-etcd-2 ... node-zzz
记下 Pod 名称和控制层面节点名称以备后续使用。
请注意,每个 etcd pod 都会以
kube-etcd
后跟数字的形式来命名。 此数字称为 pod 的“成员编号”。它会将 pod 标识为容纳用户集群对象数据的 etcd 集群的特定成员。本指南使用占位符 MEMBER_NUMBER 来指代 etcd pod 成员编号。另请注意,etcd 集群中的每个 pod 都在各自的节点上运行。
准备部署实用程序 pod
为用户集群的 Kubernetes API 服务器保存 PodDisruptionBudget (PDB) 清单。然后删除 PDB。
kubectl --kubeconfig ADMIN_CLUSTER_KUBECONIFG get pdb --namespace USER_CLUSTER_NAME \ kube-apiserver-pdb --output yaml > kube-apiserver-pdb.yaml kubectl --kubeconfig ADMIN_CLUSTER_KUBECONIFG delete pdb --namespace USER_CLUSTER_NAME \ kube-apiserver-pdb
停止 Kubernetes API 服务器和 etcd 维护 Deployment。这样可以确保在恢复期间没有组件使用 etcd:
kubectl --kubeconfig ADMIN_CLUSTER_KUBECONIFG --namespace USER_CLUSTER_NAME \ scale --replicas 0 statefulset kube-apiserver kubectl --kubeconfig ADMIN_CLUSTER_KUBECONIFG --namespace USER_CLUSTER_NAME \ scale --replicas 0 deployment gke-master-etcd-maintenance
回调您的 etcd pod 的容器映像的名称。
部署实用程序 pod
对您的每个 etcd pod 执行本部分中的步骤。
回调 etcd pod 的名称和运行 pod 的节点的名称。
在当前目录中将以下 pod 清单保存在名为
etcd-utility-MEMBER_NUMBER.yaml
的文件中:apiVersion: v1 kind: Pod metadata: name: etcd-utility-MEMBER_NUMBER namespace: USER_CLUSTER_NAME spec: containers: - command: ["/bin/sh"] args: ["-ec", "while :; do echo '.'; sleep 5 ; done"] image: gcr.io/gke-on-prem-release/etcd-util:GKE_ON_PREM_VERSION name: etcd-utility volumeMounts: - mountPath: /var/lib/etcd name: data - mountPath: /etcd.local.config/certificates name: etcd-certs nodeSelector: kubernetes.googleapis.com/cluster-name: USER_CLUSTER_NAME kubernetes.io/hostname: NODE_NAME tolerations: - effect: NoExecute key: node.kubernetes.io/not-ready operator: Exists tolerationSeconds: 300 - effect: NoExecute key: node.kubernetes.io/unreachable operator: Exists tolerationSeconds: 300 - effect: NoSchedule key: node.kubernetes.io/unschedulable operator: Exists volumes: - name: data persistentVolumeClaim: claimName: data-kube-etcd-MEMBER_NUMBER - name: etcd-certs secret: defaultMode: 420 secretName: kube-etcd-certs
上面的清单描述了您为了恢复 etcd 数据而临时运行的实用程序 pod。
在管理员集群中创建实用程序 pod:
kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG apply -f etcd-utility-MEMBER_NUMBER.yaml
将备份文件
snapshot.db
复制到实用程序 pod 的根目录中:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONIFG cp snapshot.db \ USER_CLUSTER_NAME/etcd-utility-MEMBER_NUMBER:snapshot.db
通过 shell 进入实用程序 pod 中的
etcd-utility
容器:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONIFG exec -it --namespace USER_CLUSTER_NAME \ etcd-utility-MEMBER_NUMBER --container etcd-utility -- bin/sh
在 shell 的根目录中,使用
snapshot.db
来恢复 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 \ --name=kube-etcd-MEMBER_NUMBER \ --initial-cluster=kube-etcd-0=https://kube-etcd-0.kube-etcd:2380,kube-etcd-1=https://kube-etcd-1.kube-etcd:2380,kube-etcd-2=https://kube-etcd-2.kube-etcd:2380 \ --initial-cluster-token=etcd-cluster-1 \ --initial-advertise-peer-urls=https://kube-etcd-MEMBER_NUMBER.kube-etcd:2380 \ snapshot restore snapshot.db
上述命令将 etcd 数据存储在
/kube-etcd-MEMBER_NUMBER.etcd
目录中。在 shell 中,删除旧的 etcd 数据:
rm -r var/lib/etcd/*
在 shell 中,将恢复后的 etcd 数据复制到其永久位置:
cp -r kube-etcd-MEMBER_NUMBER.etcd/* var/lib/etcd/
在 shell 中,移除临时 etcd 目录和备份文件:
rm -R kube-etcd-MEMBER_NUMBER.etcd/ rm snapshot.db
在 shell 中,输入
exit
以退出 shell。删除实用程序 pod:
kubectl --kubeconfig ADMIN_CLUSTER_KUBECONIFG delete pod \ --namespace USER_CLUSTER_NAME etcd-utility-MEMBER_NUMBER
重启组件
现在您已部署和删除了实用程序 pod,接下来需要重启一些集群组件。
在
kube-etcd
StatefulSet 中重启 pod:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG rollout restart statefulset \ --namespace USER_CLUSTER_NAME kube-etcd
为您的用户集群启动 Kubernetes API 服务器:
kubectl --kubeconfig ADMIN_CLUSTER_KUBECONIFG scale statefulset --replicas 3 \ --namespace USER_CLUSTER_NAME kube-apiserver
为您的用户集群启动 etcd 维护 Deployment:
kubectl --kubeconfig ADMIN_CLUSTER_KUBECONIFG scale deployment --replicas 1 \ --namespace=USER_CLUSTER_NAME gke-master-etcd-maintenance
为 Kubernetes API 服务器恢复 PDB:
kubectl --kubeconfig ADMIN_CLUSTER_KUBECONIFG apply -f kube-apiserver-pdb.yaml
备份管理员集群
管理员集群备份包含以下内容:
- 管理员集群的 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 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,请执行以下操作:
使用 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 +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 地址。
停止
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/
使用 Docker 运行
etcdctl restore
:sudo docker run --rm \ -v '/mnt:/backup' \ -v '/var/lib/etcd:/var/lib/etcd' --env ETCDCTL_API=3 'gcr.io/gke-on-prem-release/etcd-util:GKE_ON_PREM_VERSION' /bin/sh -c "etcdctl snapshot restore '/backup/snapshot.db'; rm -r /var/lib/etcd/*; 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
将
/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 文件访问恢复的集群。
自动备份集群
您可以使用此处提供的示例脚本自动备份集群。请注意,以下脚本不受支持,仅供参考,您应在此基础上编写更好、更可靠且更完善的脚本。在运行脚本之前,请在脚本开头填写五个变量的值:
- 将
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 ${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 -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 admin_snapshot.db"
kubectl --kubeconfig=${ADMIN_CLUSTER_KUBECONFIG} cp -n kube-system ${admin_etcd}:admin_snapshot.db $BACKUP_DIR/admin-cluster_snapshot.db
后续步骤
- 了解如何诊断集群问题
- 了解 augur,这是一个用于从 etcd 备份中恢复单个对象的开源工具。