Kubernetes operator(一)client-go篇【更新中】

云原生学习路线导航页(持续更新中)

  • 本文是 Kubernetes operator学习 系列第一篇,主要对client-go进行学习,从源码阅读角度,学习client-go各个组件的实现原理、如何协同工作等
  • 参考视频:Bilibili 2022年最新k8s编程operator篇,UP主:白丁云原生
  • 本文引用声明
    • 部分内容来自 白丁云原生 所提供 资料:链接: https://pan.baidu.com/s/1BibLAishAFJLeTyYCLnlbA 提取码: en2p
    • 部分来自:https://zhuanlan.zhihu.com/p/573982128
    • 并根据个人理解进行了汇总和修改

1.为什么要学习 client-go

  • 为了适应更多的业务场景,k8s提供了很多的扩展点,用于满足更复杂的需求
  • K8s的扩展点如下:
    在这里插入图片描述
  • ① kubectl
    • 用户通过kubectl与ApiServer进行交互,kubectl提供了插件,可以扩展kubectl的行为,但是这些插件只能影响用户本地的环境
  • ② API Server
    • 处理所有的请求,可以对用户请求进行 身份认证、基于其内容阻止请求、编辑请求内容、处理删除操作等等。
    • 这个扩展点应该说的是:用户可以 自定义 API Server
  • ③ k8s提供的内置资源
    • 我们无法修改,只能通过 annotation、label 控制他们
  • ④ CRD
    • 自定义资源,配合 自定义控制器Custom Controller,扩展k8s的特定业务场景
  • ⑤ scheduler
    • 调度器,决定k8s把Pod放到哪个节点执行。k8s提供了多种方式扩展调度行为
  • ⑥ Controller Manager
    • 实际上也是k8s的一个客户端,通过与API Server交互。k8s的每种资源都有对应的控制器,都属于ControllerManager
    • client-go本质上就是一个与apiserver交互的库,所以Controller Manager也是通过 client-go 库与 API Server交互的
  • ⑦ Custom Controller
    • 自定义控制器,可以控制 内置资源,也可以控制自定义资源CRD
  • ⑧ kubelet
    • 使用CNI:使得k8s可以使用不同技术,连接Pod网络
    • 使用CSI:使得k8s可以支持不同的存储类型
    • 使用CRI:使得k8s可以支持不同的容器运行时
  • ⑨ client-go
    • 一个通用的Golang库,用于和 apiserver 交互
    • 不管是k8s的各个组件,还是我们自己为CRD开发Custom Controller,都需要使用 client-go 与 API Server 进行通信

综上所述,要想学习 Operator,使用 CRD + Custom Controller 扩展kubernetes功能,必须先学习 Client-go 库,学会如何与APIServer进行交互

2.client-go与kubernetes版本对应关系

我们假设前提:kubernetes版本为 v1.x.y

  • kubernetes版本 >= v1.17.0时,client-go 版本使用 v0.x.y
  • kubernetes版本 < v1.17.0时,client-go 版本使用 v1.x.y

3.client-go架构

3.1.client-go 源代码目录介绍

  • github地址:https://github.com/kubernetes/client-go
    在这里插入图片描述
  • discovery:用于发现API Server都是支持哪些API。kubectl apiversions使用了同样的机制
  • dynamic:包含了kubernetes dynamic client的逻辑,可以操作任意的k8s资源API对象,包括内置的、自定义的资源对象
  • informers:包含了所有内置资源的informer,便于操作k8s的资源对象
  • kubernetes:包含了访问Kubernetes API的 所有ClientSet
  • listers:包含了所有内置资源的lister,用于读取缓存中k8s资源对象的信息
  • plugin/pkg/client/auth:包含所有可选的认证插件,用于从外部获取credential(凭证)
  • tools:包含一系列工具,编写控制器时会用到很多里面的工具方法
  • transport:包含了创建连接、认证的逻辑,会被上层的ClientSet使用

3.2.client-go 架构

