欢迎光临散文网 会员登陆 & 注册

client-go详细介绍

2023-07-26 16:25 作者:风格星辰  | 我要投稿

GVR/GVK
kubernetes API时通过HTTP协议RESTful的形式提供的,同时支持JSON和Protobuf的数据格式,Protobuf是方便集群内部调用而支持的,我们一般使用JSON格式
在kubernetes API中,一般使用GVR或GVK来区分特定的资源。根据不同的分组、版本以及资源进行URL的定义。
同时,因为历史原因,API分组分为无域名资源组和有域名资源组。
无域名资源组也被称为核心资源组 Core Group
有域名资源组
/apis/apps/v1/deployments
无域名资源组
/apis/v1/pods

GVR/GVK含义介绍
G Goup 资源组,包含一组资源操作的集合
V Version 资源版本,用于区分不同API的稳定程度及兼容性
R Resource 资源信息,用于区分不同的资源API
K Kind 资源对象类型,每个资源对象都需要Kind来区分它自身代表的资源类型
接口调用的时候,只需要知道GVR即可
GVK相反,通过GVK信息可以获取要读取的资源的GVR,进而构造REST api。
这种GVK和GVR的映射叫做REST mapper。主要作用在ListWatcher时,根据Schema定义的类型GVK解析出GVR,向APIServer发起HTTP请求获取资源,然后Watch。

Client-go简介
负责与APIServer服务进行交互的客户端库。可以对各类资源对象进行管理操作,包括内置对象和CRD。

开发流程
1、通过配置创建config对象
2、通过config对象创建对应的客户端对象
3、通过客户端对象创建informer,并添加对应的GVR
4、添加监听事件处理函数
5、启动informer

Client-go客户端对象
Client-go提供了4种类型的客户端对象,分别是RESTClient、DiscoveryClient、ClientSet、DynamicClient。
1、RESTClient:最基础的客户端,主要是对HTTP请求进行了封装,支持json和protobuf格式的数据
2、DiscoveryClient:发现客户端,负责发现APIServer支持的资源组、资源版本和资源信息
3、ClientSet:负责操作Kubernetes内置的资源对象,如Pod、Service
4、DynamicClient:动态客户端,可以对任意的Kubernetes资源进行通用操作,包括CRD
它和ClientSet主要区别是,ClientSet是严格结构化定义的,更加安全,DynamicClient是宽松的非结构化的,更加灵活。其返回的对象是map[string]interface{}

RESTClient
RESTClient是其他三个类型的客户端的父类,是最基础的客户端
提供了对RESTful对应方法的封装,通过这些方法与APIServer进行交互,可以操作Kubernetes内置的所有类型以及CRD
使用起来比较复杂,需要配置的参数过于繁琐。需要进一步封装

RESTClient请求过程
GET定义请求方式,返回了一个Request结构体对象,用来构建APIServer请求用的
依次执行了Namespace、Resource、VersionParams构建参数
Do方法通过Request发起请求,通过Response解析请求返回数据
request先检查是否有可用的client,没有使用默认的,然后调用net/http包的功能

ClientSet
一组资源对象客户端的集合,对内置对象进行操作

ClientSet请求过程
CoreV1返回Core V1Client实例对象
Pods调用了newPods函数,返回PodInterface对象,实现了对pod对象相关所有方法。
并将RESTClient赋值给Client对象
List使用RESTClient与Apiserver交互

DynamicClient
动态客户端,通过动态指定资源组、资源版本和资源等信息,来操作任意的K8s资源对象的客户端。不仅可以操作内置对象,也可以操作CRD
ClientSet种版本与类型紧密耦合,DynamicClient使用嵌套map[string]interface{}结构存储Apiserver返回值,使用反射机制,运行时,进行数据绑定。这种方式更灵活,但是无法获取强数据类型的检查和验证。

DynamicClient请求过程
Resource返回基于gvr生成一个对应资源的资源对象客户端
Namespace,指定一个可操作的命名空间
List通过RESTClient调用k8s Apiserver接口返回数据,格式是二进制,然后转换为对应的未结构对象。

DiscoveryClient
前面的对象都是针对资源对象管理的,DiscoveryClient针对GVR的。用于查看当前集群支持的资源钻,资源版本、资源信息。

DiscoveryClient请求过程
ServerGroupResources
ServerGroups负责获取gv数据,然后通过调用fetchGroupVersionResources,
接着调用ServerResourceForGroupVersion方法获取GV对应的Resource数据即资源数据。
同时返回一个map[gv]resourceList数据格式,最后做数据转换

将GVR缓存到本地
kubernetes本地缓存地址.kube/cache/discovery/master_ip_port/
NewCachedDiscoveryClientForConfig创建一个客户端
ServerGroupsAndResource获取数据并缓存。从缓存文件中找,有直接返回,没有调用APIServer获取GVR数据,将获取到的数据缓存到本地,返回给客户端

