etcd 调优
何时更新检测信号间隔和选举超时设置
etcd 中的默认设置应该适用于平均网络延迟较低的本地网络上的安装。但是,当跨多个数据中心或通过高延迟网络使用 etcd 时,可能需要调整检测信号间隔和选举超时设置。
网络并不是延迟的唯一来源。每个请求和响应都可能受到主节点和从属节点上慢速磁盘的影响。这些超时中的每一个都表示从请求到另一台计算机成功响应的总时间。
调整时间参数
底层的分布式共识协议依赖于两个独立的时间参数,以确保节点在停滞或离线时可以交接领导权。第一个参数称为检测信号间隔。这是领导者通知追随者它仍然是领导者的频率。对于最佳做法,应围绕成员之间的往返时间设置该参数。默认情况下,etcd 使用 100ms
心跳间隔。
第二个参数是选举超时。此超时是指跟随者节点在尝试成为领导者之前在未听到心跳的情况下运行多长时间。默认情况下,etcd 使用 1000ms
选举超时。
调整这些值是一种权衡。建议心跳间隔的值约为成员之间平均往返时间 (RTT) 的最大值,通常约为往返时间的 0.5-1.5 倍。如果心跳间隔过低,etcd 会发送不必要的消息,增加 CPU 和网络资源的使用率。另一方面,检测信号间隔过长会导致选举超时时间过长。较高的选举超时需要更长的时间才能检测到领导者故障。测量往返时间 (RTT) 的最简单方法是使用 PING 实用程序。
应根据成员之间的检测信号间隔和平均往返时间设置选举超时。选举超时必须至少是往返时间的 10 倍,这样才能考虑网络中的差异。例如,如果成员之间的往返时间为 10 毫秒,则选举超时应至少为 100 毫秒。
选举超时上限为 50000ms(50s),仅在部署全局分布式 etcd 集群时使用。美国大陆的合理往返时间为 130 毫秒,美国和日本之间的时间约为 350-400 毫秒。如果网络性能不均匀或经常出现数据包延迟/丢失,则可能需要重试几次才能成功发送数据包。因此,5s 是全局往返时间的安全上限。由于选举超时应比广播时间大一个数量级,因此对于全局分布式集群,如果 ~5 秒,则 50 秒成为合理的最大值。
对于一个集群中的所有成员,检测信号间隔和选举超时值应相同。为 etcd 成员设置不同的值可能会破坏集群稳定性。
可以在命令行上覆盖默认值:
shell
# Command line arguments:
$ etcd --heartbeat-interval=100 --election-timeout=500
# Environment variables:
$ ETCD_HEARTBEAT_INTERVAL=100 ETCD_ELECTION_TIMEOUT=500 etcd
这些值以毫秒为单位指定。
Snapshots 快照
etcd 将所有关键更改附加到日志文件中。此日志会永远增长,并且是对密钥所做的每次更改的完整线性历史记录。完整的历史记录适用于使用较少的集群,但使用频繁的集群将携带大量日志。
为了避免有一个巨大的日志,etcd 会定期制作快照。这些快照为 etcd 提供了一种通过保存系统的当前状态和删除旧日志来压缩日志的方法。
Snapshot tuning 快照调优
使用 V2 后端创建快照可能很昂贵,因此只有在对 etcd 进行给定数量的更改后才会创建快照。默认情况下,每 10,000 次更改后将创建快照。如果 etcd 的内存使用率和磁盘使用率过高,请尝试通过在命令行中设置以下内容来降低快照阈值:
sh
# Command line arguments:
$ etcd --snapshot-count=5000
# Environment variables:
$ ETCD_SNAPSHOT_COUNT=5000 etcd
Disk 磁盘
etcd 集群对磁盘延迟非常敏感。由于 etcd 必须将建议持久化到其日志中,因此来自其他进程的磁盘活动可能会导致较长 fsync
的延迟。结果是 etcd 可能会错过心跳,导致请求超时和暂时的领导丢失。当给定高磁盘优先级时,etcd 服务器有时可以与这些进程一起稳定运行。 在 Linux 上,etcd 的磁盘优先级可以配置为 ionice
:
sh
# best effort, highest priority
$ sudo ionice -c2 -n0 -p `pgrep etcd`
Network 网络
如果 etcd leader 服务于大量并发客户端请求,可能会因网络拥塞而延迟处理 follower 对等请求。这表现为以下节点上的发送缓冲区错误消息:
sh
dropped MsgProp to 247ae21ff9436b2d since streamMsg's sending buffer is full
dropped MsgAppResp to 247ae21ff9436b2d since streamMsg's sending buffer is full
这些错误可以通过将 etcd 的对等流量优先于其客户端流量来解决。在 Linux 上,可以使用流量控制机制对对等流量进行优先级排序:
sh
tc qdisc add dev eth0 root handle 1: prio bands 3
tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip sport 2380 0xffff flowid 1:1
tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip dport 2380 0xffff flowid 1:1
tc filter add dev eth0 parent 1: protocol ip prio 2 u32 match ip sport 2379 0xffff flowid 1:1
tc filter add dev eth0 parent 1: protocol ip prio 2 u32 match ip dport 2379 0xffff flowid 1:1
要取消 tc
,请执行:
sh
tc qdisc del dev eth0 root
CPU
由于 etcd 对延迟非常敏感,因此可以通过将 CPU 调控器设置为性能或保守模式来进一步优化 Linux 系统的性能。
在 Linux 上,可以将 CPU 调控器配置为性能模式:
sh
echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
ETCD 常见问题有哪些🤔?如何处理这些问题?
客户端是否必须向 etcd leader 发送请求?
Raft
是基于领导者的;领导者处理所有需要集群共识的客户端请求。但是,客户端不需要知道哪个节点是领导者。任何需要共识的请求都会发送给追随者,并自动转发给领导者。不需要共识的请求(例如,序列化读取)可以由任何集群成员处理。
Configuration 配置
listen-client-urls、advertise-client-urls 或 initial-advertise-peer-urls 有什么区别?
listen-client-urls
与 listen-peer-urls
指定 etcd 服务器绑定到的本地地址以接受传入连接。要侦听所有接口的端口,请指定 0.0.0.0
为侦听 IP 地址。
advertise-client-urls
与 initial-advertise-peer-urls
指定 etcd 客户端或其他 etcd 成员用于联系 etcd 服务器的地址。播发地址必须可从远程计算机访问。不要公布生产设置的地址, localhost
0.0.0.0
因为这些地址无法从远程计算机访问。
为什么不更改 --listen-peer-urls
或 --initial-advertise-peer-urls
更新中 etcdctl member list
公布的对等 URL?
成员播发的对等 URL 来自 --initial-advertise-peer-urls
初始群集启动时。在启动成员后更改侦听对等 URL
或初始通告对等体不会影响导出的通告对等体 URL
,因为更改必须通过仲裁以避免成员资格配置裂脑。用于 etcdctl member update
更新成员的对等 URL
。
部署的系统要求
由于 etcd
将数据写入磁盘,因此其性能很大程度上取决于磁盘性能。因此,强烈建议使用 SSD。要评估磁盘是否足够快,可以进行 etcd
,一种可能性是使用磁盘基准测试工具,例如 fio
。有关如何执行此操作的示例,请阅读相关文档。
为了防止性能下降或无意中使键值存储过载,etcd 默认强制将可配置的存储大小配额设置为 2GB。为避免交换内存或内存不足,计算机应至少具有同样多的 RAM 来覆盖配额。
对于正常环境,建议的最大大小为 8GB,如果配置的值超过该值,etcd 会在启动时发出警告。
在 CoreOS,etcd 集群通常部署在具有双核处理器、2GB RAM 和至少 80GB SSD 的专用 CoreOS Container Linux 机器上。
请注意,性能本质上取决于工作负载;请在生产部署之前进行测试。有关更多建议,请参阅硬件。
为什么集群成员数量为奇数?
etcd 集群需要大多数节点(仲裁)才能就集群状态的更新达成一致。
对于具有 n 个成员的集群,仲裁为 (n/2)+1
。对于任何奇数大小的群集,添加一个节点将始终增加仲裁所需的节点数。
尽管将节点添加到奇数大小的群集看起来更好,因为有更多的计算机,但容错能力更差,因为完全相同数量的节点可能会在不丢失仲裁的情况下失败,但有更多的节点可能会失败。
如果集群处于无法容忍任何故障的状态,则在删除节点之前添加节点是危险的,因为如果新节点无法向集群注册(例如,地址配置错误),仲裁将永久丢失。
集群最大是多少合适?
从理论上讲,没有硬性限制。但是,etcd
集群可能不应超过 7 个节点。
Google Chubby 锁服务,类似于 etcd
,在 Google 中广泛部署多年,建议运行五个节点。
一个 5 成员的 etcd 集群可以容忍两个成员故障,这在大多数情况下就足够了。
尽管较大的群集提供了更好的容错能力,但由于数据必须在更多计算机之间复制,因此写入性能会受到影响。
什么是容错?
只要可以建立成员仲裁,etcd 集群就会运行。
如果由于暂时性网络故障(例如分区)而丢失了仲裁,则一旦网络恢复并恢复仲裁,etcd 就会自动安全地恢复; Raft
强制执行集群一致性。对于断电,etcd
会将 Raft
日志持久化到磁盘; etcd 将日志重放到故障点,并恢复集群参与。
对于永久性硬件故障,可以通过运行时重新配置从群集中删除节点。
建议集群中的成员数量为奇数。奇数大小的集群允许的故障数与偶数大小的集群相同,但节点更少。通过比较偶数和奇数大小的聚类可以看出差异:
Cluster Size 群集大小 | Majority 大多数 | Failure Tolerance 容错 |
---|---|---|
1 | 1 | 0 |
2 | 2 | 0 |
3 | 2 | 1 |
4 | 3 | 1 |
5 | 3 | 2 |
6 | 4 | 2 |
7 | 4 | 3 |
8 | 5 | 3 |
9 | 5 | 4 |
添加成员以使集群大小达到偶数并不会购买额外的容错能力。同样,在网络分区期间,奇数个成员保证始终存在一个多数分区,该分区在分区结束时可以继续运行并成为事实来源。
etcd 是否适用于跨区域或跨数据中心部署?
跨区域部署 etcd 可以提高 etcd 的容错能力,因为成员位于单独的故障域中,代价是跨越数据中心边界导致的共识请求延迟更高。
由于 etcd 依赖于成员仲裁来达成共识,因此跨数据中心的延迟会有些明显,因为至少大多数集群成员必须响应共识请求。此外,群集数据必须在所有对等节点之间复制,因此也会有带宽成本。
延迟时间越长,默认的 etcd
配置可能会导致频繁的选举或心跳超时。
如何备份 etcd 集群?
在删除不正常的成员之前,我应该添加成员吗?
替换 etcd
节点时,务必先删除该成员,然后再添加其替换
etcd
采用基于仲裁模型的分布式共识;(N/2)+1 成员,即多数成员,必须先就提案达成一致意见,然后才能提交提案集。这些建议包括键值更新和成员身份更改。该模型完全避免了裂脑不一致的任何可能性。不利的一面是永久性的法定人数损失是灾难性的。
这适用于成员身份:如果一个 3 成员集群有 1 个被关闭的成员,它仍然可以向前推进,因为仲裁人数为 2 人,并且 2 名成员仍然有效。但是,向 3 成员集群添加新成员会将法定人数增加到 3 人,因为 4 名成员的多数需要 3 票。由于法定人数增加,这个额外的成员在容错方面是无效的;群集距离不可恢复还有一个节点故障。
此外,该新成员存在风险,因为它可能配置错误或无法加入群集。在这种情况下,无法恢复仲裁,因为群集有两个成员关闭,两个成员打开,但需要三票才能更改成员身份以撤消拙劣的成员身份添加。默认情况下,etcd 将拒绝可能以这种方式关闭集群的成员添加尝试。
另一方面,如果首先从集群成员身份中删除已关闭的成员,则成员数将变为 2,仲裁仍为 2。通过添加新成员进行删除后,仲裁人数也将稳定在 2。因此,即使无法启动新节点,仍然可以通过剩余活动成员的仲裁来删除新成员。
为什么 etcd 不接受成员资格更改?
etcd 设置 strict-reconfig-check
,以拒绝会导致仲裁丢失的重新配置请求。放弃仲裁确实有风险(尤其是当群集已经运行不正常时)。尽管在添加新成员时,如果存在仲裁丢失,则禁用仲裁检查可能很完美,但这可能会导致完全成熟的群集不一致。
对于许多应用程序来说,这将使问题变得更糟("磁盘几何损坏"是最可怕的候选者)。
为什么 etcd 会因磁盘延迟峰值而失去领导者?
这是故意的;磁盘延迟是领导者活动的一部分。假设集群 leader 需要一分钟的时间将 raft 日志更新同步到磁盘,但 etcd 集群有一秒的选举超时。即使领导者可以在选举间隔内处理网络消息(例如,发送检测信号),它实际上不可用,因为它无法提交任何新提案;它正在慢速磁盘上等待。如果集群经常因磁盘延迟而失去其领导者,请尝试调整磁盘设置或 etcd 时间参数。
etcd 警告 "request ignored (cluster ID mismatch)" 是什么意思?
每个新的 etcd 集群都会根据初始集群配置和用户提供的唯一 initial-cluster-token
值生成一个新的集群 ID。通过具有唯一的集群 ID,可以保护 etcd 免受可能损坏集群的跨集群相互的影响。
通常,此警告发生在拆除旧集群,然后为新集群重用某些对等地址之后。如果旧集群中的任何 etcd 进程仍在运行,它将尝试联系新集群。新集群将识别集群 ID 不匹配,然后忽略该请求并发出此警告。通常通过确保不同群集之间的对等地址不相交来清除此警告。
"mvcc: database space exceeded"是什么意思,该如何解决?
etcd 中的多版本并发控制数据模型保留了密钥空间的确切历史记录。如果不定期压缩此历史记录(例如,通过设置 --auto-compaction
),etcd 最终会耗尽其存储空间。如果 etcd 的存储空间不足,它会发出空间配额警报,以保护集群免受进一步写入。只要发出警报,etcd 就会响应带有错误 mvcc: database space exceeded
的写入请求。
要从低空间配额警报中恢复,请执行以下操作:
- Compact
- Defragment 对每个 etcd 端点进行碎片整理。
- Disarm 消除警报。
etcd 警告"etcdserver/api/v3rpc: transport: http2Server.HandleStreams failed to read frame: read tcp 127.0.0.1:2379->127.0.0.1:43020: read: connection reset by peer"是什么意思?
当服务器收到客户端流过早关闭的 TCP RST 标志时,这是 gRPC 端警告。
例如,客户端关闭了其连接,而 gRPC 服务器尚未处理 TCP 队列中的所有 HTTP/2 帧。某些数据可能在服务器端丢失,但只要客户端连接已经关闭,就可以了。
只有旧版本的 gRPC 会记录这一点。etcd >=v3.2.13 默认使用 DEBUG 级别记录此内容,我们可以在启动 etcd 的时候启用标志时 --log-level=debug
就可以输出 debug 信息。
Performance 性能
应该如何对 etcd 进行基准测试?
可以使用基准测试工具 benchmark 。我们也可以在这个地址查看 https://etcd.io/docs/v3.5/op-guide/performance/
当前的基准测试结果。
etcd 警告"apply entries took too long"是什么意思?
在大多数 etcd 成员同意提交请求后,每个 etcd 服务器都会将请求应用到其数据存储中,并将结果保存到磁盘上。即使使用速度较慢的机械磁盘或虚拟化网络磁盘(例如 Amazon 的 EBS 或 Google 的 PD),应用请求通常也应少于 50 毫秒。如果平均应用持续时间超过 100 毫秒,etcd 会警告条目应用时间过长。
第一可能是由磁盘速度慢引起的
磁盘可能在 etcd 和其他应用程序之间遇到争用,或者磁盘太慢(例如,共享虚拟化磁盘)。若要排除慢速磁盘导致此警告,请监视backend_commit_duration_seconds(p99 持续时间应小于 25 毫秒)以确认磁盘速度相当快。如果磁盘速度太慢,则为 etcd 分配专用磁盘或使用更快的磁盘通常可以解决问题。
第二个可能的原因是 CPU 资源不够导致的
如果对计算机 CPU 使用率的监控显示使用率过高,则可能没有足够的计算容量用于 etcd。将 etcd 移动到专用机器,增加进程资源隔离 cgroup,或将 etcd 服务器进程重新设置为更高的优先级通常可以解决问题。
访问过多密钥(例如,获取整个密钥空间)的昂贵用户请求也可能导致长时间的应用延迟。但是,每个请求访问少于几百个密钥应始终是高性能的。
如果上述建议均未清除警告,请打开一个问题,其中包含详细的日志记录、监视、指标和可选的工作负载信息。
etcd 警告"failed to send out heartbeat on time" 是什么意思?
etcd 使用基于 leader 的共识协议来实现一致的数据复制和日志执行。集群成员选举一个领导者,所有其他成员都成为追随者。当选的领导人必须定期向其追随者发送心跳,以保持其领导地位。如果在选举间隔内未收到心跳,追随者将推断领导者失败并触发选举。如果领导者没有及时发送心跳,但仍在运行,则选举是虚假的,很可能是由资源不足引起的。为了捕获这些软故障,如果领导者跳过两个心跳间隔,etcd 将警告它未能按时发送心跳。
通常,此问题是由于以下两方面引起的:
由磁盘速度慢引起的
在领导者发送附加了元数据的检测信号之前,它可能需要将元数据保存到磁盘。磁盘可能在 etcd
和其他应用程序之间遇到争用,或者磁盘太慢(例如,共享虚拟化磁盘)。若要排除慢速磁盘导致此警告,请监视 wal_fsync_duration_seconds
(p99 持续时间应小于 10 毫秒)以确认磁盘速度相当快。如果磁盘速度太慢,则为 etcd
分配专用磁盘或使用更快的磁盘通常可以解决问题。为了判断磁盘是否足够快,可以使用 fio 等基准测试工具。
第二个可能原因是 CPU 匮乏
如果对计算机 CPU 使用率的监控显示使用率过高,则可能没有足够的计算容量用于 etcd
。将 etcd
移动到专用机器,使用 cgroups 增加进程资源隔离,或者将 etcd 服务器进程置于更高的优先级通常可以解决问题。
网络速度慢也可能导致此问题
如果 etcd 机器之间的网络指标显示延迟时间长或丢弃率高,则可能没有足够的网络容量用于 etcd。 将 etcd 成员移动到不太拥塞的网络通常可以解决问题。但是,如果 etcd 集群部署在数据中心之间,则成员之间的延迟会很长。对于此类部署,请调整配置以大致匹配计算机之间的往返时间,并将 heartbeat-interval
election-timeout
配置至少为 5 * heartbeat-interval
。有关详细信息,请参阅优化文档。
如果上述建议均未清除警告,请打开一个问题,其中包含详细的日志记录、监视、指标和可选的工作负载信息。
etcd 警告"snapshotting is taking more than x seconds to finish ..."是什么意思,如何解决?
etcd 发送其完整键值存储的快照,以刷新慢速关注者和备份。快照传输时间慢会增加 MTTR;如果集群正在以高吞吐量引入数据,则慢速关注者可能会在完成快照接收之前需要新的快照来实时锁定。
为了捕获缓慢的快照性能,etcd 会在发送快照花费超过 30 秒并超过 1Gbps 连接的预期传输时间时发出警告。