图片参考来源:https://zhuanlan.zhihu.com/p/573982128
在这里插入图片描述
下面先介绍各组件整体的运转流程,然后对 client-go 和 一个 CRDController 应该包含哪些组件进行详细介绍。

  • 整体流程简介
    • Reflector会持续监听k8s集群中指定资源类型的API,当发现变动和更新时,就会创建一个发生变动的 对象副本,并将其添加到队列DeltaFIFO中
    • Informer监听DeltaFIFO队列,取出对象,做两件事:
      • (1)将对象加入Indexer,Indexer 会将 [对象key, 对象] 存入一个线程安全的Cache中
      • (2)根据对象的 资源类型和操作,找到对应 Controller 预先提供的 Resource Event Handler,调用Handler,将对象的Key加入该 Controller 的 Workqueue
    • Controller 的循环函数 ProcessItem,监听到 Workqueue 有数据了,就会取出一个key,交给处理函数Worker,Worker 会根据 Key,使用 Indexer reference 从 Cache 中 获取 该key对应的 真实对象。然后就可以进行调谐了。
    • 注意点
      • DeltaFIFO 中 存的是 对象副本
      • Cache 中 存的是 [对象key, 对象] 的映射
      • Workqueue 中存的是 对象Key
      • CRDController 中,使用Informer对象,是为了向其中添加一些 Resource Event Handlers
      • CRDController 中,使用Indexer对象,是为了根据对象Key,获取对象实例
  • client-go组件
    • Reflector
      • reflector会一直监听kubernetes中指定资源类型的API,实现监听的函数就是ListAndWatch。这种监听机制既适用于k8s的内建资源,也适用于自定义资源。
      • 当reflector通过监听API发现资源对象实例存在新的 notification 时,它就会使用 listing API 获取这个新的实例对象,并将其放入 watchHandler 函数内的 DeltaFIFO 中;
    • Informer
      • Informer 会从 Delta FIFO 中取出对象。实现这个功能的方法对应源码中的 processLoop;
      • Informer 取出对象后,根据Resource类型,调用对应的 Resource Event Handler 回调函数,该函数实际上由某个具体的 Controller 提供,函数中会获取对象的 key,并将 key 放入到 该Controller 内部的 Workqueue 中,等候处理。
    • Indexer 和 Thread Safe Store
      • Indexer 会提供对象的索引功能,通常是基于对象Key来创建索引。默认索引函数是MetaNamespaceKeyFunc, 它生成的索引键为/格式。
      • Indexer 维护着一个线程安全的 Cache,即 Thread Safe Store。存储的是[对象key, 对象],用对象Key可以进行获取对象实例。
    • Resource Event Handlers reference
      • 这实际上是所有Controller的Resource Event Handlers的引用。
      • 这些 handlers 由具体的Controller提供,就是 Informer 的回调函数。Informer 会根据资源的类型,调用对应Controller的 handler 方法
      • handler 通常都是用于将资源对象的key放入到 该Controller 内部的 Workqueue 中,等候处理。
  • 自定义控制器组件
    • Informer reference
      • Informer reference 是 Informer 实例对象的引用,用于操作和处理自定义资源对象
      • 我们编写自定义控制器时,需要引用自己需要的Informer,向其中加入一系列 Resource Event Handlers
    • Indexer reference
      • Indexer reference 是 Indexer实例对象的引用,用于根据对象Key索引资源对象
      • 我们编写自定义控制器时,应该创建Indexer的引用,将对象Key传给它,就可以获取想要处理的对象
      • NewIndexerInformer函数
        • client-go中的基本控制器提供了 NewIndexerInformer 函数,用于创建Informer和Indexer。
        • 可以直接使用NewIndexerInformer 函数,或者也可以使用工厂方法来创建Informer
    • Resource Event Handlers
      • 由具体的 Controller 给 Client-go 的Informer 提供的回调函数,获取待处理对象的key,并将key放入到Workqueue中。
    • Workqueue
      • 此队列是 具体的Controller 内部创建的队列,用于暂时存储从Resource event handler 中 传递过来的,待处理对象的Key。
      • Resource event handler 函数通常会获取待处理对象的key,并将key放入到这个workqueue中。
    • Process Item
      • 这个函数为循环函数,它不断从 Work queue 中取出对象的key,并使用 Indexer Reference 获取这个key对应的具体资源对象,然后根据资源的变化,做具体的调谐 Reconcile 动作。

3.3.使用client-go编写Controller的步骤

  • 根据2.2中所述,编写一个 自定义Controller,需要实现如下功能。
    • 先从client-go中获取对应资源的 Informer
    • 提供 一系列的 Resource event handlers,并加入对应的Informer,供该informer回调
    • 提供一个 Workqueue 队列,存储待处理的对象的Key
    • 提供一个 循环函数 ProcessItem,不断从 Workqueue 中取出对象的key,交给 处理函数 Worker
      • 提供一个 处理函数 Worker,根据对象Key,使用对应资源的Indexer,获取到该对象的实例,根据对象的属性变化,做真正的调谐过程。

