Kubernetes client-go 源码分析 - ListWatcher
2021/10/19 17:11:05
本文主要是介绍Kubernetes client-go 源码分析 - ListWatcher,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
概述ListWatch 对象的创建GetterListWatchList() & Watch()
概述
源码版本信息
- Project: kubernetes
- Branch: master
- Last commit id: d25d741c
- Date: 2021-09-26
ListWatcher 是 Reflector 的一个主要能力提供者,今天我们具体看下 ListWatcher 是如何实现 List()
和 Watch()
过程的。这里我们只跟到 RESTClient 到调用层,不深入 RESTClient 本身的实现;后面有机会再单独结合 apiserver、etcd 等整体串在一起讲 k8s 里的 list-watch 机制底层原理。
ListWatch 对象的创建
ListWatcher 对应的新建实例函数如下:
- client-go/tools/cache/listwatch.go:70
1// 这里 Getter 类型的 c 对应一个 RESTClient 2func NewListWatchFromClient(c Getter, resource string, namespace string, fieldSelector fields.Selector) *ListWatch { optionsModifier := func(options *metav1.ListOptions) { options.FieldSelector = fieldSelector.String() // 序列化成字符串 } // 调用下面这个 NewFilteredListWatchFromClient() 函数 return NewFilteredListWatchFromClient(c, resource, namespace, optionsModifier) 8}
主要逻辑在下面,list 和 watch 能力都是通过 RESTClient 提供:
1func NewFilteredListWatchFromClient(c Getter, resource string, namespace string, optionsModifier func(options *metav1.ListOptions)) *ListWatch { // list 某个 namespace 下的某个 resource listFunc := func(options metav1.ListOptions) (runtime.Object, error) { optionsModifier(&options) return c.Get(). // RESTClient.Get() -> *request.Request Namespace(namespace). Resource(resource). VersionedParams(&options, metav1.ParameterCodec). Do(context.TODO()). Get() } // watch 某个 namespace 下的某个 resource watchFunc := func(options metav1.ListOptions) (watch.Interface, error) { options.Watch = true optionsModifier(&options) return c.Get(). Namespace(namespace). Resource(resource). VersionedParams(&options, metav1.ParameterCodec). Watch(context.TODO()) } return &ListWatch{ListFunc: listFunc, WatchFunc: watchFunc} 23}
Getter
上面有一个 Getter 接口,看下定义:
- client-go/tools/cache/listwatch.go:65
1type Getter interface { Get() *restclient.Request 3}
这里需要一个能够获得 *restclient.Request
的方式
我们实际使用的时候,会用 rest.Interface
接口类型的实例,这是一个相对底层的工具,封装的是 Kubernetes REST apis 相应动作:
- client-go/rest/client.go:41
1type Interface interface { GetRateLimiter() flowcontrol.RateLimiter Verb(verb string) *Request Post() *Request Put() *Request Patch(pt types.PatchType) *Request Get() *Request Delete() *Request APIVersion() schema.GroupVersion 10}
对应实现是:
- client-go/rest/client.go:81
1type RESTClient struct { base *url.URL versionedAPIPath string content ClientContentConfig createBackoffMgr func() BackoffManager rateLimiter flowcontrol.RateLimiter warningHandler WarningHandler Client *http.Client 9}
Getter 接口的 Get()
方法返回的是一个 *restclient.Request
类型,Request 的用法我们直接看 ListWatch 的 New 函数里已经看到是怎么玩的了。
至于这里的 RESTClient 和我们代码里常用的 Clientset 的关系,这里先简单举个例子介绍一下:我们在用 clientset 去 Get 一个指定名字的 DaemonSet 的时候,调用过程类似这样:
1r.AppsV1().DaemonSets("default").Get(ctx, "test-ds", getOpt)
这里的 Get 其实就是利用了 RESTClient 提供的能力,方法实现对应如下:
1func (c *daemonSets) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.DaemonSet, err error) { result = &v1beta1.DaemonSet{} err = c.client.Get(). // 其实就是 RESTClient.Get(),返回的是 *rest.Request 对象 Namespace(c.ns). Resource("daemonsets"). Name(name). VersionedParams(&options, scheme.ParameterCodec). Do(ctx). Into(result) return 11}
ListWatch
上面 NewFilteredListWatchFromClient()
函数里实现了 ListFunc 和 WatchFunc 属性的初始化,我们接着看下 ListWatch 结构体定义:
- client-go/tools/cache/listwatch.go:57
1type ListWatch struct { ListFunc ListFunc WatchFunc WatchFunc // DisableChunking requests no chunking for this list watcher. DisableChunking bool 6}
实现的接口叫做 ListWatcher
1type ListerWatcher interface { Lister Watcher 4}
这里的 Lister 是
1type Lister interface { // List 的返回值应该是一个 list 类型对象,也就是里面有 Items 字段,里面的 ResourceVersion 可以用来 watch List(options metav1.ListOptions) (runtime.Object, error) 4}
这里的 Watcher 是
1type Watcher interface { // 从指定的资源版本开始 watch Watch(options metav1.ListOptions) (watch.Interface, error) 4}
List() & Watch()
最后 ListWatch 对象的 List() 和 Watch() 的实现就没有太多新内容了:
- client-go/tools/cache/listwatch.go:103
1func (lw *ListWatch) List(options metav1.ListOptions) (runtime.Object, error) { // ListWatch 在 Reflector 中使用,在 Reflector 中已经有了分页逻辑,所以这里不能再添加分页相关代码 return lw.ListFunc(options)}func (lw *ListWatch) Watch(options metav1.ListOptions) (watch.Interface, error) { return lw.WatchFunc(options)}
(转载请保留本文原始链接 https://www.danielhu.cn)
这篇关于Kubernetes client-go 源码分析 - ListWatcher的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-15在Kubernetes (k8s) 中搭建三台 Nginx 服务器怎么实现?-icode9专业技术文章分享
- 2024-11-05基于Kubernetes的自定义AWS云平台搭建指南
- 2024-11-05基于Kubernetes Gateway API的现代流量管理方案
- 2024-11-05在Kubernetes上部署你的第一个应用:Nginx服务器
- 2024-11-05利用拓扑感知路由控制Kubernetes中的流量
- 2024-11-05Kubernetes中的层次命名空间:更灵活的资源管理方案
- 2024-11-055分钟上手 Kubernetes:精简实用的 Kubectl 命令速查宝典!
- 2024-10-30K8s 容器的定向调度与亲和性
- 2024-10-28云原生周刊:K8s未来三大发展方向 丨2024.10.28
- 2024-10-25亚马逊弹性Kubernetes服务(EKS)实战:轻松搭建Kubernetes平台