本文简要分析etcd社区的几个真实的issue,希望对etcd感兴趣的同学有所收获,这也是社区互助的精神。本文这个系列的第一篇文章,后面不定期可能会有后续的总结分享。
13340
这个issue的原始链接如下:
https://github.com/etcd-io/etcd/issues/13340
这个问题主要是反馈etcd的'/health'这个endpoint的处理逻辑不合理,是VMware的一个engineer反馈的问题。当etcd作为static POD部署到K8S中时,可以添加livenessProbe以及startupProbe,例如下面就是一个livenessProbe定义:
livenessProbe:
failureThreshold: 8
httpGet:
host: 127.0.0.1
path: /health
port: 2381
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 15
这个问题的关键就在于,当etcd cluster有多个member时,etcd在处理/health请求时,是进行了lineariable read,所以这个endpoint实际上检查的cluster的健康状态。关于Linearizablity,请参与零君前一篇文章:
这样就有一个问题,就是本地member其实是健康的,但是有可能其他member还没有启动完成,导致quorum还不达标,或者发生了leader change;这就导致/health返回false,最后kubelet就restart了当前member,造成恶性循环。
为了解决这个问题,零君给etcd提交了一个PR(还在review过程中),为"/health"增加了一个新的参数serializable=true。这样etcd就执行serialiable read,从而只检查本地member的健康状态。具体请参考PR:
https://github.com/etcd-io/etcd/pull/13399
13406
这个issue的原始链接如下:
https://github.com/etcd-io/etcd/issues/13406
这个问题主要是反馈etcd无法正常启动,刚一启动就会panic。好在reporter提供了db文件。经过分析,是db文件损坏了。
etcd的db文件是由boltDB来管理的,所有数据是按照B+tree的方式组织的。一般来说,一个page的大小就是4K。
关于BoltDB的具体分析,请先关注公众号,然后用关键字“bolt"搜索零君的历史文章。
reporter提供的文件大小总共2527232字节,那么这个DB文件中总共应该有617 (2527232/4096) 个page。但是meta page中记录的却是1706个page,显然超出的范围。另外,B+tree的internal page中也有些无效的记录。
零君临时写了一个简单的小程序(如下),修复了这些错误之后,etcd就正常启动了。有可能有一定的数据丢失,不过总比etcd无法启动要好很多了。
https://github.com/ahrtr/etcd-issues/blob/master/13406/main.go
13415
这个issue的原始链接如下:
https://github.com/etcd-io/etcd/issues/13415
这个问题主要是反馈etcd 3.5在enable authentication之后,/health就返回false。
这个问题的确是在3.5中新引入的。但严格来说,这并不是一个问题。在3.4中,当enable auth之后,/health其实并不经过auth。而在3.5中,则需要经过auth。当request context中没有auth info,etcd会从certificate中获取auth info。所以解决办法也简单,就是请求/health时,采用HTTPS而不是HTTP。
这个问题的具体分析见:
https://github.com/ahrtr/etcd-issues/tree/master/13415
13418
这个issue的原始链接如下:
https://github.com/etcd-io/etcd/issues/13418
这个问题主要是一个哥们尝试用编程的方式来启动一个etcd cluster,发现总有问题。程序的执行逻辑大致如下:
start a node A with one peer object define node A
wait until A become leader
send ProposeConfChange to add node B
start node B with 2 peers objects defines node A & B
results -> reject/hint inf loop
如果看过零君之前写的一篇文章《管理etcd cluster成员的几点注意事项》,这个问题自然就引刃而解了。关键就在于启动第二个node的时候,要加入一个现有的cluster,而不是创建一个新cluster。从CLI的角度来说,就是要是设置参数:
--initial-cluster-state existing"
从编程的角度来说,启动第二个节点,要调用raft.RestartNode,而不是raft.StartNode。reporter按照我的建议修改之后,就正常 工作了。详细分析以及具体的代码,请参考:
https://github.com/ahrtr/etcd-issues/tree/master/13418
13418
所有这些issue都总结在了如下的repo中,以后会陆续加入新的issue分析。
https://github.com/ahrtr/etcd-issues
--END--