• client-go controller-runtime kubebuilder


    背景

    这半年一直做k8s相关的工作,一直接触client-go controller-runtime kubebuilder,但是很少有文章将这三个的区别说明白,直接用框架是简单,但是出了问题就是黑盒,这不符合我的理念,所以这篇文章从头说起

    sample-controller

    官方的sample-controller,就是最简单controller,这个项目就用了client-go来实现controller
    在这里插入图片描述
    这是一张在网上被玩烂的图,特别的好,分为上下两部分,上面就是client-go的informer机制(informer机制网上一大堆我就不说了,一句话总结所谓的 Informer,就是一个自带缓存和索引机制,可以触发 Handler 的客户端库),下面就是实现controller的思路。我主要说下半部分(6)调度event handler,就是调用AddFunction、UpdateFunction、DeleteFunction,这几个方法做了什么事呢?(7)就是将对象的key放到了workqueue工作队列中(8)就是不断的从工作队列读取key(9)就是根据key从indexer中取对象,然后做处理。所以说如果自己写controller就要去实现下半部分。

    controller-runtime

    在这里插入图片描述
    controller-runtime,我的理解就是方便用户去写custom controller的,让用户的关注点只关心写处理逻辑,也就是reconciler,在看一下之前的那一张图(6)(7)(8)都是固定的套路,只有handle object这一步才是处理逻辑,所以controller干的事就是帮用户处理了(6)(7)(8)。congtroller中引入了几个新的概念:
    Manager:需要管理器来创建和启动控制器(可以有多个控制器与管理器关联),sample-controller中需要自己controller := NewController和controller.Run,现在manager帮你干了,你只需要写run里面的东西

    Reconciler:用户需要关心的地方,也就上图handle object那部分。上图(9)部分

    Cache:之前你的代码需要操作informer,现在不需要了,直接操作cache就可以,前面我也说过Informer就是一个自带缓存和索引机制,可以触发 Handler 的客户端库

    Controller: 一方面向 Informer 注册 eventHandler,另一方面从队列中获取数据。controller 将从队列中获取数据并执行用户自定义的 Reconciler 功能。上图(6)(7)(8)部分

    我把上图用大白话说一下,controller向informer注册event handler(AddFunction、UpdateFunction、DeleteFunction,这些handler就是将对象的key写到工作队列中),cache负责把informer启动起来,让informer list、watch k8s,当有对象发生变化了informer调用之前注册进来的event handler,将对象的key放到work queue工作队列中,controller不断的从work queue工作队列中获取对象的key,然后调用用户自己写的Reconciler程序。Reconciler的逻辑就是拿着key从cache中获取到对象,然后将对象协调成期望的状态。

    在这里插入图片描述
    上面这张图总结了哪部分是client-go,哪部分是controller-runtime,哪部分是需要用户自己写代码的地方,可以看出来只需要关心绿色的部分,其实也就是之前handle object那部分,剩下的controller-runtime都帮你干了,看着图细想一下,首先是manager的client和cache,你写的哪个控制器都是在和k8s的api进行交互,所以一个是和k8s连接的客户端,一个是k8s对象的缓存数据,controller 负责注册event handler,并且从workqueue中读取对象,最后负责调用用户自己写的reconciler。

    kubebuilder

    kubebuilder是对controller的进一层封装,我们用代码说话

    下面是controller-runtime的main

    func main() {
    	mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{})
    	
    	// in a real controller, we'd create a new scheme for this
    	err = api.AddToScheme(mgr.GetScheme())
    	if err != nil {
    		setupLog.Error(err, "unable to add scheme")
    		os.Exit(1)
    	}
    
    	err = ctrl.NewControllerManagedBy(mgr).
    		For(&api.ChaosPod{}).
    		Owns(&corev1.Pod{}).
    		Complete(&reconciler{
    			Client: mgr.GetClient(),
    			scheme: mgr.GetScheme(),
    		})
    		
    	if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
    		setupLog.Error(err, "problem running manager")
    		os.Exit(1)
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    下面是kubebuilder的main

    func main() {
    	mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
    		Scheme:                 scheme,
    	})
    
    	if err = (&controller.abcReconciler{
    		Client: mgr.GetClient(),
    		Scheme: mgr.GetScheme(),
    	}).SetupWithManager(mgr); err != nil {
    		setupLog.Error(err, "unable to create controller", "controller", "abcCluster")
    		os.Exit(1)
    	}
    
    	setupLog.Info("starting manager")
    	if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
    		setupLog.Error(err, "problem running manager")
    		os.Exit(1)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    有没有感觉非常的像,貌似多了一个SetupWithManager,点进去看一下

    func (r *abcReconciler) SetupWithManager(mgr ctrl.Manager) error {
    	return ctrl.NewControllerManagedBy(mgr).
    		For(&infrastructurev1alpha1.Abc{}).
    		Complete(r)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    仔细对比一下,是不是发现就是controller runtime里面的NewControllerManagedBy,我没有再仔细看下去,但是我觉得就是又对controller封装了一下,提供给了开发者更简单的使用方式。

    总结

    具体的可以边用边看,但是思路一定要理清,不然上来就用kubebuilder出了问题真的不知道发生了什么。

  • 相关阅读:
    hbase_学习_HBase环境搭建(单机)
    Windows 10驱动开发入门(五):创建虚拟显示器 Indirect Display驱动开发
    QT应用启动失败排查方法
    MySQL之视图、存储过程
    LeetCode 刷题 -- 139. 单词拆分
    php一维数组合并
    【错误记录】HarmonyOS 运行报错 ( Failure INSTALL_PARSE_FAILED_USESDK_ERROR )
    文心大模型写——网课点播系统(项目需求)
    TodoList案例
    【2023,学点儿新Java-34】基本数据类型变量 运算规则:自动类型提升、强制类型转换 | 为什么标识符的声明规则里要求不能数字开头?(通俗地讲解——让你豁然开朗!)
  • 原文地址:https://blog.csdn.net/yanchendage/article/details/134310876