K8S ETCD 集群裂开极限拯救业务系统

552 阅读5分钟

场景复现

故障描述

在真实业务场景下,三台 Master 组建的 kubernetes 集群,其中一台 ETCD 意外脱离集群,导致 etcd 状态异常,但集群服务未受到影响。

此时的处理方式预期是通过清理故障 ETCD 所在 Node 上的 ETCD 数据,然后 delete 掉这个节点,并使用 kubeadm join 方法把这台 Master 重新加入集群。但实际情况总是背道而驰,在执行 join 的时候出现其他错误,导致 node 无法正常加入集群。排查后发现,此时剩下的两台 etcd 也出现故障,集群整个裂开。

根据业务场景搭建测试环境,模拟场景拓扑参考图(三台 kvm 分别为三台 Master)。

查看正常运行集群状态

# 1. 进入一个 etcd pod,执行下面命令
export ETCDCTL_API=3
alias etcdctl='etcdctl --endpoints=172.28.120.51:2379,172.28.120.52:2379,172.28.120.50:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key'

2. 执行下面命令获取 etcd 状态:
sh-5.0# etcdctl member list -w table
+------------------+---------+-----------+----------------------------+----------------------------+------------+
|        ID        | STATUS  |   NAME    |         PEER ADDRS         |        CLIENT ADDRS        | IS LEARNER |
+------------------+---------+-----------+----------------------------+----------------------------+------------+
|  18fc15545a6b2a6 | started | kvm120-50 | https://172.28.120.50:2380 | https://172.28.120.50:2379 |      false |
| 4826ab5891646eb9 | started | kvm120-51 | https://172.28.120.51:2380 | https://172.28.120.51:2379 |      false |
| 4a57c85ca3b3df25 | started | kvm120-52 | https://172.28.120.52:2380 | https://172.28.120.52:2379 |      false |
+------------------+---------+-----------+----------------------------+----------------------------+------------+
sh-5.0# etcdctl endpoint status -w table
+--------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
|      ENDPOINT      |        ID        | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+--------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| 172.28.120.51:2379 | 4826ab5891646eb9 |   3.5.0 |  3.4 MB |     false |      false |         3 |       3817 |               3817 |        |
| 172.28.120.52:2379 | 4a57c85ca3b3df25 |   3.5.0 |  3.4 MB |     false |      false |         3 |       3817 |               3817 |        |
| 172.28.120.50:2379 |  18fc15545a6b2a6 |   3.5.0 |  3.4 MB |      true |      false |         3 |       3817 |               3817 |        |
+--------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+

此时,kvm120-50 为 LEADER image.png

制造故障场景

对 kvm120-50 执行 kubeadm reset 之后 etcd 状态: image.png

制造 ETCD 集群故障

人为删除 ETCD 数据,制造出 k8s 集群故障场景, image.png

稍等片刻, k8s 状态出現异常,集群离开 image.png image.png


ETCD 修復解決

修复思路: 找到一台数据完整的 ETCD Master,作为一个单 Master 集群先把 ETCD 启动成功,恢复 kubelet 服务。而后依次把其他 Master 节点加入集群,最终实现三台 Master 组建 ETCD 集群。

单节点启动 kvm120-51

# 进 kubernentes 目录
cd /etc/kubernetes/manifests/
# 修改文件内容(只展示部分内容)
vim etcd.yaml
----------------
當前内容:
- --initial-cluster=kvm120-50=https://172.28.120.50:2380,kvm120-51=https://172.28.120.51:2380,kvm120-52=https://172.28.120.52:2380
- --initial-cluster-state=existing
-------------------------
修改為:
- --initial-cluster=kvm120-51=https://172.28.120.51:2380
- --initial-cluster-state=new
- --force-new-cluster 

# 重啓kubelet
systemctl restart kubelet 

