bitnami etcd 故障成员恢复
本文介绍了在使用 bitnami/etcd 部署的集群中,如何恢复故障成员的方法。首先在处理前,往 etcd 集群中添加一些数据,以验证恢复方案不会导致集群数据丢失。然后,通过删除 etcd-1 pv 的数据目录来模拟 etcd-1 成员故障,并查看 etcd-1 pod 日志、etcd 集群成员状态以及 endpoint 健康状态来分析故障原因。接着,本文提供了一套恢复方案,包括将故障成员 etcd-1 从集群中移除、将 etcd statefulsets 缩放为 0、删除故障成员 etcd-1 绑定的 pv 的数据目录、修改 statefulsets 中 ETCD_INITIAL_CLUSTER_STATE 配置的值为 "existing"、将 etcd statefulsets 恢复为原来的副本数以及检查 etcd 集群 endpoint 健康状态等步骤。最后,验证数据是否完整。
bitnami etcd 故障成员恢复
环境准备
准备一个使用 bitnami/etcd 部署的集群。
查看 statefulsets:
| 1 | [root@cnode1 ~]# kubectl -n etcd get statefulsets.apps | 
查看 pod:
| 1 | [root@cnode1 ~]# kubectl -n etcd get pod | 
查看 ETCD_INITIAL_CLUSTER_STATE 配置:
| 1 | [root@cnode1 ~]# kubectl -n etcd get statefulsets.apps etcd -o yaml | grep ETCD_INITIAL_CLUSTER_STATE -A 1 | 
查看 etcd 集群成员状态:
| 1 | I have no name!@etcd-0:/opt/bitnami/etcd$ bin/etcdctl member list | 
该集群有 3 个成员:
- etcd-0
- etcd-1
- etcd-2
添加测试数据
在处理前,先往 etcd 集群中添加一些数据,以验证恢复方案不会导致集群数据丢失。
| 1 | [root@cnode1 ~]# kubectl -n etcd exec -it etcd-0 -- bash | 
破坏 etcd-1 成员
获取 etcd-1 的 pv:(所有 pv 均使用 local-storage)
| 1 | [root@cnode1 ~]# kubectl -n etcd get pvc | 
获取 etcd-1 pv 所在的节点:
| 1 | [root@cnode1 ~]# kubectl get pv pvc-4832f8c4-0827-4992-9e39-185f9c0f8e20 -o yaml | grep nodeAffinity -A 7 | 
获取 etcd-1 pv 的数据目录:
| 1 | [root@cnode1 ~]# kubectl get pv pvc-4832f8c4-0827-4992-9e39-185f9c0f8e20 -o yaml | grep hostPath -A 2 | 
进入节点 cnode3 后台:
| 1 | ssh root@cnode3 | 
删除 etcd-1 pv 的数据目录:
| 1 | [root@cnode3 ~]# rm -rf /data/local-path-provisioner/pvc-4832f8c4-0827-4992-9e39-185f9c0f8e20_etcd_data-etcd-1/data/ | 
删除 etcd-1 pod:
| 1 | [root@cnode1 ~]# kubectl -n etcd delete pod etcd-1 | 
等待 etcd-1 pod 重新被拉起:
| 1 | [root@cnode1 ~]# kubectl -n etcd get pod | 
此状态下,重启 etcd 集群也无法恢复:
| 1 | [root@cnode1 ~]# kubectl -n etcd rollout restart statefulset etcd | 
分析 etcd-1 故障
查看 etcd-1 pod 日志:
| 1 | [root@cnode1 ~]# kubectl -n etcd logs -f etcd-1 | 
查看 etcd 集群成员状态:(这个命令无法得知 endpoint 的健康状态)
| 1 | [root@cnode1 ~]# kubectl -n etcd exec -it etcd-0 -- bash | 
查看 etcd 集群 endpoint 健康状态:
| 1 | I have no name!@etcd-0:/opt/bitnami/etcd$ bin/etcdctl endpoint health --endpoints=etcd-0.etcd-headless.etcd:2380,etcd-1.etcd-headless.etcd:2380,etcd-2.etcd-headless.etcd:2380 -w table | 
恢复方案
(1)将故障成员 etcd-1 从集群中移除
| 1 | [root@cnode1 ~]# kubectl -n etcd exec -it etcd-0 -- bash | 
(2)将 etcd statefulsets 缩放为 0
| 1 | [root@cnode1 ~]# kubectl -n etcd scale statefulset etcd --replicas=0 | 
(3)删除故障成员 etcd-1 绑定的 pv 的数据目录
- 获取 etcd-1 的 pv - 1 
 2
 3
 4
 5- [root@cnode1 ~]# kubectl -n etcd get pvc 
 NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
 data-etcd-0 Bound pvc-2a2f2a25-69b3-41ab-a21d-a5aa3d05277d 10Gi RWO local-storage 30d
 data-etcd-1 Bound pvc-4832f8c4-0827-4992-9e39-185f9c0f8e20 10Gi RWO local-storage 4h10m
 data-etcd-2 Bound pvc-6da8bcd7-cd2a-43fc-9849-7e1c2870f193 10Gi RWO local-storage 30d
