k8s的ETCD故障处理

在 3 节点 Master 的 etcd 集群(Raft 共识集群)中,数据恢复需区分集群部分节点故障集群全量故障 两种场景,核心原则是:优先通过健康节点自动恢复,仅当多数节点(≥2)数据损坏 / 丢失时,才从快照全量恢复(3 节点 etcd 集群需至少 2 个节点达成共识,因此全量恢复需先重置集群再重建)。

一、前提准备

  1. 确认 etcd 集群状态

    复制代码
    # 任选一个Master节点,检查etcd集群成员和健康状态
    ETCDCTL_API=3 etcdctl \
    --endpoints=https://127.0.0.1:2379 \
    --cacert=/etc/kubernetes/pki/etcd/ca.crt \
    --cert=/etc/kubernetes/pki/etcd/server.crt \
    --key=/etc/kubernetes/pki/etcd/server.key \
    member list  # 查看集群成员(正常应显示3个节点)
    
    ETCDCTL_API=3 etcdctl \
    --endpoints="https://master1:2379,https://master2:2379,https://master3:2379" \
    --cacert=/etc/kubernetes/pki/etcd/ca.crt \
    --cert=/etc/kubernetes/pki/etcd/server.crt \
    --key=/etc/kubernetes/pki/etcd/server.key \
    endpoint health  # 检查所有节点健康状态
  2. 准备有效快照 :确保有最新的 etcd 快照(推荐每小时备份,快照命名格式:etcd-snapshot-202512061000.db),快照路径建议统一存放至所有 Master 节点的/var/lib/etcd/snapshots/目录。

二、场景 1:单节点 etcd 数据损坏(多数节点健康)

3 节点 etcd 集群中,若仅 1 个节点数据损坏(如 IO 故障导致),无需全量恢复,只需重置该节点 etcd 并重新加入集群(利用 Raft 共识自动同步数据)。

步骤 1:停止故障节点的 etcd 服务
复制代码
# 在故障Master节点(如master2)停止etcd静态Pod(kubelet会自动重建,需先删除静态Pod文件)
mv /etc/kubernetes/manifests/etcd.yaml /etc/kubernetes/manifests/etcd.yaml.bak
# 等待etcd Pod停止
kubectl -n kube-system get pods | grep etcd
步骤 2:清理故障节点的 etcd 数据目录
复制代码
# 备份旧数据(可选)
mv /var/lib/etcd /var/lib/etcd.bak
# 创建空数据目录
mkdir -p /var/lib/etcd && chown -R root:root /var/lib/etcd
步骤 3:重新加入 etcd 集群
方式 1:通过 kubeadm 重置节点后重新加入(推荐)
复制代码
# 在故障节点执行重置(保留etcd证书)
kubeadm reset --keep-certs
# 从健康Master节点(如master1)获取加入控制平面的命令(master1上执行)
kubeadm token create --print-join-command --certificate-key $(kubeadm init phase upload-certs --upload-certs | grep -v 'Certificate key' | tail -1)
# 示例输出:kubeadm join vip:6443 --token xxx --discovery-token-ca-cert-hash sha256:xxx --control-plane --certificate-key xxx

# 在故障节点执行上述join命令,重新加入集群
kubeadm join vip:6443 --token xxx --discovery-token-ca-cert-hash sha256:xxx --control-plane --certificate-key xxx
方式 2:手动添加 etcd 成员(适用于 kubeadm 外置 etcd 场景)
复制代码
# 在健康节点(如master1)添加故障节点到etcd集群
ETCDCTL_API=3 etcdctl \
--endpoints=https://master1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
member add etcd-master2 --peer-urls=https://master2:2380

# 在故障节点恢复etcd静态Pod文件
mv /etc/kubernetes/manifests/etcd.yaml.bak /etc/kubernetes/manifests/etcd.yaml
# kubelet会自动重建etcd Pod,并从集群同步数据
步骤 4:验证节点恢复
复制代码
# 检查etcd集群成员状态(健康节点执行)
ETCDCTL_API=3 etcdctl \
--endpoints=https://master1:2379,https://master2:2379,https://master3:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
member list

# 检查所有etcd节点健康状态
ETCDCTL_API=3 etcdctl endpoint health --endpoints=https://master1:2379,https://master2:2379,https://master3:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key

三、场景 2:多数节点(≥2)数据损坏 / 全集群故障

当 2 个及以上节点 etcd 数据损坏,或集群完全无法启动时,需从快照全量恢复 etcd 集群,步骤如下:

步骤 1:停止所有 Master 节点的 etcd 服务
复制代码
# 在所有Master节点(master1、master2、master3)执行
mv /etc/kubernetes/manifests/etcd.yaml /etc/kubernetes/manifests/etcd.yaml.bak
# 等待所有etcd Pod停止
kubectl -n kube-system get pods | grep etcd
步骤 2:选择一个节点作为恢复主节点(如 master1)
复制代码
# 在master1清理旧数据
mv /var/lib/etcd /var/lib/etcd.bak
# 从快照恢复etcd数据(指定新的集群名称和初始集群配置)
ETCDCTL_API=3 etcdctl snapshot restore \
/var/lib/etcd/snapshots/etcd-snapshot-202512061000.db \
--data-dir=/var/lib/etcd \
--name=etcd-master1 \
--initial-cluster=etcd-master1=https://master1:2380,etcd-master2=https://master2:2380,etcd-master3=https://master3:2380 \
--initial-cluster-token=etcd-cluster-token \
--initial-advertise-peer-urls=https://master1:2380