修改内容參考 image.png 此时查看 etcd 容器状态,发现已经启动成功 image.png 并且可以执行 kubectl 命令,查看etcd 集群。不要被 kvm120-50 etcd 处于running 状态迷惑,是历史状态记录。 image.png 此时进入 Pod 查看 etcd 状态,只有 kvm120-51 一个 member,其他两个 etcd 依然是未启动状态 image.png

解決 kvm120-52

登录 kvm120-52 机器

# 1. 暂停 kubelet 服务
systemctl stop kubelet

# 2. 删除 etcd data
 rm -rf member/

# 3. 修改 etcd 配置文件
vim /etc/kubernetes/manifests/etcd.yaml
-------------------
当前内容:
- --initial-cluster=kvm120-50=https://172.28.120.50:2380,kvm120-52=https://172.28.120.52:2380
修改为:
- --initial-cluster=kvm120-51=https://172.28.120.51:2380,kvm120-52=https://172.28.120.52:2380
# 注意修改内容为集群 kvm120-50 改为 kvm120-51

# 4. 启动 kubelet
systemctl start kubelet

# 5. 进入 kvm120-51 的 etcd 中,执行 member add 
etcdctl member add kvm120-52 --endpoints=172.28.120.51:2379 --peer-urls="https://172.28.120.52:2380"
return result:
Member c5c8dfd52609bd98 added to cluster 151f8d40c4dcdb0c
ETCD_NAME="kvm120-52"
ETCD_INITIAL_CLUSTER="kvm120-51=https://172.28.120.51:2380,kvm120-52=https://172.28.120.52:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://172.28.120.52:2380"
ETCD_INITIAL_CLUSTER_STATE="existing"

修改内容参考 image.png 稍等片刻,在kvm120-52 上查看 etcd 容器启动状态,预期是member 加入成功,并且 Pod 状态也正常 image.png image.png image.png

解決 kvm120-50

因为 kvm120-50 已经执行 kubeadm reset ,所以需要先把这个 node 加入k8s 集群

已有 master 节点(kvm120-51)执行:
1、kubeadm init phase upload-certs --upload-certs
return result:
W1020 17:38:45.294364   30188 version.go:103] could not fetch a Kubernetes version from the internet: unable to get URL "https://dl.k8s.io/release/stable-1.txt": Get "https://cdn.dl.k8s.io/release/stable-1.txt": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
W1020 17:38:45.294615   30188 version.go:104] falling back to the local client version: v1.22.1
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[upload-certs] Using certificate key:
926101fa7099309378b20014e07089685b107727ceee0xxxxxxxxxxx

2、kubeadm token create  --print-join-command

kubeadm join 172.28.8.112:6443 --token 3r5iyj.sssssssssss --discovery-token-ca-cert-hash sha256:4c9ef3b5927c8cbb46f2fe189738e46cea77cab980df1c6f751683xxxxxxxxx


3、将1、2步命令的结果拼合到一起,在新的master上执行。
第2步打印的命令 --control-plane --certificate-key 第一步的生成的key

拼合完的命令是类似这样:
kubeadm join 172.28.8.112:6443 --token 3r5iyj.sssssssssss --discovery-token-ca-cert-hash sha256:4c9ef3b5927c8cbb46f2fe189738e46cea77cab980df1c6f751683xxxxxxxxx --control-plane --certificate-key 926101fa7099309378b20014e07089685b107727ceee0xxxxxxxxxxx 

在需要加入集群的 node 上执行(在 kvm120-50) image.png

最后的返回结果 image.png

执行 kubectl get node如下所示,此时 ndoe 已经成功加入集群: image.png

执行完成后登录 ETCD 查看結果 image.png


总结

在解决问题过程中,发现 kubernentes 在部署集群时 etcd.yaml 中的内容是不一样的。第一台 Master 启动时只有一台主机信息,而第二台 Master 启动时只有两台信息,第三台就有完整信息。所以在手工启动 ETCD 过程中需要修改这部分内容才能够解决问题。

【参考连接】

[1] # k8s 集群灾难恢复 cnblog

[2] # Disaster recovery etcd官网