K8S的client-go与Informer机制
K8s的client-go和Informer机制介绍
K8S的client-go与Informer机制
一、介绍
client-go是一个包含KubernetesAPI的SDK,它在整个k8s源码中发挥着不可或缺的作用。
二、KubernetesAPIs
2.1 规范
2.1.1 RESTful
REST,即Representational State Transfer的缩写。这个词组可以翻译为"表现层状态转化"。
- 每一个URI代表一种资源;
- 客户端和服务器之间,传递这种资源的某种表现层;
- 客户端通过五个HTTP动词,对服务器端资源进行操作,实现"表现层状态转化"。
提问:注册登录场景的相关API如何用RESTful的方式设计?
2.1.2 GVK®
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin
namespace: default
spec:
replicas: 1
…
- apiVersion ≈ apiGroupVersion = Group/Version
- GVK = Group Version Kind
- GVR = Group Version Resources
提问:Resource和Kind有什么区别?
答:Resource是一个对象,Kind是一个对象的类型名称
提问:一个标准的K8S资源的API长什么样?
2.2 实战调用
2.2.1 跳过鉴权
因为本次分享的API只是个引子,我们就不讲鉴权了。kubectl有个proxy的子命令可以实现在本地搭建一个具备kubectl同等权限的代理。这里我们通过这种方式跳过鉴权。
kubectl proxy --port=6443
2.2.2 几个例子
- 获取当前版本信息
- http://localhost:6443/version
- 获取APIServer支持的所有APIGroup
- http://localhost:6443/apis
- 获取全部命名空间的Deployment列表
- http://localhost:6443/apis/apps/v1/deployments
- 获取命名空间default下的Deployment列表
- http://localhost:6443/apis/apps/v1/namespaces/default/deployments
- 获取命名空间default下的一个Deployment对象
- http://localhost:6443/apis/apps/v1/namespaces/default/deployments/httpbin
- 获取Pod列表
- http://localhost:6443/api/v1/namespaces/default/pods
提问:获取rollout列表的接口是什么样
http://localhost:6443/apis/argoproj.io/v1alpha1/rollouts
- http://localhost:6443/api/v1/namespaces/default/pods
三、client-go源码
3.1 实战调用
clientset
clientset.AppsV1().Deployments(apiv1.NamespaceDefault).Create(context.TODO(), deployment, metav1.CreateOptions{})
dynamic
deploymentRes := schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"}
dynamicClient.Resource(deploymentRes).Namespace(namespace).Create(context.TODO(), deployment, metav1.CreateOptions{})
restclient
c.client.Post().
Namespace(c.ns).
Resource("deployments").
VersionedParams(&opts, scheme.ParameterCodec).
Body(deployment).
Do(ctx).
Into(result)
https://github.com/kubernetes/client-go/tree/master/examples
3.2 Package介绍
client-go源码目录结构
- discovery:用于发现APIs的相关资源
- kubernetes(clientset):基于rest封装的包含所有k8s内置资源的client集合
- informers:基于clientset实现了一个资源缓存池,封装了所有资源的list和get操作
- dynamic:基于rest实现了一个动态的client,支持所有类型的资源进行操作
- dynamic/dynamicinformer:为dynamic实现的informer
- tools/cache:informer的底层实现
- tools/watch:informer的watch实现,使用它可以watch到informer的资源变化
- transport:用作初始化一个http连接,AA也是在这里完成的
3.3 核心Package走读
3.3.1 kubernetes(clientset)
3.3.2 dynamic
3.3.3 transport
3.4 Informer
informer实际上是为controller服务的,所以这里我们先了解下k8s的controller的设计理念。
3.4.1 控制循环
控制论图解
Kubernetes中的控制循环
通常,控制环路如下所示:
- 阅读资源的状态
- 更改群集或群集外部世界中对象的状态
- 通过etcd中的API服务器更新步骤1中的资源状态
- 重复循环;返回步骤1。
提问:在控制循环中要求近乎实时的获取资源状态,如何实现?
边沿触发与电平触发
提问:事件驱动如何保证不丢数据?
这张图里展示了三种策略:
- edge-driven-only,错过了第二状态改变
- edge-triggered,不依赖事件的数据而是自行获取数据
- edge-triggered with resync,在上一个策略的基础上增加resync
3.4.2 ListWatch
list-watch,顾名思义由list和watch组成。list调用资源的list API获取所有资源,watch调用资源的watch API监听资源变更事件。
提问:如何实现watch?
- 方案1:短轮训
- 方案2:长轮训
- 方案3:chunked
普通HTTP响应体
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 25
Mozilla Developer Network ——> body 数据内容,大小为25字节
chunked的HTTP响应体
```bash
HTTP/1.1 206 OK
Content-Type: text/plain
Transfer-Encoding: chunked
7 ——> 第一个chunk块,大小为7字节
Mozilla ——> 第一个chunk块内容
9 ——> 第二个chunk块,大小为9字节
Developer ——> 第二个chunk块内容
7 ——> 第三个chunk块,大小为7字节
Network ——> 第三个chunk块内容
0 ——> 标记性终止块,大小为0字节
普通HTTP请求响应处理
chunked的HTTP请求处理
informer中的chunk
抓包观察watch机制
3.4.3 核心代码走读
Informer组件:
- Controller
- Reflector:通过Kubernetes Watch API监听resource下的所有事件
- Lister:用来被调用List/Get方法
- Processor:记录并触发回调函数
- DeltaFIFO
- LocalStore
四、实现一个简单的Controller
参考文档
https://github.com/kubernetes/client-go
https://qiankunli.github.io/2020/07/20/client_go.html
https://zh.wikipedia.org/wiki/%E6%8E%A7%E5%88%B6%E8%AE%BA
深入理解k8s中的list-watch机制
更多推荐
所有评论(0)