1. etcd集群
1.1 etcd集群简介
etcd为了提高可用性提供了集群模式,集群模式下会选举leader,并通过leader和raft机制保证集群模式下的一致性问题,同一时刻有且仅有一个leader。关于集群模式,需要关注以下:
- API操作etcd时,不需要关注节点是否是leader,对于需要保证一致性的请求,follower节点会自动转发给leader处理。
- 集群成员的数目一般是奇数,如果有3个成员,表明集群最大允许挂掉1个节点,如果有5个成员,则最大允许挂掉2个节点。当然节点数目不是越大越好,因为一致性机制下节点数目会影响写性能。
1.2 etcd集群搭建
参考手册:https://blog.lecury.cn/2016/06/27/Etcd集群搭建过程/
2. etcd运维
集群模式大大提高了etcd的可用性,但是仍存在异常和挂掉的可能性。为了进一步提高稳定性和可用性,可以从以下方面着手。
2.1 etcd operator
etcd operator概念最早出现在k8s的生态中,目的是借助k8s平台自动创建、管理etcd集群,不仅提供部署能力,还提供故障迁移的能力。
方案的理念是相似的,是将etcd集群交给一个全局控制器来管理,这个控制器可以运行在k8s平台,也可以独立运行,以提高etcd集群的稳定性和可用性。
2.2 容灾和恢复
目前搜集到的方案大致是:
- 定期dump数据,推送到分布式存储中。
- 恢复时,将数据拷到每个节点上然后分别执行restore。
restore的方式
1 | $ ETCDCTL_API=3 etcdctl snapshot restore snapshot.db \ |
然后再启动
1 | $ etcd \ |
整体操作还是挺麻烦的,完善的容灾机制需要快、准,最好提供平台化的支持,最终目标是实现一键回滚到某个时间点。
参考:https://etcd.io/docs/v3.3.12/op-guide/recovery/
2.3 etcd监控和报警
对etcd集群来说,监控和报警是必不可少的,没有机制能够保证100%的可用,我们需要监控和报警及时的发现问题。
etcd内置了很多prometheus metrics,可以通过prometheus+Grafana方便的监控etcd集群。主要监控点包括:
- 成员状态
- 集群吞吐 kps
- snapshot时间
- 错误情况
- 内存相关
- 等等
这里有个etcd监控模板:https://grafana.com/grafana/dashboards/3070
2.4 etcd集群新增节点
如果该节点曾属于集群成员,那么删除etcd data目录,重启即可。可以通过以下方式查看是否是集群成员
1 | ETCDCTL_API=2 etcdctl member list |
如果该节点是一个新的节点,那么启动etcd时,
- 先在集群节点上执行
etcdctl member add new_node --peer-urls=xxx
- 设置环境变量
ETCD_INITIAL_CLUSTER
和ETCD_INITIAL_CLUSTER_STATE
:分别指明了etcd的集群地址和集群状态。 - 启动这个new node
3. 常见问题
3.1 如何选择etcd集群的节点数目?
首先要理解为什么需要增加节点数目?原因大致为:
- 提高etcd集群的可用性:3个节点能最大容忍一个节点不可用,5个节点则可以最大容忍2个节点不可用,节点数增加从概率角度上确实能增大集群的可用性。
- 提高读的吞吐:集群任何一个节点都能提供读的服务,增加节点类似于横向扩展了。
注意节点数并不是越多越好,因为etcd的一致性机制,每次写操作都需要同步到每个节点,节点数越多会降低写操作的吞吐。
在读写均存在的场景下,建议etcd集群有3个节点,如果读远大于写的场景下,可以考虑增加到5个节点。
3.2 etcd内存、snapshot大小异常
大致原因有以下几点:
- etcd的key/value具有版本功能,频繁更新key/value会使得版本增加过快。
- raft log的太多了
- golang gc问题
解决办法有:
- 开启自动compact:启动参数增加
--auto-compaction-retention=168
- 设置存储quota上限: 启动参数增加
--quota-backend-bytes=8589934592
- 限制raft log:调小
--snapshot-count=10000
3.3 etcd节点挂掉时间太长,重启失败咋办?
集群没挂掉的情况下,直接删除data目录,重新加入集群处理。
3.4 mvcc: database space exceeded 报错如何处理?
etcd会保存key的历史版本,如果没有定期compact的话,就会耗尽etcd的存储空间。如果etcd的剩余空间很小的时候,就会报警:mvcc: database space exceeded.
解决办法:
- compact etcd历史
- 清理每个etcd endpoint
- 消除报警
1 | recv=`ETCDCTL_API=3 ./etcdctl --endpoints=http://$addr endpoint status --write-out="json" | egrep -o '"revision":[0-9]*' | egrep -o '[0-9].*'` |