Kubernetes 数据库 Etcd 日常运维及技巧
作者:徐亚松 地址:http://www.xuyasong.com/?p=1983
etcd 是基于 raft算法的分布式键值数据库,生来就为集群化而设计的,由于Raft算法在做决策时需要超半数节点的投票,所以etcd集群一般推荐奇数节点,如3、5或者7个节点构成一个集群。
以上是etcd集群部署的共识,但是还需要注意以下问题:
一、Etcd选主过程
etcd 是高可用的,允许部分机器故障,以标准的3 节点etcd 集群,容忍1台机器宕机,下面以最简单的leader宕机来演示raft 的投票逻辑,以实际的运行日志来验证并理解。更多的场景可以看之前的原理解析
场景:正常运行的三台etcd:100、101、102。当前任期为 7,leader 为 101机器。使101 宕机
宕机前:101 为 leader,3 个 member
宕机后:102 成为新 leader,2 个 member
选举过程:
将 101 机器的 etcd 停止,此时只剩 2 台,但总数为 3。
1、101停止etcd 的运行
2、102(91d63231b87fadda) 收到消息,发现101(8a4bb0af2f19bd46)心跳超时,于是发起了新一轮选举,任期为 7+1=8
91d63231b87fadda [term 7] received MsgTimeoutNow from 8a4bb0af2f19bd46 and starts an election to get leadership.
3、102(91d63231b87fadda)成为新一任的候选人,然后自己投给了自己,获得 1 票;
91d63231b87fadda became candidate at term 8
91d63231b87fadda received MsgVoteResp from 91d63231b87fadda at term 8
4、102(91d63231b87fadda)发送给 挂掉的101 和 另一个100,希望他们也投给自己;
91d63231b87fadda [logterm: 7, index: 4340153] sent MsgVote request to 8a4bb0af2f19bd46 at term 8
91d63231b87fadda [logterm: 7, index: 4340153] sent MsgVote request to 9feab580a25dd270 at term 8
5、102 肯定收不到 101 的回应,因为 101 已经挂掉;
etcd[24203]: lost the TCP streaming connection with peer 8a4bb0af2f19bd46 (stream MsgApp v2 reader)
6、100 (9feab580a25dd270)收到了 102 的拉票消息,因为任期 8 大于当前100机器所处的 7,于是知道是发起了新的一轮选举,因此回应 101,我给你投票。这里任期term是关键,也就是说,100 和 102 谁先感受到 101 宕机,发起投票,谁就是新的 leader,这个也和进程初始的启动时间有关。
9feab580a25dd270 [term: 7] received a MsgVote message with higher term from 91d63231b87fadda [term: 8]
9feab580a25dd270 became follower at term 8
9feab580a25dd270 [logterm: 7, index: 4340153, vote: 0] cast MsgVote for 91d63231b8
9feab580a25dd270 elected leader 91d63231b87fadda at term 8
7、102 获得了 2 票,一票是自己,一票是 100,超过半数,成为新的 leader。任期为 8;
91d63231b87fadda elected leader 91d63231b87fadda at term 8
更换完成。
二、Etcd集群必须是奇数节点吗?
etcd官方推荐3、5、7个节点,虽然raft算法也是半数以上投票才能有 leader,但奇数只是推荐,其实偶数也是可以的。如 2、4、8个节点。分情况说明:
1 个节点:就是单实例,没有集群概念,不做讨论;
2 个节点:是集群,但没人会这么配,这里说点废话:双节点的etcd能启动,启动时也能有主,可以正常提供服务,但是一台挂掉之后,就选不出主了,因为他只能拿到1票,剩下的那台也无法提供服务,也就是双节点无容错能力,不要使用。
2节点正常运行:
1台宕机后:
3 节点:标准的3 节点etcd 集群只能容忍1台机器宕机,挂掉 1 台的逻辑上边已经演示过,如果再挂 1 台,就和 2节点的情形一致了,一直选,一直增加任期,但就是选不出来,服务也就不可用了;
4 节点:最大容忍1 台
5 节点:最大容忍 2 台
6 节点:最大容忍 2 台
你会发现偶数节点虽然多了一台机器,但是容错能力是一样的,也就是说,你可以设置偶数节点,但没增加什么能力,还浪费了一台机器。同时etcd 是通过复制数据给所有节点来达到一致性,因此偶数的多一台机器增加不了性能,反而会拉低写入速度。
三、Etcd集群机器越多越好吗?
etcd 集群是一个 Raft Group,没有 shared。所以它的极限有两部分,一是单机的容量限制,内存和磁盘;二是网络开销,每次 Raft 操作需要所有节点参与,每一次写操作需要集群中大多数节点将日志落盘成功后,Leader 节点才能修改内部状态机,并将结果返回给客户端。因此节点越多性能越低,所以扩展很多 etcd 节点是没有意义的,一般是 3、5、7, 7 个也足够了。
在 k8s 中一般是3*master机器做高可用,也就是 3节点的 etcd。也有人将 etcd独立于 k8s集群之外,来更好地扩展 etcd 集群,或者根据 k8s 的资源来拆分 etcd,如 events 放在单独的 etcd 集群中。不同的副本数视业务规模而定,3,5,7 都可以。
四、Etcd有脑裂问题吗?
集群化的软件总会提到脑裂问题,如ElasticSearch、Zookeeper集群,脑裂就是同一个集群中的不同节点,对于集群的状态有了不一样的理解。
etcd 中有没有脑裂问题?答案是:没有
The majority side becomes the available cluster and the minority side is unavailable; there is no “split-brain” in etcd.
以网络分区导致脑裂为例,一开始有5个节点, Node 5 为 Leader。
由于出现网络故障,124 成为一个分区,35 成为一个分区, Node 5 的 leader 任期还没结束的一段时间内,仍然认为自己是当前leader,但是此时另外一边的分区,因为124无法连接 5,于是选出了新的leader 1,网络分区形成。
35分区是否可用?如果写入了1而读取了 5,是否会读取旧数据(stale read)?
答:35分区属于少数派,被认为是异常节点,无法执行写操作。写入 1 的可以成功,并在网络分区恢复后,35 因为任期旧,会自动成为 follower,异常期间的新数据也会从 1 同步给 35。
而 5 的读请求也会失败,etcd 通过ReadIndex、Lease read保证线性一致读,即节点5在处理读请求时,首先需要与集群多数节点确认自己依然是Leader并查询 commit index,5做不到多数节点确认,因此读失败。
因此 etcd 不存在脑裂问题。线性一致读的内容下面会提到。
五、Etcd是强一致性吗?
是强一致性,读和写都可以保证线性一致,关于一致性的分析可以看 这篇文章
线性一致读
线性一致性读需要在所有节点走一遍确认,查询速度会有所降低,要开启线性一致性读,在不同的 client是有所区别的:
v2 版本:通过 sdk访问时,quorum=true 的时候读取是线性一致的,通过etcdctl访问时,该参数默认为true。
v3 版本:通过 sdk访问时,WithSerializable=true 的时候读取是线性一致的,通过etcdctl访问时consistency=“l”表示线性(默认为 l,非线性为 s)
为了保证线性一致性读,早期的 etcd(_etcd v3.0 _)对所有的读写请求都会走一遍 Raft 协议来满足强一致性。然而通常在现实使用中,读请求占了 etcd 所有请求中的绝大部分,如果每次读请求都要走一遍 raft 协议落盘,etcd 性能将非常差。
因此在 etcd v3.1 版本中优化了读请求(PR#6275),使用的方法满足一个简单的策略:每次读操作时记录此时集群的 commit index,当状态机的 apply index 大于或者等于 commit index 时即可返回数据。由于此时状态机已经把读请求所要读的 commit index 对应的日志进行了 apply 操作,符合线性一致读的要求,便可返回此时读到的结果。
六、Etcd集群部署
简单介绍下 etcd 的安装过程。下载 etcd3.4 的 release 包。
1、生成证书
1.1 ca-config.json
创建用来生成 CA 文件的 JSON 配置文件,这个文件后面会被各种组件使用,包括了证书过期时间的配置,expiry字段:
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"demo": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
}
1.2 ca-csr.json
创建用来生成 CA 证书签名请求(CSR)的 JSON 配置文件:
{
"CN": "demo",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "demo",
"OU": "cloudnative"
}
]
}
1.3 生成基础 ca 证书
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
执行后会生成三个文件:
ca.csr:证书签名请求,一般用于提供给证书颁发机构,自签就不需要了
ca.pem:证书,公共证书
ca-key.pem:CA密钥
1.4 生成 etcd 证书
增加etcd-csr.json文件,ip 需要填写三台 etcd 机器的 ip:
{
"CN": "demo",
"hosts": [
"127.0.0.1",
"ip1","ip2","ip3"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "demo",
"OU": "cloudnative"
}
]
}
这里的hosts字段中指定了授权使用该证书的IP和域名列表,因为现在要生成的证书需要被etcd集群各个节点使用,所以这里指定了各个节点的IP。
生成证书:
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=jpaas etcd-csr.json | cfssljson -bare etcd
创建etcd 的 CA 证书:这里需要4 个文件
etcd-csr.json:etcd的证书配置
ca.pem:基础公钥
ca-key.pem:基础私钥
ca-config.json:配置文件,如过期时间
执行后会生成三个文件:
etcd.csr
etcd.pem
etcd-key.pem
在一台机器上做证书生成,生成后将这三个文件拷贝到其他几台机器。
2、部署集群
etcd 启动配置示例:
./etcd \
--name=etcd-0 \
--client-cert-auth=true \
--cert-file=/etc/etcd/ssl/etcd.pem \
--key-file=/etc/etcd/ssl/etcd-key.pem \
--peer-cert-file=/etc/etcd/ssl/etcd.pem \
--peer-key-file=/etc/etcd/ssl/etcd-key.pem \
--trusted-ca-file=/etc/etcd/ssl/ca.pem \
--peer-trusted-ca-file=/etc/etcd/ssl/ca.pem \
--initial-advertise-peer-urls https://100.0.0.0:2380 \
--listen-peer-urls https://100.0.0.0:2380 \
--listen-client-urls https://100.0.0.0:2379,https://127.0.0.1:2379 \
--advertise-client-urls https://100.0.0.0:2379 \
--initial-cluster-token etcd-cluster \
--initial-cluster etcd-0=https://100.0.0.0:2380,etcd-1=https://100.0.0.1:2380,etcd-2=https://100.0.0.2:2380 \
--initial-cluster-state new \
--quota-backend-bytes=8589934592 \
--auto-compaction-retention=10 \
--enable-pprof=true \
--data-dir=/var/lib/etcd
3、etcdctl命令
因为etcd配置了证书,所以所有的命令都要带上证书访问,如:
ETCDCTL_API=3 ./etcdctl --endpoints=https://0:2379,https://1:2379,https://2:2379 --cacert /etc/etcd/ssl/ca.pem --cert /etc/etcd/ssl/etcd.pem --key /etc/etcd/ssl/etcd-key.pem endpoint status --write-out=table
version: 查看版本
member list: 查看节点
endpoint status: 节点状态,leader 情况
endpoint health: 健康状态与耗时
set app demo: 写入
get app: 获取
update app demo1:更新
rm app: 删除
mkdir demo 创建文件夹
rmdir dir 删除文件夹
backup 备份
watch key 监测 key 变化
get / –prefix –keys-only: 查看所有 key
- END -
QPS、TPS、并发用户数、吞吐量关系
年轻时偷的懒,迟早是要还的。点亮