controller-manager学习三部曲之三:deployment的controller启动分析

欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos

《controller-manager学习三部曲》完整链接

  1. 通过脚本文件寻找程序入口
  2. 源码学习
  3. deployment的controller启动分析

本篇概览

  • 本文是《controller-manager学习三部曲》的终篇,前面咱们从启动到运行已经分析了controller-manager的详细工作,对controller-manager有了详细了解,也知道controller-manager最重要的任务是调用各controller的初始化方法,使它们进入正常的工作状态,也就是下面代码的黄色箭头位置
    在这里插入图片描述

  • 这些初始化方法又是哪来的呢?不得不再次提到前文多次遇到的NewControllerInitializers方法,这里面有所有controller的初始化方法
    在这里插入图片描述

  • 现在问题来了:controller有这么多,它们的初始化到底做了些什么?

  • 篇幅所限,自然不可能把每个controller的初始化方法都看一遍,所以咱们还是挑一个典型的来看看吧,就选deployment的controller,也就是上图黄色箭头指向的那行

register(names.DeploymentController, startDeploymentController)
  • 不过在正式阅读deployment的controller启动代码之前,先巩固一下基础,弄清楚register方法是什么

register方法

  • 所有controller都要通过register方法注册,所以这个register有必要了解一下
// controllers是个map,key就是controller的名称了,value是初始化方法
controllers := map[string]InitFunc{}
// register在此定义
register := func(name string, fn InitFunc) {// 同一个key不能注册多次 if _, found := controllers[name]; found {panic(fmt.Sprintf("controller name %q was registered twice", name))}controllers[name] = fn
}
  • 作为value的InitFunc也非常重要,它对初始化方法的入参和返回值做了定义,保证了一致性
type InitFunc func(ctx context.Context, controllerCtx ControllerContext) (controller controller.Interface, enabled bool, err error)
  • InitFunc会在StartControllers方法中被执行,每个InitFunc执行结束意味着对应controller初始化完成,来看看它的三个返回值
返回值说明
controller创建的controller对象,这是个接口定义,只要求实现Name方法
enabled用于描述创建的controller对象是否可用,如果可用就会做健康检查相关的判断和注册工作
err如果创建过程有错误发生就在此返回,此err一旦不为空就会导致整个controller-manager进程退出
  • 现在准备工作算是完成了,该研究deployment的启动代码了,也就是startDeploymentController方法

且看deployment的controller是如何创建的

  • 如果您看过欣宸之前的《client-go实战》系列,应该对自定义controller的套路非常熟悉,主要是下面这几件事情
  1. 创建队列,并指定处理队列数据的方法
  2. 监听指定类型的资源,待其发生变化的时候将其放入队列,由前面指定的方法来做具体的处理
  • 正因为熟悉了这个套路,才可以提前猜测deployment的controller做的也是这些事情,然后再来验证猜测
  • startDeploymentController方法的源码很简单,先创建对象再调用Run方法启动业务处理逻辑,要注意的是NewDeploymentController的入参,有deployment、replicaset、pod等三种Informer,所以controller会监听这三种资源的变更,然后还有个client在请求api-server时会用到
func startDeploymentController(ctx context.Context, controllerContext ControllerContext) (controller.Interface, bool, error) {// 实例化对象dc, err := deployment.NewDeploymentController(ctx,controllerContext.InformerFactory.Apps().V1().Deployments(),controllerContext.InformerFactory.Apps().V1().ReplicaSets(),controllerContext.InformerFactory.Core().V1().Pods(),controllerContext.ClientBuilder.ClientOrDie("deployment-controller"),)if err != nil {return nil, true, fmt.Errorf("error creating Deployment controller: %v", err)}go dc.Run(ctx, int(controllerContext.ComponentConfig.DeploymentController.ConcurrentDeploymentSyncs))return nil, true, nil
}
  • 打开方法,看看deployment的controller具体是如何创建的
