Kubernetes API Concepts
rest api
高效检测变化,resourceVersion机制
watch请求使用http
Transfer-Encoding: chunked
Content-Type: application/json
bookmark事件(应该是防止某个客户端的resourceVersion落后太多,因为resourceVersion是全局唯一递增的)
limit和continue机制,类似于关系型数据库MySQL的offset和limit,对于etcd也可以通过getprefix的limit min_mod_revision等参数实现。
但是continue令牌有5分钟的过期时间,可见apiserver只保持在5分钟内的缓存一致性,并不是直接读取etcd。
get list的resourceVersion语义
watch的resourceVersion语义
从文档推测,list和watch的resourceVersion语义的暗示都是一样的
如果不指定,则从etcd quorum read 的获取最新版本资源
(etcd 读。Linearizability:要么raft读超时,要么返回最新值,WithSerializable非一致性读,可以通过–etcd-quorum-read配置apiserver)。
如果指定为0,则获取apiserver缓存中的最旧的历史版本(多实例apiserver提高可用性)。
如果指定明确,则从指定版本获取,等于或者大于。
apiserver对etcd的这些扩展特性和etcd原生接口和存储实现原则是一致的,都是
缓存昂贵的不常变化的配置数据
(一切皆声明的配置,过期删除),并且k8s各组件均通过Reflector抽象,基于resync和revision机制,实现listwatch接口。以
最好的性能和可选择的CP/AP提供通信服务
。
条条道路通罗马,k3s 用的是 sqlite,但是毕竟缺乏分布式能力,还得用rqlite,
etcd都把raft这些搞好了,关系型数据库也不是必须的,kv存储已经够用,为啥要重新造轮子呢。
这里说的比较实在。
etcd的前世今生:为什么Kubernetes使用etcd?
APIServer和组件(kubelet)通信源码分析
reflector 通过 listwatch 将消息事件同步到数据目的地store,kubelet的store实现是UndeltaStore,controller的store实现是DeltaFIFO,scheduler的store实现是FIFO。
对于apiserver, reflector.listerWatcher 来自于 newCacherListerWatcher,其storage就是数据源,大家都知道apiserver的数据源是etcd,他实现了storage的接口。
对于其他组件,reflector.listerWatcher 来自于 NewListWatchFromClient,其数据源是c.CoreV1().RESTClient(),也就是对应apiserver的rest接口。