4.client-go的client组件

4.1.Client类型

  • 我们知道,client-go 可以实现与 kubernetes 的通信。如何实现的呢?
  • client-go 主要提供了4种 client 组件:
    • RESTClient:最基础的客户端,提供最基本的封装,可以通过它组装与API Server即时通讯时 的 url
    • Clientset:是一个Client的集合,在Clientset中包含了所有K8S内置资源 的 Client,通过Clientset便可以很方便的操作如Pod、Service这些资源
    • dynamicClient:动态客户端,可以操作任意K8S的资源,包括CRD定义的资源
    • DiscoveryClient:用于发现K8S提供的资源组、资源版本和资源信息,比如:kubectl api-resources
  • 4种client分别对应源码目录:
    在这里插入图片描述

4.2.RESTClient

4.2.1.RESTClient结构体

type RESTClient struct {// base is the root URL for all invocations of the clientbase *url.URL// versionedAPIPath is a path segment connecting the base URL to the resource rootversionedAPIPath string// content describes how a RESTClient encodes and decodes responses.content ClientContentConfig// creates BackoffManager that is passed to requests.createBackoffMgr func() BackoffManager// rateLimiter is shared among all requests created by this client unless specifically// overridden.rateLimiter flowcontrol.RateLimiter// warningHandler is shared among all requests created by this client.// If not set, defaultWarningHandler is used.warningHandler WarningHandler// Set specific behavior of the client.  If not set http.DefaultClient will be used.Client *http.Client
}

4.2.2.RESTClient常用方法

  • RESTClientFor()
    • 位置:rest/config.go 文件
    • 函数签名:func RESTClientFor(config *Config) (*RESTClient, error),直接 rest点 调用
    • 该方法是用于 创建一个 RESTClient 实例
    • 接收一个 rest.Config 类型参数,Config中包含了 限速器、编解码器 等
      • RESTClientFor 方法内部会从 Config 中取出这些配置,设置给RESTClient 实例
      • 这样RESTClient 实例就具有了 限速、编解码 等多种功能
      • 因此,我们创建Config的时候,可以手动设置这些功能,下面的示例中会展示。
  • RESTClient实例的常用方法
    • /rest/client.go 中有一个接口 Interface
      // Interface captures the set of operations for generically interacting with Kubernetes REST apis.
      type Interface interface {GetRateLimiter() flowcontrol.RateLimiterVerb(verb string) *RequestPost() *RequestPut() *RequestPatch(pt types.PatchType) *RequestGet() *RequestDelete() *RequestAPIVersion() schema.GroupVersion
      }
      
    • RESTClient 实现了这个接口,因此具有所有的方法,用于发送各种类型的请求
    • 另外,Interface 每个方法的返回值都是 Request 类型,Request 类型的各种方法,很多的返回值也是 Request,这样就可以实现 链式编程

4.2.3.Request 和 Result 常用方法

  • Request 位于 /rest/request.go
    • func (r *Request) Namespace(namespace string) *Request:设置 当前Resquest 访问的 namespace
    • func (r *Request) Resource(resource string) *Request:设置 当前Resquest 想要访问的资源类型
    • func (r *Request) Name(resourceName string) *Request:设置 当前Resquest 想要访问的资源的名称
    • func (r *Request) Do(ctx context.Context) Result:格式化并执行请求。返回一个 Result 对象,以便于处理响应。
  • Result 也位于 /rest/request.go
    在这里插入图片描述

