etcd 集群实战:强一致、Leader 选举与三节点高可用状态底座


很多自托管架构里,最大的公共单点往往不是数据库,而是那层"谁都不太当回事"的状态存储:K8s 的集群状态、分布式锁、服务发现、选举协调、配置下发,全压在它身上。etcd 就是这个角色的行业标准——一个高可用的分布式键值存储。它解决的问题是"多台机器如何对同一份状态达成一致、并容忍节点故障"。这篇讲清 etcd 解决什么、三节点集群怎么搭、Raft 怎么工作、CPU/IO 类典型坑怎么排,以及它适合承接什么、不适合承接什么。

一、etcd 解决什么:把"分布式系统里的公共状态"变得一致且高可用

分布式系统里,最危险的是各节点"各说各话":同一条配置在 A 机器和 B 机器上不一样、两个节点都以为自己是主、锁被两个进程同时持有一半天。etcd 的核心价值是"给多节点提供一个强一致的状态层":任何时刻只有一份被各方认可的值,写进去就持久化、读出来是一致的;节点挂了会自动选新主、数据不丢(前提是多数派还活着)。自托管里它最常见的两个位置:作为 K8s 的"大脑"(存所有资源对象),以及作为分布式锁/选主/服务发现的底座(配合如"谁来做 leader"的选主逻辑)。理解 etcd 要先抓住它"强一致 + 多数派"的本质:它不是普通缓存,写要过"多数派确认",所以延迟有下限,别把它当高速 KV 用。

二、三节点集群怎么搭:从 binary 或打包方式快速起一个可用集群

etcd 的事务是"节点数 + 编配":写操作需要多数派(N=3 需 2 台)确认,所以奇数节点最划算——三节点坏一台仍可用,五节点坏两台仍可用。起步就用 3 台,别贪多(更多节点 = 每次写等更多确认,反而更慢)。搭建核心是让各节点知道彼此身份与互相可达:每个节点给一个 name、一个 client URL(对外)和一个 peer URL(节点间集群通信),并把全部节点作为 initial cluster 声明。下面是一份三节点 example 的启动姿势。

# 每台节点(etc1/etc2/etc3)下发同一份集群成员后,各自启动 etcd。
# 以 etcd-1 为例,其余两台的 --name/--initial-advertise-peer-urls 换成各自值:
etcd \\
  --name etcd-1 \\
  --data-dir /var/lib/etcd \\
  --initial-advertise-peer-urls http://10.0.0.11:2380 \\
  --listen-peer-urls http://0.0.0.0:2380 \\
  --listen-client-urls http://0.0.0.0:2379,http://10.0.0.11:2379 \\
  --advertise-client-urls http://10.0.0.11:2379 \\
  --initial-cluster \\
    etcd-1=http://10.0.0.11:2380,etcd-2=http://10.0.0.12:2380,etcd-3=http://10.0.0.13:2380 \\
  --initial-cluster-state=existing  # 加入既有集群用 existing;全新集群新建用 new

# 验证健康:任一客户端 URL 上执行
etcdctl --endpoints=http://10.0.0.11:2379,http://10.0.0.12:2379,http://10.0.0.13:2379 endpoint health

刚上手最省心的做法是"让编排器帮你建":K8s(static pod 或 operator)会替你管理这组启动参数;自托管想不手工踩坑,也可以用 docker compose 起三节点(peer 端口对开)。但不管哪种,都要抓住"initial-cluster 是否与真实节点一致"这一关——写错会导致集群起不来或误判已存在。

三、Raft 与健康排查:抓住"Leader / Follower / 多数派"这根主线

etcd 用的是一致性算法 Raft:节点分 Leader(负责接受写、广播)、Follower(跟随复制)、Candidate(选举中)。写一条数据,Leader 先写本地再广播给多数派,得确认才算提交;Leader 挂了,剩余节点发起选举选新主。排查问题先看"谁是 Leader、有没有产生选举风暴、集群是否达到法定票数":用 endpoint status 看各节点角色与版本差距,用 endpoint health 看健康,用 endpoint hashkv 对比各节点数据是否一致(哈希不同说明某节点落后了)。典型坑:一是网络抖动导致频繁 leader 迁移(反复选举)——检查节点间延迟与防火墙;二是某节点磁盘慢拖累整体写延迟——注意 etcd 是"写路径敏感"的。

# 看每个节点角色 / 版本 / 磁盘与后端状态
etcdctl endpoint status --write-out=table \\
  --endpoints=http://10.0.0.11:2379,http://10.0.0.12:2379,http://10.0.0.13:2379

# 看某节点是否已经跟踪上(数据哈希是否和别的一致)
etcdctl endpoint hashkv \\
  --endpoints=http://10.0.0.11:2379,http://10.0.0.12:2379,http://10.0.0.13:2379

四、典型故障与边界:别把 etcd 当缓存,也别用单节点裸跑

etcd 的坑集中在几处。一是"单节点裸跑":很多人为省事起一个节点当 KV,一旦这台挂了状态全没,等于把系统的"一致性生命线"退化成"一台没了就全没",除非明确接受这是开发环境,否则别省这份冗余。二是"把它当缓存/当消息队列":etcd 是强一致存储,写入成本显著高于 Redis,适合"小但重要的状态",不适合大批量临时数据或高吞吐消息。三是"数据无限膨胀":etcd 默认给一定上限,超发会导致写失败甚至集群不稳,要配合压缩(compact/defrag)与告警治理 key 增长。四是"IO 敏感":etcd 重度依赖 append-only 写入,慢盘会直接拉高三节点写延迟,优先给 SSD。边界要认清:它管"一致的小状态",不替代共享文件系统(那边用 NFS/Gluster/Ceph)、不替代缓存、不替代消息队列。

自托管一旦把"公共状态"交给 etcd 三节点,很多上层问题(选主、配置一致性、服务发现)就从"天天扯皮"变成"有明确答案";代价是你要照顾好它的磁盘、网络与节点数。这层"一致性底座"配好了,往上的 K8s 乃至各类高可用方案才站得稳。


手机扫码阅读

微信或手机浏览器扫一扫,随时随地随心阅读与分享

自建权威与递归 DNS 实战:Bind9 让域名解析从玄学变配置

Proxmox VE 虚拟化实战:KVM/LXC、快照备份与整机迁移

评 论
更换验证码