K8s 中的Book mark解决了什么问题
这就要从kubernetes各个模块的通信机制说起。List-Watch 是kubernetes中server和client通信的最核心的机制, 比如说api-server监听etcd, kubelet监听api-server, scheduler监听api-server等等,其实其他模块监听api-server相当于监听etcd,因为在k8s的设计中,只有api-server能跟etcd通信,其
这就要从kubernetes各个模块的通信机制说起。
List-Watch 是kubernetes中server和client通信的最核心的机制, 比如说api-server监听etcd, kubelet监听api-server, scheduler监听api-server等等,其实其他模块监听api-server相当于监听etcd,因为在k8s的设计中,只有api-server能跟etcd通信,其他模块需要etcd的数据就只好监听api-server了。
但什么是List-Watch呢?
简单来讲就是先list当前时间点为止的全量变化,然后watch增量变化。
实现这个逻辑的模块就是go-client中大名鼎鼎的Reflector。
这一机制很好,减轻了workload,但是有一个场景有问题: 断开重连(watch因为某些原因断开,然后reconnect)
因为有可能在断开期间resource有更新,但是没watch到,这样就丢失了event(断开期间),怎么解决这个问题呢,kubernetes给resource添加了resourceversion,这样当reconnect的时候,client只要发送断开前的resourceversion, server就会把这个resourceversion之后的所有event发给client,这样就避免了丢失event。
但是还有一个问题,etcd保存历史变更时间太短,默认etcd3仅仅保存5分钟的变更。 另外resourceversion是一类资源共用一个自增长的数列,啥意思呢,举例来讲:所有的pod都使用同一个自增数列,而List-Watch机制是带filter的,比如说某一个kubelet就只关心位于自己node上的pod,所以在噶kubelet看来,resourceversion只是增长的,但是并不连续, 比如改kubelet看到的resourceversion是(1,3,8, 23, 44), 没有的resourceversion因为并不在改kubelet所在的node上,所以该kubelet并不关心。
想象一个场景,某kubelet的watch connection断开了,reconnect的时候上传的断开前的resourceversion是5,但是此时api-server保存的历史变更已经是resourceversion = 10了, 并不是说这个reconnct花了超过5分钟,而是resourceversion = 5之后的几个版本改kubelet并不关心,所以没有更新version,一直保持resourceversion=5,一旦reconnect只能拿着5来找server(这段要好好理解), server也没办法啊,只要返回一个错:too old version error,然后client(kubelet)看到这个错只好清空自己之前的积累(cache),重新List,如果累计了太多的历史变更,这得花较长的时间。
OK, 我们看看你bookmark干啥,其实就是server到client的一个通知机制,甭管你关心不关心(filter),一旦发生变更我通知你,但是因为你不关心你,所以我仅仅通知你变更的resourceversion,至于变更是什么内容,不告诉你,这样client就有了最新的resourceversion,这样就大大减少了List的几率,据说List的次数降低到原来的3%,很了不起的成就!
更多推荐
所有评论(0)