- 获取 etcd-1 pv 所在的节点 - 1 
 2
 3
 4
 5
 6
 7
 8
 9- [root@cnode1 ~]# kubectl get pv pvc-4832f8c4-0827-4992-9e39-185f9c0f8e20 -o yaml | grep nodeAffinity -A 7 
 nodeAffinity:
 required:
 nodeSelectorTerms:
 - matchExpressions:
 - key: kubernetes.io/hostname
 operator: In
 values:
 - cnode3
- 获取 etcd-1 pv 的数据目录 - 1 
 2
 3
 4- [root@cnode1 ~]# kubectl get pv pvc-4832f8c4-0827-4992-9e39-185f9c0f8e20 -o yaml | grep hostPath -A 2 
 hostPath:
 path: /data/local-path-provisioner/pvc-4832f8c4-0827-4992-9e39-185f9c0f8e20_etcd_data-etcd-1
 type: DirectoryOrCreate
- 进入节点 cnode3 后台 - 1 - ssh root@cnode3 
- 清除 etcd-1 pv 的数据目录 - 1 
 2
 3- [root@cnode1 ~]# rm -rf /data/local-path-provisioner/pvc-4832f8c4-0827-4992-9e39-185f9c0f8e20_etcd_data-etcd-1/data/ 
 [root@cnode1 ~]# ls /data/local-path-provisioner/pvc-4832f8c4-0827-4992-9e39-185f9c0f8e20_etcd_data-etcd-1/
 [root@cnode1 ~]#
(4)修改 statefulsets 中 ETCD_INITIAL_CLUSTER_STATE 配置的值为 "existing"
| 1 | [root@cnode1 ~]# kubectl -n etcd edit statefulsets.apps etcd | 
修改内容如下:
| 1 | - name: ETCD_INITIAL_CLUSTER_STATE | 
(5)将 etcd statefulsets 恢复为原来的副本数
| 1 | [root@cnode1 ~]# kubectl -n etcd scale statefulset etcd --replicas=3 | 
(6)查看 etcd-1 的日志
| 1 | [root@cnode1 ~]# kubectl -n etcd logs -f etcd-1 | 
(7)查看 etcd statefulsets 状态
| 1 | [root@cnode1 ~]# kubectl -n etcd get statefulsets.apps etcd | 
(8)检查 etcd 集群 endpoint 健康状态
| 1 | [root@cnode1 ~]# kubectl -n etcd exec -it etcd-0 -- bash | 
(9)查看 etcd 集群成员状态
| 1 | [root@cnode1 ~]# kubectl -n etcd exec -it etcd-0 -- bash | 
(10)修改 statefulsets 中 ETCD_INITIAL_CLUSTER_STATE 配置的值恢复为 "new"(可选)
| 1 | [root@cnode1 ~]# kubectl -n etcd edit statefulsets.apps etcd | 
修改内容如下:
| 1 | - name: ETCD_INITIAL_CLUSTER_STATE | 
等待 statefulsets 重启完成:
| 1 | [root@cnode1 ~]# kubectl -n etcd get statefulsets.apps etcd | 
(11)验证数据是否完整
| 1 | [root@cnode1 ~]# kubectl -n etcd exec -it etcd-0 -- bash |