4.2.4.RESTClient使用示例

  • 需求:获取default命名空间下的所有pod,并打印所有pod的name
    package mainimport ("context"v1 "k8s.io/api/core/v1""k8s.io/client-go/kubernetes/scheme""k8s.io/client-go/rest""k8s.io/client-go/tools/clientcmd"
    )func main() {// 在你机器的homeDir下,放入集群的config文件,用于连接集群(可以直接从集群master的~/.kube/config拷贝过来)config, err := clientcmd.BuildConfigFromFlags("", clientcmd.RecommendedHomeFile)if err != nil {panic(err)}// 设置默认 GroupVersion(我要操作的是pod,不属于任何的group,所以使用了SchemeGroupVersion。你要操作什么,就写什么GroupVersion即可)config.GroupVersion = &v1.SchemeGroupVersion// 设置编解码器(后面的 Into方法 就是使用它完成 反序列化 的)config.NegotiatedSerializer = scheme.Codecs// 设置 API 根的子路径config.APIPath = "/api"// 创建一个 RESTClientrestClient, err := rest.RESTClientFor(config)if err != nil {panic(err)}// 创建一个Pod,用于接收请求结果pods := v1.PodList{}// 链式编程 发送请求,并反序列化结果到pod中err = restClient.Get().Namespace(v1.NamespaceDefault).Resource("pods").Do(context.TODO()).Into(&pods)if err != nil {panic(err)}// 打印pod名称for _, pod := range pods.Items {println(pod.Name)}
    }
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/641459.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pod的亲和性和反亲和性

pod的亲和性和反亲和性 调度策略&#xff1a; 匹配标签 操作符 拓扑域 调度目标 node的亲和性 主机标签 In Notin exists doesexists Gt Lt 不支持 指定主机 pod的亲和性 pod的标签 In Notin exists doesexists 支持 pod和指…

什么是 Web3.0

什么是Web3.0 对于 Web3.0 的解释网上有很多&#xff0c;目前来说 Web3.0 是一个趋势&#xff0c;尚未有明确的定义。我们今天讨论下几个核心的点&#xff0c;就能很好的理解 Web3.0 要解决哪些问题 谁创造数据&#xff0c;这里的数据可以是一篇博客&#xff0c;一段视频&…

Oracle Linux 8.9 安装图解

风险告知 本人及本篇博文不为任何人及任何行为的任何风险承担责任&#xff0c;图解仅供参考&#xff0c;请悉知&#xff01;本次安装图解是在一个全新的演示环境下进行的&#xff0c;演示环境中没有任何有价值的数据&#xff0c;但这并不代表摆在你面前的环境也是如此。生产环境…

在Vue.js中,什么是mixins?它们的作用是什么?

目录 一、Vue.js介绍 二、什么是mixins 三、mixins的应用场景 四、mixins的优势和作用 一、Vue.js介绍 Vue.js是一种流行的JavaScript前端框架,用于构建交互式的Web界面。它被设计为易于理解和集成的框架,使开发者能够快速构建可复用的组件化应用程序。Vue.js采用了MVVM&a…

如何测试python 版本与 torch 、 torchvision 版本是否对应?

python 版本与 torch 、 torchvision 版本的对应关系如下图所示&#xff1a; 打开 anaconda powershell prompt&#xff0c;输入如下命令&#xff1a; >python>>>import torch>>>c torch.ones((3,1)) //创建矩阵>>>c c.cuda(0) …

Keepalived + Nginx双主架构

Keepalived Nginx双主架构 环境准备&#xff1a; keepalived_master1服务器nginx&#xff1a;172.20.26.167 keepalived_master2服务器nginx&#xff1a;172.20.26.198 各服务器关闭selinux、防火墙等服务。 开机安装部署nginx 在172.20.26.167服务器上 yum install ngi…

分布式深度学习中的数据并行和模型并行

&#x1f380;个人主页&#xff1a; https://zhangxiaoshu.blog.csdn.net &#x1f4e2;欢迎大家&#xff1a;关注&#x1f50d;点赞&#x1f44d;评论&#x1f4dd;收藏⭐️&#xff0c;如有错误敬请指正! &#x1f495;未来很长&#xff0c;值得我们全力奔赴更美好的生活&…

LLMs之Vanna:Vanna(利用自然语言查询数据库的SQL工具+底层基于RAG)的简介、安装、使用方法之详细攻略

LLMs之Vanna&#xff1a;Vanna(利用自然语言查询数据库的SQL工具底层基于RAG)的简介、安装、使用方法之详细攻略 目录 Vanna的简介 1、用户界面 2、RAG vs. Fine-Tuning 3、为什么选择Vanna&#xff1f; 4、扩展Vanna Vanna的安装和使用方法 1、安装 2、训练 (1)、使用…

c#中使用UTF-8编码处理多语言文本的有效策略

使用UTF-8编码处理多语言文本的有效策略 在当今的全球化时代&#xff0c;软件开发者常常需要处理包含多种语言的文本。这不仅涉及英文和其他西方语言&#xff0c;还包括中文、日文、韩文等多字节字符系统。在这篇博客中&#xff0c;我将探讨如何有效地使用UTF-8编码来处理混合语…

