首页 / 资讯中心 / 文章详情

三节点Etcd集群二进制部署全攻略:从证书到排障

三节点Etcd集群二进制部署全攻略:从证书到排障 ★ FEATURED ARTICLE
如果正准备用二进制方式手动搭建 Kubernetes 集群那么 Etcd 这一步基本决定了后面所有组件的命运。写过 kubeadm 的部署脚本、排查过证书报错、也帮人捞过 Etcd 数据我可以说Etcd 集群部署不到位后面 kube-apiserver、kube-scheduler 全都跟着遭殃。这篇就把三节点 Etcd 集群从零到可用的完整过程讲透证书怎么签、配置文件里每一项是什么意思、systemd 怎么拉起集群、验证命令有哪些以及我在这个过程中踩过、帮别人排查过的那些坑。这篇文章适合两种读者一是正在手工搭建 Kubernetes 集群想彻底搞懂每个基础组件来龙去脉的运维或平台工程师二是线上环境用了托管集群、但遇到 Etcd 问题只能干着急想补上这块底层知识的人。读完你不仅能照着步骤把集群搭起来还能知道出问题时该往哪个方向查不会对着日志一脸茫然。1. Etcd 到底是什么角色为什么它值得单独花一篇文章讲1.1 Kubernetes 里几乎一切状态都“住”在 Etcd 中Etcd 本质上是一个分布式键值存储但在 Kubernetes 的体系里它的地位远超“一个存储”这么简单。你可以把整个 Kubernetes 集群看成一台大型状态机而 Etcd 就是这台状态机唯一认可的“记忆体”。具体到数据层面这些东西全部存在 Etcd 里所有资源对象Pod、Deployment、Service、ConfigMap、Secret、Namespace、Node 等。控制器的期望状态和实际状态记录。RBAC 策略、ServiceAccount、Lease 对象。调度器选出来之后要把结果写回去控制器要拿“期望状态”去比对kubelet 要上报节点和 Pod 运行状态。也就是说kube-apiserver 是无状态的吗是但它每次读写都要找 Etcd。Etcd 挂了API 还能不能响应能但读的是缓存写入基本就断了更关键的是Etcd 客户端连接会持续重试导致 apiserver 变慢、超时进而整个控制平面都不稳定。所以 Etcd 的可用性本质上是整个集群的可用性。1.2 三节点为什么被称为黄金配置Etcd 是 Raft 共识算法的典型实现。Raft 要求集群必须有一个 Leader所有写请求由 Leader 处理并且多数派确认后才算提交成功。这个“多数派”就是 Quorum计算公式很简单Quorum N/2 1只取整数部分。N3Quorum2可以容忍 1 个节点故障。N5Quorum3可以容忍 2 个节点故障。N4Quorum3只能容忍 1 个节点故障和 3 节点集群容错能力相同却多了一个节点的成本和同步风险。所以生产环境最常见的是 3 节点起步要求高可用就上 5 节点偶数节点在 Raft 模型里没有收益。这一点在物理机、虚拟机、云主机上部署都一样别为了“看起来更多”就盲目加偶数节点。1.3 二进制部署和 kubeadm 部署的本质差别kubeadm 默认方式下Etcd 以静态 Pod 形式跑在控制平面节点上系统层面你看到的其实是一个容器。它的参数、证书、启动方式都被 kubeadm 封装好了这当然方便但也带来了一个问题你很难彻底理解 Etcd 进程内部的启动流程、配置加载顺序、证书校验逻辑和恢复过程。二进制部署则是另一条路线直接拿到 Etcd 官方二进制包手动指定启动参数。证书自己签目录自己规划systemd 自己写。每个配置项都看得见摸得着出问题能快速定位。在企业离线交付、等保合规、统一配置管理等场景里二进制部署几乎是必经之路因为它能把所有组件从镜像层面解放出来完全受控。代价也不小你必须有足够的排障能力否则 Etcd 集群一节点挂了恢复流程会让人难受。可这恰恰是今天我们做这件事的意义——把底层逻辑先搞通。2. 动手之前证书、主机、目录这四件事必须提前想清楚2.1 主机规划与会话要求Etcd 集群节点之间通信非常频繁Leader 心跳、日志复制都在 2380 端口上客户端请求走 2379 端口。规划主机时我建议每家至少按这个标准项目建议值说明节点数量3 台起5 台更稳奇数节点多数派原则CPU2 核起4 核更好Etcd 是 IO 密集型 网络密集型内存4GB 起8GB 更优数据量越大缓存需求越高磁盘SSD容量 20GB-50GBwal 和 snapshot 的 fsync 很伤机械盘时钟同步必须开启Raft 对时间偏移敏感建议 chrony 或 ntpd网络节点间 1Gbps 以上延迟太高会影响 Leader 选举我把时钟同步单独拿出来强调是因为它太容易被忽略。Etcd 节点之间时间偏差过大时会出现请求被拒绝、日志频繁报错、选举异常。这不是代码问题是环境问题排查起来特别迷惑人。2.2 版本选择与二进制文件获取Etcd 版本的选择不能乱来。Kubernetes 对不同版本的 Etcd 有官方支持矩阵例如较新的 Kubernetes 版本通常要求 Etcd 3.5.x 系列部署前一定要先确认 K8s 版本对应的兼容范围。以当前的稳定形态来说3.5.x 是生产推荐系列。下载时需要注意架构。绝大多数服务器是 linux-amd64如果你的环境是 arm64比如某些国产化服务器或 ARM 云主机就选择对应的 linux-arm64 包。官方 release 页面提供 etcd-v3.5.x-linux-amd64.tar.gz 这类压缩包下载后记得校验 sha256 一致性离线环境无法联网时要提前准备好全部依赖文件。2.3 目录结构统一我在三台机器上习惯采用完全一致的布局这会让后续排障和管理省很多事/etc/etcd/etcd.conf.yml配置文件。/etc/etcd/ssl/全部证书文件包括 CA 和节点证书。/var/lib/etcd/Etcd 数据目录包括 wal、snap、member 文件夹。数据目录最好挂在独立的数据盘上别和系统盘抢 IO。虽然大部分场景下系统盘也能跑但高负载下出现 fsync 延迟会直接影响集群健康。2.4 证书规划这才是二进制部署最容易出错的一步Etcd 集群用 TLS 做三层通信加密客户端访问2379、节点之间访问2380、还有客户端与节点之间的双向认证。证书方案决定了后续所有调用方式。生产环境里我强烈建议用专门的证书工具来签发而不是手写 openssl 命令链。这里我以最常见的 cfssl 为例也顺便提一句 openssl 完全可以替代但配置过程会更繁琐。证书设计思路分两类严格隔离型每个节点发两本证书一本给 peer 通信一本给 client 通信。合并简化型一本证书同时配置 client auth 和 server auth既当 peer 证书又当 client 证书。严格型更安全职责清晰简化型更易维护实际也跑得很稳。考虑到多数项目手工作业时倾向减少文件数量我下面的示例采用每个节点一本独立证书用途同时开启 client 和 server auth。这样做在 Etcd 配置里只需要把同一份证书路径分别填到 client-transport-security 和 peer-transport-security 里即可。证书目录规划ca.pem、ca-key.pem自建 CA 的根证书和私钥。etcd-01.pem、etcd-01-key.pem节点 1 的证书和私钥。etcd-02.pem、etcd-02-key.pem节点 2。etcd-03.pem、etcd-03-key.pem节点 3。签发证书时需要将节点 IP 和主机名写入 SAN 列表。如果漏了节点 IP客户端连接时会报 IP 不在证书的允许列表中这种问题非常隐蔽。用 cfssl 签发单个节点证书的请求文件长这样{ CN: etcd-01, hosts: [ 10.10.10.11, 127.0.0.1, etcd-01 ], key: { algo: rsa, size: 2048 }, names: [ { C: CN, L: Beijing, ST: Beijing } ] }CN 写清楚节点标识hosts 里塞上节点 IP、回环地址和主机名。等三台节点的证书请求文件都准备好一次性交给 CA 签发即可。签发出证书后建议用下面的命令检查证书的关键属性openssl x509 -in etcd-01.pem -text -noout重点看 Extended Key Usage 里是否包含 TLS Web Server Authentication 和 TLS Web Client Authentication再看 Subject Alternative Name 里是否包含了节点 IP。这两个点没问题证书这块才算稳了。3. 三节点 Etcd 集群从解压到 health 的完整实操3.1 解压、分发与基础环境假设你已经下载好了 etcd-v3.5.x-linux-amd64.tar.gz。在任一管理机上解压后先确认二进制文件是哪个tar -xzvf etcd-v3.5.x-linux-amd64.tar.gz cd etcd-v3.5.x-linux-amd64/ ls -l etcd etcdctl etcdutletcd 是服务端etcdctl 是客户端工具etcdutl 是运维工具快照恢复等。把这几个文件都分发到三台节点上建议统一放到 /usr/local/bin/ 目录这样 systemd 里 ExecStart 路径可以保持一致。分发证书也一样把 ca.pem、对应节点的证书、私钥放到每台机器的 /etc/etcd/ssl/ 下。文件权限必须收紧私钥最好改成 600mkdir -p /etc/etcd/ssl cp ca.pem etcd-01.pem etcd-01-key.pem /etc/etcd/ssl/ chmod 600 /etc/etcd/ssl/*-key.pem chmod 644 /etc/etcd/ssl/*.pem同时创建好数据目录mkdir -p /var/lib/etcd这一步看起来琐碎但目录权限、文件路径不一致是二进制部署里最常见的低级错误。建议分配完文件之后三台机器都做一个快速校验ls -l /usr/local/bin/etcd ls -l /etc/etcd/ssl/3.2 配置文件编写每一项都是重点Etcd 支持命令行参数和配置文件两种方式。我推荐用配置文件因为三节点配置有很多公共项管理起来比一长串命令行参数清爽得多。以节点 1 为例name: etcd-01>[Unit] DescriptionEtcd Server Afternetwork.target Afternetwork-online.target Wantsnetwork-online.target [Service] Typenotify ExecStart/usr/local/bin/etcd --config-file/etc/etcd/etcd.conf.yml Restarton-failure RestartSec5 LimitNOFILE65536 [Install] WantedBymulti-user.targetTypenotify很关键。Etcd 启动完成后会通过 sd_notify 向 systemd 发送一个就绪通知systemd 接收到这个通知后才会认为服务已经是活跃状态。如果改成 simple可能出现服务还在启动过程中就被容器平台或监控判定为活着导致健康检查误判。LimitNOFILE调高文件描述符限制避免高并发连接下文件句柄耗尽。Etcd 生产环境经常把文件描述符上限调高到 65536 或更高这属于常规操作。配置完成后先加载并启动systemctl daemon-reload systemctl enable etcd systemctl start etcd如果你这个时候只启动了节点 1另外两个节点还没启动Etcd 会一直尝试等待其他成员上线。这是正常现象不用担心。但有一点要记住三个节点必须用同一个 initial-cluster-token 快速拉起如果间隔时间过长某些节点会因为证书过期、数据状态不一致等问题变得异常。3.4 集群健康检查从 member 到 endpoint三个节点都启动后先看本机进程状态systemctl status etcd然后再用 etcdctl 验证集群。Etcd v3.5 版本开始etcdctl 默认就是 API v3不需要再手动设置 ETCDCTL_API3但为了保险显式声明一下没有坏处export ETCDCTL_API3 export ETCDCTL_CACERT/etc/etcd/ssl/ca.pem export ETCDCTL_CERT/etc/etcd/ssl/etcd-01.pem export ETCDCTL_KEY/etc/etcd/ssl/etcd-01-key.pem export ETCDCTL_ENDPOINTShttps://10.10.10.11:2379,https://10.10.10.12:2379,https://10.10.10.13:2379接着检查成员列表etcdctl member list输出里应当有三条记录每条的 name 和 IP 对应规划好的节点。如果只出现一条或者两条说明部分节点还没成功加入集群去看对应的 etcd 日志。再检查健康状态etcdctl endpoint health --cluster正常输出应该是每个节点都显示 healthy。如果某个节点 unhealthy例如显示 connection refused要么是端口没监听要么是证书问题。最后做一次实际的读写验证etcdctl put /test-key hello-etcd etcdctl get /test-key能够正常写入和读取说明客户端到 Etcd 的完整链路已经是通的。这一步验证完成后顺手清理掉测试键。3.5 与 kube-apiserver 对接前的最后确认Etcd 集群自己的健康验证通过只代表 Etcd 内部正常。后续 kubernetes 部署时kube-apiserver 会作为客户端连接 Etcd它也需要一套客户端证书。如果你在证书阶段没有给 apiserver 单独签发一本 client auth 证书现在就要补上。apiserver 证书的 CN 一般叫 kube-apiserver用途仅包含 client auth 即可。这一步很多部署过程会忽略结果启动 kube-apiserver 时报无法验证 Etcd 服务端证书或客户端证书错误。提前把 apiserver 的证书签好放到控制平面的证书目录里后面会顺手很多。另一个要确认的是防火墙和云平台安全组。2379/2380 端口必须对 kube-apiserver 所在节点、Etcd 集群内部节点开放。有时 Etcd 健康检查正常但 apiserver 就是连不上原因是被安全策略拦截了很无奈。4. 部署现场最常踩的坑现象、原因与排查命令4.1 证书校验失败x509 错误的几种形态这是二进制部署 Etcd 里我见过最多的报错。典型的日志是client: etcd cluster is unavailable or misconfigured error: this client supports only etcd v3.4看起来像版本不支持实际上往往是因为 etcdctl 连接时没有指定证书导致握手失败。另一种经典报错remote error: tls: bad certificate原因基本有三类客户端连接时没带证书而服务端又开启了 client-cert-auth。证书信任链不对比如客户端只带了服务端证书没带 CA。证书 SAN 列表里没有服务端 IP服务端校验地址时不通过。排查手段并不复杂先用 openssl 验证证书链路openssl verify -CAfile /etc/etcd/ssl/ca.pem /etc/etcd/ssl/etcd-01.pem然后确认 etcdctl 有没有加载 CA 和环境变量。踩过几次坑后我养成了一个习惯在所有调用 Etcd 的机器上都把 ETCDCTL_CACERT 环境变量写进 profile避免手误。4.2 节点无法加入集群ID 冲突和 initial-cluster-state 的隐患Etcd 数据目录里保存着集群 ID 和节点自身 ID。如果你用一套预先准备的数据目录加入一个全新的集群或者反过来用旧数据目录加入一个已经存在的新集群都会报出类似下面的错误etcdserver: request timed out rejected request from ... due to mismatched cluster ID这个问题的根源是initial-cluster-state或者数据目录不匹配。最常见场景是第一次部署三个节点时因为某种原因某个节点先进入了 existing 状态之后你把它清掉又想重新加入就会撞上 ID 冲突。解决办法确保所有节点首次启动时都使用initial-cluster-state: new并且数据目录是空的。如果数据目录有残留直接清掉再启动rm -rf /var/lib/etcd/*记住etcd-01、etcd-02、etcd-03 的集群 ID 必须一致否则集群根本无法形成多数派。查询方法是etcdctl endpoint status --cluster -w table输出里会显示每个节点的 DB Size、Leader、Raft Term 和 Raft Index。如果某些节点的 Raft Term 异常高说明这个节点曾经被其他集群污染过。4.3 启动后集群不稳定Raft 日志刷个没完有一种情况是集群能起来但日志里疯狂刷raft: became candidate at term 3 raft: became follower at term 4说明节点之间网络通信不稳定或者 Leader 选举超时。这类问题有几个典型原因节点间时钟偏移过大。2380 端口被防火墙限制导致部分 peer 连接失败。网络延迟过高心跳超时。磁盘 IO 太高fsync 延迟导致 Raft 日志写入变慢。排查时先看 etcd 日志时间戳journalctl -u etcd -f再检查端口连接ss -lntp | grep -E 2379|2380如果能看到三对 2380 连接说明 peer 网络通了。如果连接数不对优先查防火墙和安全组。时钟同步用timedatectl查看各节点的 NTP 同步状态偏差超过 100ms 就该警惕了。4.4 节点重启后无法重新加入集群Etcd 集群正常运行后某个节点因为重启或 crash 掉线等它恢复后应该能自动重新加回集群。但有时候会出现etcdserver: no leader或者报错提示本地节点已经更新到更高任期但无法与其他成员重新建立连接。这种情况通常是因为数据目录中残留了旧的 WAL 文件而其他节点已经推进了更多日志。如果该节点掉线时间不长一般不会出问题如果掉线太久且日志被压缩掉就可能无法追赶。标准的恢复思路是让这个节点以空数据目录重新加入前提是你有完整的集群快照。我在生产上宁可备份到位也不太愿意去手工修 WAL因为 Raft 日志修复的坑很深不如直接恢复快照来得干净。4.5 快速定位故障速查表现象可能原因首选排查命令etcdctl member list 只显示本节点其他节点未启动或 peer 连接失败journalctl -u etcd -fconnection refused端口监听不完整ss -lntpx509: certificate signed by unknown authority客户端 CA 配置错误openssl verifymismatched cluster ID数据目录或 initial-cluster-token 不一致etcdctl endpoint statusrequest timed out网络延迟高或 Leader 不可用ping / etcdctl endpoint healthno leader多数派丢失或磁盘 fsync 慢journalctl / iostat5. 集群建好不是终点备份、监控与性能要点5.1 备份不能等到故障后才想起来Etcd 集群运行期间的常规备份用 etcdctl snapshot save 做在线快照就够了。它能在不停机的情况下捕获当前一致状态适合作为周期性备份方案。备份命令etcdctl snapshot save /backup/etcd-snapshot-$(date %Y%m%d).db备份文件会比较大保留策略一般建议保留最近 7 到 14 天。恢复流程略微复杂因为 snapshot restore 会生成新的集群 ID 和成员 ID不等于直接把旧快照覆盖回去。大致流程三台节点全部停止 etcd 服务。清空每台节点的>etcdctl compaction --physical 10另外压缩并不能立即缩小 DB 文件大小还需要做碎片整理。碎片整理必须是 leader 节点执行并且期间会阻塞写操作建议低峰期操作etcdctl defrag --cluster执行完可以再用 endpoint status 观察 db size 是否下降。正常情况下 DB 大小时长时短是正常的但长期只涨不缩就有问题了。5.3 需要盯住的几个关键指标监控层面我建议至少覆盖这几项etcd_server_has_leader0 代表没有 Leader这是最高优先级的告警。etcd_server_leader_changes_seen_totalLeader 频繁切换不是好事说明节点间网络或者磁盘 IO 有问题。etcd_network_peer_round_trip_time_seconds节点间 RTT超过几百毫秒就该注意。etcd_disk_wal_fsync_duration_secondsWAL fsync 耗时长期偏高说明磁盘性能是瓶颈。配合 Prometheus 和 Grafana 的官方面板这些指标基本能让你第一时间感知 Etcd 的异常。5.4 升级 Etcd 的唯一建议先演练再动生产Etcd 的版本升级必须谨慎。不要跨大版本跳级比如 3.4 直接升 3.6官方不保证这种跳跃安全。合理路径是一步步升级每升完一个小版本都确认集群健康、数据读写正常再继续下一步。升级过程中逐节点滚动的方式是标准做法停一个节点、替换二进制、恢复服务、确认成员 healthy再操作下一个。任何一次 member 掉线时间都不宜过长避免节点被其他成员判定为失联。最后再分享一点个人体会Etcd 集群部署这件事表面上是配置几个文件的体力活实际上考验的是对 Raft 模型和系统资源敏感性的理解。我在真正亲手部署第一套二进制 Etcd 集群时也经历过三节点一直拉不起来、日志全是 tls 错误的阶段。后来一步步拆解发现是证书 SAN 列表漏了节点 IP虽然过程狼狈但那次之后我对“证书链、节点 ID、Quorum”这三样东西的敏感度完全不一样了。如果你也准备在生产环境落地这套方案我的建议是先在测试环境把三节点的完整生命周期走一遍包括正常部署、滚动升级、单节点故障、双节点故障、快照恢复而不是直接拿生产练手。等你经历过几次节点宕机再把它拉回来你会发现当初花在二进制部署上的每一分钟都很值得。
阅读完成 · 觉得有帮助?
咨询建站