Informer

架构图


informer负责与Kubernetes APIServer进行Watch操作。资源可以是内置对象也可以是CRD
informer是一个带有本地缓存以及索引机制的核心工具包,当请求为查询操作时,优先从本地缓存中查找数据,而创建、更新、删除这类操作,根据事件通知写入到队列DeltaFIFO,同时对应事件处理过后,更新本地缓存,使本地缓存与ETCD数据保持一致。

Informer组件
Reflector:使用List-Watch来保证本地缓存数据的准确性、顺序性和一致性。List对应资源的全量列表数据,Watch负责变化部分的数据。监听对应的事件并将资源对象变化存放到本地队列DeltaFIFO中
DeltaFIFO:增量队列,记录资源变化的过程。Reflector是生产者。
Indexer:用来存储资源对象并自带索引功能的本地存储。Reflector从DeltaFIFO中将消费出来的资源对象存储到Indexer,Indexer数据与etcd保持一致。从而client-go可以本地读取,减少APIServer数据交互压力。

Reflector
List-Watch
List负责调用资源对应的RESTfulAPI接口获取全局数据列表,并同步到本地缓存中。是短链接
Watch负责监听资源的变化,并调相应事件处理函数进行处理,同时更新本地缓存,使本地缓存与etcd数据保持一致。是长链接

定时同步
定时器定时触发同步机制,定时更新缓存数据
Reflector组件对于数据更新同步,都是基于ResourceVersion进行的,数据变化时,会递增更新。保证事件顺序性
ResourceVersion根据需求,进行配置
未设置,从最新版本开始监听
设置为0,从任意版本开始监听,首选可用最新的,但不是必须,可能返回陈旧数据
从指定版本监听

DeltaFIFO
1、FIFO:是一个队列,拥有队列基本方法
2、Delta:是一个资源对象本地缓存,保存存储对象的消费类型,如Added,Updated、Deleted等,包括Type即事件类型,Object资源对象数据

indexer
本身是一个存储,在存储基础上扩展了索引功能
Reflector通过DeltaFIFO系列操作后,更新存储到Indexer中。数据与etcd完全一致
IndexFunc:索引器函数,用于计算资源对象索引值列表,可以自定义
Index:存储数据,查找某个命名空间下pod,就让pod按照命名空间进行索引
Indexers:存储索引器,key为索引器名称,value为IndexFunc
Indices:存储缓存器,key为索引器名称,value为缓存数据
Indexers是存储索引,Indices是存储数据

threadSafeMap并发安全存储
Cache

SharedInformer
一个资源收到多个控制器管理,可以通过SharedInformer来创建一份供多个控制器共享的缓存
SharedInformer是一个接口,包含添加事件,当有资源变化时,会回调通知使用者,启动函数以及获取全量对象是否已经同步到本地存储中。


扩展
Watch事件通知模式
Etcd v2 轮询
Etcd v2 Watch机制采用HTTP/1.x实现,每个Watcher对应一个TCP连接。Client通过HTTP/1.x长连接定时轮询Server,获取最新的数据变化事件。Watcher数量很多时,大量轮询也会导致Server消耗大量的Socket,内存等资源,导致Etcd的扩展性和稳定性变差;

Etcd v3 流式推送
Etcd v3基于HTTP/2的gRPC协议,双向流的Watch API设计,实现了连接多路复用。同时事件通知模式也从client轮询优化为server流式推送

如何实现
消息可靠性
消息实时性
消息顺序性
高性能

1、可靠性
通过list调用获取所有资源数据,watch获取增量数据,两者结合保证可靠性。

2、实时性
list-watch机制下,每当apiserver的资源产生状态变更事件,都会将事件及时的推送给客户端,从而保证消息的实时性

3、顺序性
K8S在每个资源的事件中都带一个resourceVersion的标签,这个标签是递增的数字,所以当客户端并发处理同一个资源的事件时,它就可以对比resourceVersion来保证最终的状态和最新的事件所期望的状态保持一致。

4、高性能
List-watch通过异步通知达到高性能的特点。watch作为异步消息通知机制,复用一条长链接,保证实时性的同时也保证了性能。

异常重试机制
etcd中watcher的channel缓冲区满了之后,会将其标记为slow watcher,然后通过异步机制重试保证事件可靠性。失败则加到队列。成功,根据版本号对比决定将slower watcher转化为unsynced watcher或者synced watcher。
不断遍历unsynced watcher,批量找出某个key的一批watcher监听的最小版本,遍历获取key历史版本转化为事件发送给对应watcher的channel。
推送完成后将unsynced watcher转换为synced watcher
如果客户端的最新版本号小于缓冲区最小版本号,说明部分数据丢失了,需要list重新获取最新的数据,然后再次watch。


client-go详细介绍的评论 (共 条)

分享到微博请遵守国家法律