概述ListWatch 对象的创建GetterListWatchList() & Watch()

概述

源码版本信息

  • Project: kubernetes
  • Branch: master
  • Last commit id: d25d741c
  • Date: 2021-09-26

ListWatcherReflector 的一个主要能力提供者,今天我们具体看下 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 {
3   optionsModifier := func(options *metav1.ListOptions) {
4      options.FieldSelector = fieldSelector.String() // 序列化成字符串
5   }
6   // 调用下面这个 NewFilteredListWatchFromClient() 函数
7   return NewFilteredListWatchFromClient(c, resource, namespace, optionsModifier)
8}

主要逻辑在下面,list 和 watch 能力都是通过 RESTClient 提供:

 1func NewFilteredListWatchFromClient(c Getter, resource string, namespace string, optionsModifier func(options *metav1.ListOptions)) *ListWatch {
2   // list 某个 namespace 下的某个 resource
3   listFunc := func(options metav1.ListOptions) (runtime.Object, error) {
4      optionsModifier(&options)
5      return c.Get(). // RESTClient.Get() -> *request.Request
6         Namespace(namespace).
7         Resource(resource).
8         VersionedParams(&options, metav1.ParameterCodec).
9         Do(context.TODO()).
10         Get()
11   }
12   // watch 某个 namespace 下的某个 resource
13   watchFunc := func(options metav1.ListOptions) (watch.Interface, error) {
14      options.Watch = true
15      optionsModifier(&options)
16      return c.Get().
17         Namespace(namespace).
18         Resource(resource).
19         VersionedParams(&options, metav1.ParameterCodec).
20         Watch(context.TODO())
21   }
22   return &ListWatch{ListFunc: listFunc, WatchFunc: watchFunc}
23}

Getter

上面有一个 Getter 接口,看下定义:

  • client-go/tools/cache/listwatch.go:65
1type Getter interface {
2   Get() *restclient.Request
3}

这里需要一个能够获得 *restclient.Request 的方式

我们实际使用的时候,会用 rest.Interface 接口类型的实例,这是一个相对底层的工具,封装的是 Kubernetes REST apis 相应动作:

  • client-go/rest/client.go:41
 1type Interface interface {
2   GetRateLimiter() flowcontrol.RateLimiter
3   Verb(verb string) *Request
4   Post() *Request
5   Put() *Request
6   Patch(pt types.PatchType) *Request
7   Get() *Request
8   Delete() *Request
9   APIVersion() schema.GroupVersion
10}

对应实现是:

  • client-go/rest/client.go:81
 1type RESTClient struct {
2   base *url.URL
3   versionedAPIPath string
4   content ClientContentConfig
5   createBackoffMgr func() BackoffManager
6   rateLimiter flowcontrol.RateLimiter
7   warningHandler WarningHandler
8   Client *http.Client
9}
10

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) {
2    result = &v1beta1.DaemonSet{}
3  err = c.client.Get(). // 其实就是 RESTClient.Get(),返回的是 *rest.Request 对象
4        Namespace(c.ns).
5        Resource("daemonsets").
6        Name(name).
7        VersionedParams(&options, scheme.ParameterCodec).
8        Do(ctx).
9        Into(result)
10    return
11}

ListWatch

上面 NewFilteredListWatchFromClient() 函数里实现了 ListFuncWatchFunc 属性的初始化,我们接着看下 ListWatch 结构体定义:

  • client-go/tools/cache/listwatch.go:57
1type ListWatch struct {
2   ListFunc  ListFunc
3   WatchFunc WatchFunc
4   // DisableChunking requests no chunking for this list watcher.
5   DisableChunking bool
6}

实现的接口叫做 ListWatcher

1type ListerWatcher interface {
2    Lister
3    Watcher
4}

这里的 Lister 是

1type Lister interface {
2   // List 的返回值应该是一个 list 类型对象,也就是里面有 Items 字段,里面的 ResourceVersion 可以用来 watch
3   List(options metav1.ListOptions) (runtime.Object, error)
4}

这里的 Watcher 是