# 修复数据目录权限
chown -R root:root /var/lib/etcd
步骤 3:启动主节点 etcd 服务
复制代码
# 在master1恢复etcd静态Pod文件
mv /etc/kubernetes/manifests/etcd.yaml.bak /etc/kubernetes/manifests/etcd.yaml
# 等待etcd Pod启动
kubectl -n kube-system get pods | grep etcd-master1
步骤 4:将其他节点加入恢复后的 etcd 集群
(1)清理 master2、master3 的 etcd 数据
复制代码
# 在master2、master3执行
mv /var/lib/etcd /var/lib/etcd.bak
mkdir -p /var/lib/etcd && chown -R root:root /var/lib/etcd
(2)在 master1 添加 master2、master3 为 etcd 成员
复制代码
# 在master1执行:添加master2
ETCDCTL_API=3 etcdctl \
--endpoints=https://master1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
member add etcd-master2 --peer-urls=https://master2:2380

# 添加master3
ETCDCTL_API=3 etcdctl \
--endpoints=https://master1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
member add etcd-master3 --peer-urls=https://master3:2380
(3)启动 master2、master3 的 etcd 服务
复制代码
# 在master2、master3执行
mv /etc/kubernetes/manifests/etcd.yaml.bak /etc/kubernetes/manifests/etcd.yaml
# 等待etcd Pod启动并同步数据
kubectl -n kube-system get pods | grep etcd
步骤 5:验证集群恢复
复制代码
# 检查etcd集群成员和健康状态
ETCDCTL_API=3 etcdctl \
--endpoints=https://master1:2379,https://master2:2379,https://master3:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
member list

ETCDCTL_API=3 etcdctl endpoint health --endpoints=https://master1:2379,https://master2:2379,https://master3:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key

# 验证K8s集群功能
kubectl get nodes
kubectl get pods -n kube-system
kubectl create ns test-ns && kubectl delete ns test-ns # 测试元数据写入

四、关键注意事项

  1. 快照时效性:恢复用的快照必须是集群故障前的有效快照,建议快照备份至独立存储(如 NFS、对象存储),避免与 etcd 数据同盘丢失;
  2. 证书一致性 :恢复过程中需确保所有节点的 etcd 证书(/etc/kubernetes/pki/etcd/)一致,否则节点无法加入集群;
  3. 静态 Pod 配置 :kubeadm 部署的 etcd 为静态 Pod,修改/etc/kubernetes/manifests/etcd.yaml后,kubelet 会自动重建 Pod,无需手动启动;
  4. 网络连通性:恢复过程中确保 3 个 Master 节点之间的 2379(客户端端口)、2380(Peer 端口)互通,否则 etcd 无法同步数据;
  5. 数据一致性:全量恢复后,集群元数据会回滚至快照时间点,需确认快照时间点后的操作(如新建 Pod、Service)需重新执行。

五、优化建议(避免集群级 etcd 故障)

  1. 快照自动化:通过 crontab 或 K8s CronJob 定期备份 etcd,快照同时同步至异地存储;
  2. 监控强化 :监控 etcd 集群的etcd_server_quota_backend_bytes_used(存储使用率)、etcd_raft_is_leader(Leader 状态)、etcd_disk_wal_fsync_duration_seconds(IO 耗时),提前预警;
  3. 存储隔离:每个 Master 节点的 etcd 数据目录使用独立 SSD/NVMe 磁盘,避免 IO 资源竞争;
  4. 集群容灾:生产环境建议部署 5 节点 etcd 集群(容忍 2 个节点故障),进一步提升可用性。
相关推荐
2301_810746311 小时前
CKA冲刺40天笔记 - day23 Kubernetes RBAC Explained - Role Based Access Control
笔记·kubernetes
Yyyy4822 小时前
k8s部署wordpress
云原生·容器·kubernetes
一周困⁸天.10 小时前
K8S-Ingress资源对象
云原生·容器·kubernetes
2301_8107463113 小时前
CKA冲刺40天笔记 - day20-day21 SSL/TLS详解
运维·笔记·网络协议·kubernetes·ssl
❀͜͡傀儡师13 小时前
docker 部署 komari-monitor监控
运维·docker·容器·komari
悬弧15 小时前
第2章:工作负载管理 - 可视化应用部署
kubernetes·k8s
一条懒鱼66615 小时前
K8S-Ingress资源对象
云原生·容器·kubernetes
luback16 小时前
前端对Docker简单了解
运维·docker·容器
帷幄庸者16 小时前
记一次Kubernetes“僵尸”挖矿病毒的排查与歼灭全录
云原生·容器·kubernetes