func NewDeploymentController(ctx context.Context, dInformer appsinformers.DeploymentInformer, rsInformer appsinformers.ReplicaSetInformer, podInformer coreinformers.PodInformer, client clientset.Interface) (*DeploymentController, error) {eventBroadcaster := record.NewBroadcaster()logger := klog.FromContext(ctx)// 创建deployment的controller对象,注意queue被用来存入要监听的业务变更,然后有对应的processor来处理(这是套路),client也传进去了,里面请求api-server会用到(主要是资源的写操作)dc := &DeploymentController{client:           client,eventBroadcaster: eventBroadcaster,eventRecorder:    eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "deployment-controller"}),queue:            workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "deployment"),}// rsControl提供PatchReplicaSet方法,可用于ReplicaSet资源的patch操作dc.rsControl = controller.RealRSControl{KubeClient: client,Recorder:   dc.eventRecorder,}// 监听Deployment资源的变化,增删改都绑定了对应的处理方法dInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{AddFunc: func(obj interface{}) {dc.addDeployment(logger, obj)},UpdateFunc: func(oldObj, newObj interface{}) {dc.updateDeployment(logger, oldObj, newObj)},// This will enter the sync loop and no-op, because the deployment has been deleted from the store.DeleteFunc: func(obj interface{}) {dc.deleteDeployment(logger, obj)},})// 监听ReplicaSet资源的变化,增删改都绑定了对应的处理方法rsInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{AddFunc: func(obj interface{}) {dc.addReplicaSet(logger, obj)},UpdateFunc: func(oldObj, newObj interface{}) {dc.updateReplicaSet(logger, oldObj, newObj)},DeleteFunc: func(obj interface{}) {dc.deleteReplicaSet(logger, obj)},})// 监听Pod资源的变化,增删改都绑定了对应的处理方法podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{DeleteFunc: func(obj interface{}) {dc.deletePod(logger, obj)},})// 这是整个controller的核心业务代码,就是收到deployment资源的变化后所做的各种操作dc.syncHandler = dc.syncDeployment// 入参是对象,功能是将对象的key放入队列dc.enqueueDeployment = dc.enqueue// 这一堆lister都会用在各种查询的场景dc.dLister = dInformer.Lister()dc.rsLister = rsInformer.Lister()dc.podLister = podInformer.Lister()// 是否已经同步的标志dc.dListerSynced = dInformer.Informer().HasSynceddc.rsListerSynced = rsInformer.Informer().HasSynceddc.podListerSynced = podInformer.Informer().HasSyncedreturn dc, nil
}
  • 在上面的代码中,果然看到了队列queue,这就是连接生产和消费的关键对象,至于dInformer.Informer().AddEventHandler、rsInformer.Informer().AddEventHandler等方面里面的AddFunc、UpdateFunc等,肯定是监听了deployment、pod的变化,然后将key放入deployment中,为了验证这个猜测,咱们挑一个看看,就看ReplicaSet的AddFunc中的(logger, obj)dc.addReplicaSet,果然,这些资源的变化都会导致相关的资源被放入队列queue
    在这里插入图片描述

  • 至此,咱们对deployment的controller创建算是了解了,接下来要了解controller如何运行,也就是下图黄色箭头所指的方法做了些什么,按照套路,这里面要做的就是让queue的生产和消费正常运转起来
    在这里插入图片描述

  • 方法的代码如下

func (dc *DeploymentController) Run(ctx context.Context, workers int) {defer utilruntime.HandleCrash()// Start events processing pipeline.dc.eventBroadcaster.StartStructuredLogging(0)dc.eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: dc.client.CoreV1().Events("")})defer dc.eventBroadcaster.Shutdown()defer dc.queue.ShutDown()logger := klog.FromContext(ctx)logger.Info("Starting controller", "controller", "deployment")defer logger.Info("Shutting down controller", "controller", "deployment")// 确保本地与api-server的同步已经完成if !cache.WaitForNamedCacheSync("deployment", ctx.Done(), dc.dListerSynced, dc.rsListerSynced, dc.podListerSynced) {return}// 多个协程并行执行,每个一秒钟执行一次dc.worker方法(其实就是消费queue的业务逻辑)for i := 0; i < workers; i++ {go wait.UntilWithContext(ctx, dc.worker, time.Second)}<-ctx.Done()
}
  • 可见是定时执行dc.worker方法,那就看看这个worker是啥吧,如下所示,其实就是processNextWorkItem,这个咱们在《client-go实战》系列中已经写了太多次了,就是消费queue的业务代码,也是整个controller的核心业务代码
