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 个节点故障),进一步提升可用性。
相关推荐
运维开发故事3 天前
基于 Arthas 的多集群在线诊断系统设计与实现
kubernetes
Patrick_Wilson5 天前
从「改个端口」到 502:Next.js on k8s 的容器端口、Service 映射与 env 覆盖
docker·kubernetes·next.js
探索云原生5 天前
K8s 1.36 这个 GA 特性,把 initContainer 拉模型的 hack 干掉了
ai·云原生·kubernetes
云恒要逆袭5 天前
运行你的第一个Docker容器
后端·docker·容器
Java之美6 天前
一次k8s升级引发的DevicePlugin注册失败
云原生·kubernetes
程序员老赵7 天前
10 分钟部署 OpenCode:Docker 一键安装,浏览器打开就能用 AI 写代码(附完整命令与排错)
docker·容器·ai编程
武子康10 天前
调查研究-183 Apple container:Mac 上用轻量 VM 跑 Linux 容器,Swift 会改写本地容器体验吗?
docker·容器·apple
2601_9618752413 天前
决战申论100题2026|最新|范文
linux·容器·centos·debian·ssh·fabric·vagrant
java_cj13 天前
深入kube-apiserver认证机制:从Bearer Token到mTLS的完整认证链解析
linux·运维·服务器·云原生·容器·kubernetes