etcd 集群故障排查与节点扩容维护操作手册
文档信息
- 故障现象:Prometheus 频繁触发
etcd_server_leader_changes_seen_total >= 4告警(15分钟内集群频繁切换 Leader)。 - 根本原因:
host53节点物理内存使用率超过 90%,触发操作系统激进的内存回收(Page Cache Reclaim),导致 etcd 事务及租约请求处理超时(超过 100ms),引发节点间心跳断开与频繁选主。 - 核心目标:安全、无缝地对
host53进行资源扩容(增加内存/CPU)并优雅重启服务。
第一部分:etcd 核心状态排查命令
当集群触发频繁选主告警时,使用以下三步快速定位病灶。
1. 检查集群成员与健康度
# 查看成员列表
ETCDCTL_API=3 /usr/local/bin/etcdctl \
--cacert=/etc/etcd/ssl/ca.pem --cert=/etc/etcd/ssl/etcd.pem --key=/etc/etcd/ssl/etcd-key.pem \
--endpoints="https://192.168.120.51:2379,https://192.168.120.52:2379,https://192.168.120.53:2379" \
member list
# 查看端点健康状态
ETCDCTL_API=3 /usr/local/bin/etcdctl --write-out=table \
--cacert=/etc/etcd/ssl/ca.pem --cert=/etc/etcd/ssl/etcd.pem --key=/etc/etcd/ssl/etcd-key.pem \
--endpoints="https://192.168.120.51:2379,https://192.168.120.52:2379,https://192.168.120.53:2379" \
endpoint health
2. 检查数据库大小及 Leader 分布
ETCDCTL_API=3 /usr/local/bin/etcdctl --write-out=table \
--cacert=/etc/etcd/ssl/ca.pem --cert=/etc/etcd/ssl/etcd.pem --key=/etc/etcd/ssl/etcd-key.pem \
--endpoints="https://192.168.120.51:2379,https://192.168.120.52:2379,https://192.168.120.53:2379" \
endpoint status
排查重点:
*DB SIZE:若接近 2GB/8GB 阈值,需执行defrag(碎片整理)。
*IS LEADER:确认当前控制中心在哪里。
*RAFT INDEX:确认三节点数据是否强一致。
3. 日志定位(抓取底层超时铁证)
在各节点执行以下命令,过滤近 24 小时内的超时警告:
journalctl -u etcd --since "24 hours ago" | grep -E "took too long|slow"
典型特征:如果出现大量
"msg":"apply request took too long",且took集中在 100ms~200ms,说明底层 I/O 遭到了严重的系统级资源抢占(如本次事件中的内存耗尽)。
第二部分:host53 节点安全维护与重启步骤
针对 3 节点的分布式 etcd 集群,必须遵循”先隔离、再优雅停止、最后单点维护”的原则,严禁暴力关机。
阶段一:重启前准备(集群保护与隔离)
1. K8s 控制平面隔离与驱逐
在任意可执行 kubectl 的主控节点上,将 host53 设为维护模式,安全驱逐运行在其上的非核心业务 Pod:
# 1. 标记节点不可调度
kubectl cordon host53
# 2. 强制驱逐 Pod(忽略守护进程,允许删除临时数据)
kubectl drain host53 --ignore-daemonsets --delete-emptydir-data --force
2. 确认双节点存活状态
在 host51 或 host52 上确认,当 host53 离线后,剩下的双节点能维持法定人数(Quorum):
ETCDCTL_API=3 /usr/local/bin/etcdctl --write-out=table \
--cacert=/etc/etcd/ssl/ca.pem --cert=/etc/etcd/ssl/etcd.pem --key=/etc/etcd/ssl/etcd-key.pem \
--endpoints="https://192.168.120.51:2379,https://192.168.120.52:2379" \
endpoint health
3. 登录 host53 优雅停止系统服务
依次停止 K8s 代理、容器运行时和 etcd 本身,释放文件锁:
# 1. 停止 Kubelet
systemctl stop kubelet
# 2. 停止容器引擎(根据实际部署选择 docker 或 containerd)
systemctl stop docker # 或 systemctl stop containerd
# 3. 停止 etcd 核心进程
systemctl stop etcd
# 4. 确认无 etcd 残留进程
阶段二:硬件调整(加资源)
- 在虚拟化平台(VMware / OpenStack / 云平台)上将
host53关机。 - 调大该虚拟机的 内存 和 CPU 配额。
- 重新开机启动
host53。
阶段三:开机后恢复与健康检查
1. 依次拉起服务
登录 host53,按照”底层组件 → 高层组件”的顺序拉起:
# 1. 首先拉起 etcd(它会自动向 51/52 同步维护期间落后的数据)
systemctl start etcd
systemctl status etcd
# 2. 拉起容器引擎与 Kubelet
systemctl start docker # 或 systemctl start containerd
systemctl start kubelet
2. 全局健康度交叉验证
在任意节点验证 3 节点 etcd 是否完全合流且状态恢复:
ETCDCTL_API=3 /usr/local/bin/etcdctl --write-out=table \
--cacert=/etc/etcd/ssl/ca.pem --cert=/etc/etcd/ssl/etcd.pem --key=/etc/etcd/ssl/etcd-key.pem \
--endpoints="https://192.168.120.51:2379,https://192.168.120.52:2379,https://192.168.120.53:2379" \
endpoint status
确认:三节点的 RAFT INDEX 恢复一致,ERRORS 为空。
3. 取消节点隔离
确认一切无误后,解除 K8s 的保护限制,允许 Pod 回流:
kubectl uncordon host53
第三部分:长期防御与长效调优建议
为防止内存再次爆满导致 etcd 崩溃,建议后续实施以下优化:
- 设置 K8s 污点隔离(强烈推荐):
禁止非控制平面的业务 Pod 混部在 etcd 节点上,防止它们抢占内存。kubectl taint nodes host53 node-role.kubernetes.io/master="":NoSchedule --overwrite kubectl taint nodes host53 node-role.kubernetes.io/control-plane="":NoSchedule --overwrite - 提升 etcd 进程的内核调度优先级:
修改/usr/lib/systemd/system/etcd.service,在[Service]中加入,赋予其最高级别的 CPU 与 I/O 调度权:Nice=-20 CPUSchedulingPolicy=rr CPUSchedulingPriority=50 IOSchedulingClass=best-effort IOSchedulingPriority=0 - 优化 etcd 选主容忍度:
若底层硬件性能存在偶发抖动,可在启动参数中放宽心跳超时(默认100ms/1000ms):--heartbeat-interval=250 --election-timeout=1250