func (dc *DeploymentController) worker(ctx context.Context) {for dc.processNextWorkItem(ctx) {}
}// 这是整个deployment的controller的核心业务逻辑,对deployment资源的变化进行响应
func (dc *DeploymentController) processNextWorkItem(ctx context.Context) bool {// 从queue中取出对象的keykey, quit := dc.queue.Get()if quit {return false}defer dc.queue.Done(key)// 对指定key对应的资源进行处理,也就是此deployment的主要工作err := dc.syncHandler(ctx, key.(string))dc.handleErr(ctx, err, key)return true
}
  • 读到这里,不知您是否有一种豁然开朗的感觉:kubernetes规范了queue、生产、消费的模式,并且在自身controller中践行此模式,这就使得开发controller和阅读controller代码都变得更加容易了,甚至在本文章,我也数次尝试在阅读代码前先猜测再验证,结果都和猜测的一致
  • 或许您可能会有疑问:代码都分析到这里了,咋不继续读dc.syncHandler的源码,把这个controller搞明白?
  • 呃…这里必须要打住了,本文的重点的controller-manager的学习,也就是controller是如何创建和启动的,而并非研究controller的具体业务,所以dc.syncHandler就不展开看了,毕竟每个controller都有自己独特的业务处理逻辑
  • 但我相信,现在的您已经可以轻松读懂dc.syncHandler,从而彻底掌握deployment的controller了,毕竟咱们一起经历了太多的套路,对这套逻辑已经熟悉
  • 至此,《controller-manager学习三部曲》就已经完成了,希望这个系列能够帮您梳理和熟悉kubernetes的controller管理和启动逻辑,让您能开发出更加契合原生kubernetes系统的controller

你不孤单,欣宸原创一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 数据库+中间件系列
  6. DevOps系列

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

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

相关文章

深入了解JavaScript混淆工具:jsjiami.v6

JavaScript混淆工具在前端开发中发挥着重要的作用&#xff0c;帮助开发者保护源代码&#xff0c;减少代码被轻易破解的风险。其中&#xff0c;jsjiami.v6 是一款备受开发者关注的混淆工具之一。本文将深入介绍jsjiami.v6的基本原理和使用方法&#xff0c;并通过案例代码演示其效…

普通男孩的新年创作纪念日

前言 首先在新春佳节&#xff0c;小编在这里祝各位大佬。萌新友友们新年好&#xff0c;希望每一个烟火般的你在新的一年里 offer 多多&#xff0c;薪资多多 &#xff0c;龙行龘龘 &#x1f409; &#x1f409; &#x1f409; &#x1f409;&#xff0c;前程朤朤 ❤️ ❤️ ❤…

【C++】内存详解(堆,栈,静态区)

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

【python】网络爬虫与信息提取--Beautiful Soup库

Beautiful Soup网站&#xff1a;https://www.crummy.com/software/BeautifulSoup/ 作用&#xff1a;它能够对HTML.xml格式进行解析&#xff0c;并且提取其中的相关信息。它可以对我们提供的任何格式进行相关的爬取&#xff0c;并且可以进行树形解析。 使用原理&#xff1a;它能…

Linux第47步_安装支持linux的第三方库和mkimage工具

安装支持linux的第三方库和mkimage工具&#xff0c;做好移植前的准备工作。 编译linux内核之前&#xff0c;需要先在 ubuntu上安装“lzop库”和“libssl-dev库”&#xff0c;否则内核编译会失败。 mkimage工具会在zImage镜像文件的前面添加0x40个字节的头部信息,就可以得到uI…

【Pyhton4Delpi】学习笔记(二)安装验证篇

D12环境下安装P4D。 一、下载 Python4Delphi&#xff08;下称P4D&#xff09;: 下载地址&#xff1a;https://github.com/pyscripter/python4delphi 下载或者克隆P4D到指定的目录&#xff0c;例如&#xff1a;MDS_New&#xff0c;目录结构如下&#xff0c;P4D就是克隆下来的…

软件开发的201个原则

ISBN: 978-7-121-41997-3 作者&#xff1a;【美】Alan M. Davis 译者&#xff1a;叶王、马学翔、吴斌、王冰清 审定&#xff1a;章淼 页数&#xff1a;344页 阅读时间&#xff1a;2023-09-24 推荐指数&#xff1a;★★★★★ 这本书可以说是集开发之大成者了&#xff0c; 如果你…

OWASP TOP10

OWASP TOP10 OWASP网址&#xff1a;http://ww.owasp.org.cn A01&#xff1a;失效的访问控制 例如&#xff1a;越权漏洞 案例1&#xff1a; 正常&#xff1a;每个人登录教务系统&#xff0c;只能查询自己的成绩信息 漏洞&#xff1a;张三登录后可以查看自己的成绩 例如&…

智胜未来,新时代IT技术人风口攻略-第一版(弃稿)