项目管理认证 | 什么是PMP项目管理?PMP证书有什么用?

01 什么是项目管理&#xff1f; 项目管理&#xff1f;听起来似乎离我们很遥远。其实不然&#xff0c; 学习了项目管理知识后&#xff0c;你会发现&#xff0c;“一切都是项目&#xff0c;一切也将成为项目”。 你可以把港珠澳大桥的建设、开发一款新型手机、开发一个好用的C…

HarmonyOS 发送http网络请求

好 本文 我们来说 http请求 首先 我们要操作网络内容 需要申请权限 项目中找到 main目录下的module.json5 最下面加上 "requestPermissions": [{"name": "ohos.permission.INTERNET"} ]这里 我在本地写了一个get接口 大家可以想办法 弄一个后…

RabbitMQ交换机

目录 交换机类型 直连交换机&#xff1a;Direct exchange 主题交换机&#xff1a;Topic exchange 扇形交换机&#xff1a;Fanout exchange 首部交换机&#xff1a;Headers exchange 死信交换机&#xff1a;Dead Letter Exchange 交换机的属性 代码实战 直连&#…

x-cmd pkg | frp - 内网穿透工具

简介 frp&#xff08;Fast Reverse Proxy&#xff09;是一个专注于内网穿透的高性能反向代理应用&#xff0c;可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。 它采用 C/S 模式&#xff0c;将服务端部署在具有公网 IP 的机器上&#xff0c;客户端部…

使用torch实现RNN

在实验室的项目遇到了困难&#xff0c;弄不明白LSTM的原理。到网上搜索&#xff0c;发现LSTM是RNN的变种&#xff0c;那就从RNN开始学吧。 带隐藏状态的RNN可以用下面两个公式来表示&#xff1a; 可以看出&#xff0c;一个RNN的参数有W_xh&#xff0c;W_hh&#xff0c;b_h&am…

[AutoSar]BSW_OS 06 Autosar OS_Alarms

一、 目录 一、关键词平台说明一、Timer1.1 配置1.2Periodical Interrupt Timer (PIT)和High Resolution Timer (HRT) 二、Alarm 工作机制三、Code3.1创建一个15ms的runnable3.2mapping到basic task3.3生成代码 关键词 嵌入式、C语言、autosar、OS、BSW 平台说明 项目ValueO…

k8s的helm

1、在没有helm之前&#xff0c;部署deployment、service、ingress等等 2、helm的作用&#xff1a;通过打包的方式&#xff0c;deployment、service、ingress这些打包在一块&#xff0c;一键部署服务、类似于yum功能 3、helm&#xff1a;官方提供的一种类似于仓库的功能&#…

时间轮设计

目录 基本概念 函数定义 函数实现与测试 测试1结果如下 测试2结果如下 基本概念 时间轮 是一种 实现延迟功能&#xff08;定时器&#xff09; 的 巧妙算法。如果一个系统存在大量的任务调度&#xff0c;时间轮可以高效的利用线程资源来进行批量化调度。把大批量的调度任务…

React16源码: React中的resetChildExpirationTime的源码实现

resetChildExpirationTime 1 &#xff09;概述 在 completeUnitOfWork 当中&#xff0c;有一步比较重要的一个操作&#xff0c;就是重置 childExpirationTimechildExpirationTime 是非常重要的一个时间节点&#xff0c;它用来记录某一个节点的子树当中&#xff0c;目前优先级最…

C++提高编程——STL:string容器、vector容器

本专栏记录C学习过程包括C基础以及数据结构和算法&#xff0c;其中第一部分计划时间一个月&#xff0c;主要跟着黑马视频教程&#xff0c;学习路线如下&#xff0c;不定时更新&#xff0c;欢迎关注。 当前章节处于&#xff1a; ---------第1阶段-C基础入门 ---------第2阶段实战…

数据结构:堆与堆排序

目录 堆的定义&#xff1a; 堆的实现&#xff1a; 堆的元素插入&#xff1a; 堆元素删除&#xff1a; 堆初始化与销毁&#xff1a; 堆排序&#xff1a; 堆的定义&#xff1a; 堆是一种完全二叉树&#xff0c;完全二叉树定义如下&#xff1a; 一棵深度为k的有n个结点的二…