1type Watcher interface {
2   // 从指定的资源版本开始 watch
3   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的更多相关文章

  1. Kubernetes client-go Informer 源码分析

    概述ControllerController 的初始化Controller 的启动processLoopHandleDeltas()SharedIndexInformersharedIndexerIn ...

  2. Kubernetes client-go DeltaFIFO 源码分析

    概述Queue 接口DeltaFIFO元素增删改 - queueActionLocked()Pop()Replace() 概述 源码版本信息 Project: kubernetes Branch: m ...

  3. Kubernetes client-go workqueue 源码分析

    概述Queue接口和结构体setAdd()Get()Done()DelayingQueue接口和结构体waitForNewDelayingQueuewaitingLoop()AddAfter()Rat ...

  4. Kubernetes client-go 源码分析 - Reflector

    概述入口 - Reflector.Run()核心 - Reflector.ListAndWatch()Reflector.watchHandler()NewReflector()小结 概述 源码版本: ...

  5. Kubernetes Deployment 源码分析(二)

    概述startDeploymentController 入口逻辑DeploymentController 对象DeploymentController 类型定义DeploymentController ...

  6. Eureka 源码分析之 Eureka Client

    文章首发于微信公众号<程序员果果> 地址:https://mp.weixin.qq.com/s/47TUd96NMz67_PCDyvyInQ 简介 Eureka是一种基于REST(Repr ...

  7. SSO单点登录系列1:cas客户端源码分析cas-client-java-2.1.1.jar

    落雨 cas 单点登录 希望能给以后来研究cas的兄弟留下一点思路,也算是研究了两天的成果,外国人的代码写的很晦涩,翻译下来也没有时间继续跟进,所以有错误的还请大家跟帖和我讨论,qq 39426378 ...

  8. client-go客户端自定义开发Kubernetes及源码分析

    介绍 client-go 是一种能够与 Kubernetes 集群通信的客户端,通过它可以对 Kubernetes 集群中各资源类型进行 CRUD 操作,它有三大 client 类,分别为:Clien ...

  9. 【原】Spark中Client源码分析(二)

    继续前一篇的内容.前一篇内容为: Spark中Client源码分析(一)http://www.cnblogs.com/yourarebest/p/5313006.html DriverClient中的 ...

随机推荐

  1. wx:key报错does not look like a valid key name

    把花括号去掉就行了,  现在改版了,  要注意了     wx:key="index"  

  2. vue引入swiper

    https://github.com/surmon-china/vue-awesome-swiper/blob/master/examples/03-pagination.vue https://su ...

  3. 深入理解nodejs的异步IO与事件模块机制

    node为什么要使用异步I/O 异步I/O的技术方案:轮询技术 node的异步I/O nodejs事件环 一.node为什么要使用异步I/O 异步最先诞生于操作系统的底层,在底层系统中,异步通过信号量 ...

  4. collections、time、datetime、random模块

    今日内容概要 1.re模块的其他知识 2.正则起别名与分组机制 3.collections模块 4.time与datetime模块 5.random随机数模块 今日内容详细 re模块的其他知识 imp ...

  5. EMC信号完整性落地实测1---走出玄学

    EMC信号完整性落地实测1---走出玄学 无论我们从51单片机,STM32电路,运放,传感器,ADC采集还是可控硅晶闸管等等电源电路跨入到电子工程师的行业,我们通常会长时间处于低频的电子电路设计调试阶 ...

  6. HCIE笔记-第十节-静态路由

    协议 :标识 前方的目的网络 是通过什么协议形成的 优先级:代表形成路由的协议的优先级数值 [厂商规定] 开销值:代表该路由协议形成此路由时的开销 -- 不同的协议计算开销值的方式有区别(越小越优) ...

  7. Prometheus TSDB存储原理

    Prometheus 包含一个存储在本地磁盘的时间序列数据库,同时也支持与远程存储系统集成,比如grafana cloud 提供的免费云存储API,只需将remote_write接口信息填写在Prom ...

  8. python基础练习题(题目 输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数)

    day10 --------------------------------------------------------------- 实例017:字符串构成 题目 输入一行字符,分别统计出其中英 ...

  9. Python装饰器:套层壳我变得更强了

    Python装饰器:套层壳我变得更强了 Python装饰器:套层壳我变得更强了 关于作用域和闭包可以聊点什么? 什么是作用域 什么是闭包 装饰器:套层壳我变得更强了 参考资料 昨天阅读了<Pyt ...

  10. 项目完成 - 基于Django3.x版本 - 开发部署小结

    前言 最近因为政企部门的工作失误,导致我们的项目差点挂掉,客户意见很大,然后我们只能被动进入007加班状态,忙得嗷嗷叫,直到今天才勉强把项目改完交付,是时候写一个小结. 技术 因为前期需求不明确,数据 ...