文章目录 抛砖引玉 鸿蒙生态小科普焦虑之下 理想要落到实处校园鼎力 鸿蒙发展不可挡培训入场 机构急于吃红利企业布局 鸿蒙应用规划动智胜未来 技术人风口来临 鸿蒙已经成为行业的焦点&#xff0c;未来的发展潜力无限。作为一名程序员兼UP主&#xff0c;我非常荣幸地接受了邀请…

基于JAVA的贫困地区人口信息管理系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 人口信息管理模块2.2 精准扶贫管理模块2.3 特殊群体管理模块2.4 案件信息管理模块2.5 物资补助模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 人口表3.2.2 扶贫表3.2.3 特殊群体表3.2.4 案件表3.2.5 物资补助表 四…

【Java程序设计】【C00251】基于Springboot的医院信息管理系统(有论文)

基于Springboot的医院信息管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的医院信管系统 本系统分为管理员功能模块、系统功能模块以及医生功能模块。 系统功能模块&#xff1a;医院信管系统&#xff0c;…

161基于matlab的快速谱峭度方法

基于matlab的快速谱峭度方法&#xff0c;选择信号峭度最大的频段进行滤波&#xff0c;对滤波好信号进行包络谱分析。输出快速谱峭度及包络谱结果。程序已调通&#xff0c;可直接运行。 161 信号处理 快速谱峭度 包络谱分析 (xiaohongshu.com)

C++初阶之类与对象(中)——六个默认函数详细解析

个人主页&#xff1a;点我进入主页 专栏分类&#xff1a;C语言初阶 C语言进阶 数据结构初阶 Linux C初阶 欢迎大家点赞&#xff0c;评论&#xff0c;收藏。 一起努力&#xff0c;一起奔赴大厂 目录 一.前言 二.构造函数 2.1构造函数的语法和特性 2.1.1语法 2.…

Blender教程(基础)-顶点合并-18

一、常规合并 准备&#xff0c;新建一个圆环8个点、全选顶点采用F填充&#xff0c;采用J链接多个顶点如下图所示图形。 选择其中一个顶点 按字母GG、移动到离另外一个顶点更近。再选中两个顶点&#xff0c;右键弹出合并顶点>到中心 二、重叠合并 回退回去 按字母G…

LocalAI 部署(主要针对 mac m2 启动)

LocalAI 部署 介绍 LocalAI 是免费的开源 OpenAI 替代方案。 LocalAI 充当 REST API 的直接替代品&#xff0c;与本地推理的 OpenAI API 规范兼容。 它无需 GPU&#xff0c;还有多种用途集成&#xff0c;允许您使用消费级硬件在本地或本地运行 LLM、生成图像、音频等等&#…

第二节:轻松玩转书生·浦语大模型趣味Demo

参考教程&#xff1a;https://github.com/InternLM/tutorial/blob/main/helloworld/hello_world.md InternLM-Chat-7B 智能对话 Demo 终端运行 web demo 运行 1.首先启动服务&#xff1a; cd /root/code/InternLM streamlit run web_demo.py --server.address 127.0.0.1 --…

普京警告:美元大衰落

来源&#xff1a;Bitcoin.com 编译/作者&#xff1a;秦晋 美元不仅是全球储备货币&#xff0c;也是美国用来维护全球权力的重要武器。甚至还是衡量比特币市值与价格的重要指标之一。比特币富豪的财富指标某种程度上也是通过美元多少来进行衡量的。 2月9日&#xff0c;俄罗斯总统…

(免费领源码)java+SSM+mysql 大学食堂订餐系统APP 75418-计算机毕业设计项目选题推荐

摘 要 本论文主要论述了如何使用SSM框架开发一个大学食堂订餐系统APP&#xff0c;将严格按照软件开发流程进行各个阶段的工作&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述大学食堂订餐系统APP的当前背景以及系统开发的目的&#xff0c;后续章节将…

一、Docker部署MySQL

Docker部署MySQL 一、安装Docker二、拉取MySQL镜像1.选择拉取版本2.拉取镜像 三、启动MySQL1.确定好挂载目录2.启动3.查看是否启动4.开启远程访问权限 一、安装Docker 安装教程&#xff1a;https://qingsi.blog.csdn.net/article/details/131270071 二、拉取MySQL镜像 1.选择…

双指针练习题复写零

复写零 给你一个长度固定的整数数组 arr &#xff0c;请你将该数组中出现的每个零都复写一遍&#xff0c;并将其余的元素向右平移。 注意&#xff1a;请不要在超过该数组长度的位置写入元素。请对输入的数组 就地 进行上述修改&#xff0c;不要从函数返回任何东西。 示例 1&…