当前位置: 首页 > news >正文

Kubernetes sample-controller 例子介绍

sample-controller

sample-controller 是 K8s 官方自定义 CDR 及控制器是实现的例子

通过使用这个自定义 CDR 控制器及阅读它的代码,基本可以了解如何制作一个 CDR 控制器

CDR 运作原理

网上有更好的文章,说明其运作原理:

  • https://www.zhaohuabing.com/post/2023-03-09-how-to-create-a-k8s-controller/
  • https://www.zhaohuabing.com/post/2023-04-04-how-to-create-a-k8s-controller-2/

CDR 定义 yaml 文件格式细节

官方文档: https://kubernetes.io/zh-cn/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/

sample-controller 目录文件说明

fananchong@myubuntu:~/k8s.io/sample-controller$ tree -L 2
.
|-- artifacts
|   `-- examples                            # CRD yaml 文件定义例子
|-- controller.go                           # 控制器实现
|-- hack                                    # k8s.io/code-generator 提供的生成 pkg/generated/ 、 pkg/apis/samplecontroller/v1alpha1/zz_generated.deepcopy.go
|   |-- boilerplate.go.txt
|   |-- custom-boilerplate.go.txt
|   |-- tools.go
|   |-- update-codegen.sh
|   `-- verify-codegen.sh
|-- main.go                                 # main 函数
|-- pkg
|   |-- apis                                # k8s.io/code-generator 根据 types.go 、 doc.go 来生成
|   |-- generated                           # 自动生成
|   `-- signals
`-- vendor                                  # go mod vendor|-- github.com|-- golang.org|-- google.golang.org|-- gopkg.in|-- k8s.io|-- modules.txt`-- sigs.k8s.io

controller.go 关键代码分析

  1. Informer 监听事件
    fooInformer 监听 Foo CDR 事件
    deploymentInformer 监听 Deployment 事件

        // Set up an event handler for when Foo resources changefooInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{AddFunc: controller.enqueueFoo,UpdateFunc: func(old, new interface{}) {controller.enqueueFoo(new)},})// Set up an event handler for when Deployment resources change. This// handler will lookup the owner of the given Deployment, and if it is// owned by a Foo resource then the handler will enqueue that Foo resource for// processing. This way, we don't need to implement custom logic for// handling Deployment resources. More info on this pattern:// https://github.com/kubernetes/community/blob/8cafef897a22026d42f5e5bb3f104febe7e29830/contributors/devel/controllers.mddeploymentInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{AddFunc: controller.handleObject,UpdateFunc: func(old, new interface{}) {newDepl := new.(*appsv1.Deployment)oldDepl := old.(*appsv1.Deployment)if newDepl.ResourceVersion == oldDepl.ResourceVersion {// Periodic resync will send update events for all known Deployments.// Two different versions of the same Deployment will always have different RVs.return}controller.handleObject(new)},DeleteFunc: controller.handleObject,})
    
  2. Foo CDR 事件处理
    压入工作队列

    // enqueueFoo takes a Foo resource and converts it into a namespace/name
    // string which is then put onto the work queue. This method should *not* be
    // passed resources of any type other than Foo.
    func (c *Controller) enqueueFoo(obj interface{}) {var key stringvar err errorif key, err = cache.MetaNamespaceKeyFunc(obj); err != nil {utilruntime.HandleError(err)return}c.workqueue.Add(key)
    }
    
  3. Deployment 事件处理
    判断是属于 Foo 控制器创建的 Deployment ,压入队列

    // handleObject will take any resource implementing metav1.Object and attempt
    // to find the Foo resource that 'owns' it. It does this by looking at the
    // objects metadata.ownerReferences field for an appropriate OwnerReference.
    // It then enqueues that Foo resource to be processed. If the object does not
    // have an appropriate OwnerReference, it will simply be skipped.
    func (c *Controller) handleObject(obj interface{}) {var object metav1.Objectvar ok boollogger := klog.FromContext(context.Background())if object, ok = obj.(metav1.Object); !ok {tombstone, ok := obj.(cache.DeletedFinalStateUnknown)if !ok {utilruntime.HandleError(fmt.Errorf("error decoding object, invalid type"))return}object, ok = tombstone.Obj.(metav1.Object)if !ok {utilruntime.HandleError(fmt.Errorf("error decoding object tombstone, invalid type"))return}logger.V(4).Info("Recovered deleted object", "resourceName", object.GetName())}logger.V(4).Info("Processing object", "object", klog.KObj(object))if ownerRef := metav1.GetControllerOf(object); ownerRef != nil {// If this object is not owned by a Foo, we should not do anything more// with it.if ownerRef.Kind != "Foo" {return}foo, err := c.foosLister.Foos(object.GetNamespace()).Get(ownerRef.Name)if err != nil {logger.V(4).Info("Ignore orphaned object", "object", klog.KObj(object), "foo", ownerRef.Name)return}c.enqueueFoo(foo)return}
    }
    
  4. Controller.Run 处理
    从队列中取出元素
    如果副本预期不一致,做 scale 处理

    // syncHandler compares the actual state with the desired, and attempts to
    // converge the two. It then updates the Status block of the Foo resource
    // with the current status of the resource.
    func (c *Controller) syncHandler(ctx context.Context, key string) error {// Convert the namespace/name string into a distinct namespace and namelogger := klog.LoggerWithValues(klog.FromContext(ctx), "resourceName", key)namespace, name, err := cache.SplitMetaNamespaceKey(key)if err != nil {utilruntime.HandleError(fmt.Errorf("invalid resource key: %s", key))return nil}// Get the Foo resource with this namespace/namefoo, err := c.foosLister.Foos(namespace).Get(name)if err != nil {// The Foo resource may no longer exist, in which case we stop// processing.if errors.IsNotFound(err) {utilruntime.HandleError(fmt.Errorf("foo '%s' in work queue no longer exists", key))return nil}return err}deploymentName := foo.Spec.DeploymentNameif deploymentName == "" {// We choose to absorb the error here as the worker would requeue the// resource otherwise. Instead, the next time the resource is updated// the resource will be queued again.utilruntime.HandleError(fmt.Errorf("%s: deployment name must be specified", key))return nil}// Get the deployment with the name specified in Foo.specdeployment, err := c.deploymentsLister.Deployments(foo.Namespace).Get(deploymentName)// If the resource doesn't exist, we'll create itif errors.IsNotFound(err) {deployment, err = c.kubeclientset.AppsV1().Deployments(foo.Namespace).Create(context.TODO(), newDeployment(foo), metav1.CreateOptions{})}// If an error occurs during Get/Create, we'll requeue the item so we can// attempt processing again later. This could have been caused by a// temporary network failure, or any other transient reason.if err != nil {return err}// If the Deployment is not controlled by this Foo resource, we should log// a warning to the event recorder and return error msg.if !metav1.IsControlledBy(deployment, foo) {msg := fmt.Sprintf(MessageResourceExists, deployment.Name)c.recorder.Event(foo, corev1.EventTypeWarning, ErrResourceExists, msg)return fmt.Errorf("%s", msg)}// If this number of the replicas on the Foo resource is specified, and the// number does not equal the current desired replicas on the Deployment, we// should update the Deployment resource.if foo.Spec.Replicas != nil && *foo.Spec.Replicas != *deployment.Spec.Replicas {logger.V(4).Info("Update deployment resource", "currentReplicas", *foo.Spec.Replicas, "desiredReplicas", *deployment.Spec.Replicas)deployment, err = c.kubeclientset.AppsV1().Deployments(foo.Namespace).Update(context.TODO(), newDeployment(foo), metav1.UpdateOptions{})}// If an error occurs during Update, we'll requeue the item so we can// attempt processing again later. This could have been caused by a// temporary network failure, or any other transient reason.if err != nil {return err}// Finally, we update the status block of the Foo resource to reflect the// current state of the worlderr = c.updateFooStatus(foo, deployment)if err != nil {return err}c.recorder.Event(foo, corev1.EventTypeNormal, SuccessSynced, MessageResourceSynced)return nil
    }
    

相关文章:

Kubernetes sample-controller 例子介绍

sample-controller sample-controller 是 K8s 官方自定义 CDR 及控制器是实现的例子 通过使用这个自定义 CDR 控制器及阅读它的代码,基本可以了解如何制作一个 CDR 控制器 CDR 运作原理 网上有更好的文章,说明其运作原理: https://www.z…...

【C/C++指针】指针*与引用的区别

指针变量的值是所指对象的地址(准确说是首地址,其类型定义其所指对象的字节长度)引用变量的值是所引用对象本身的值 1 初始化 指针变量 可不初始化 且 可以更换指向对象 int *p;//此时是个野指针,该指针变量的值是任意值&#x…...

【ArcGIS Pro微课1000例】0039:制作全球任意经纬网的两种方式

本文讲解在ArcGIS Pro中制作全球任意经纬网的两种方式。 文章目录 一、生成全球经纬网矢量1. 新建地图加载数据2. 创建经纬网矢量数据二、布局生成经纬网1. 新建布局2. 创建地图框2. 创建经纬网一、生成全球经纬网矢量 以1:100万比例尺地图分幅为例,创建经差6、维差4的经纬网…...

【二叉树】练习题终章

二叉树的销毁 void BTreeDestroy(BTNode* root) {if (root NULL)return;BTreeDestroy(root->left);BTreeDestroy(root->right);free(root); }递归展示图 使用后序销毁,如果用前序销毁的话,就会找不到根对应的子树的地址.下面就不能被销毁了&…...

flutter开发实战-实现获取视频的缩略图封面video_thumbnail

flutter开发实战-实现获取视频的缩略图封面video_thumbnail 在很多时候,我们查看视频的时候,视频没有播放时候,会显示一张封面,可能封面没有配置图片,这时候就需要通过获取视频的缩略图来显示封面了。这里使用了video…...

Prompt Toolkit探索:打造交互式CLI应用

简介:prompt_toolkit 是一个 Python 的库,它提供了一系列功能丰富的用户界面元素,比如自动完成、语法高亮、多行编辑、提示等等,让你可以轻松地构建出功能强大的命令行工具。而且,这个库还被 IPython 和 pgcli 这样的知…...

【已解决】AttributeError: module ‘gradio‘ has no attribute ‘outputs‘

问题描述 AttributeError: module gradio has no attribute outputs 不知道作者用的是哪个gradio版本,最新的版本报错AttributeError: module gradio has no attribute outputs , 换一个老一点的版本会报错AttributeError: module gradio has no attribu…...

WPF Mvvm模式下面如何将事件映射到ViewModel层

前言 平常用惯了Command绑定,都快忘记传统的基于事件编程模式了,但是Commond模式里面有个明显的问题,就是你无法获取到事件源的参数。很多大聪明肯定会说,这还不简单,通过自己写控件,给控件加个自定义属性不就行了,想要啥事件就写啥事件进去,完全自主可控。但是对于写…...

C# WPF上位机开发(计算器界面设计)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 c# wpf最大的优势就是开发业务软件比较快、效率比较高。一般来说,它的界面和逻辑部分可以同时开发。界面的部分用xaml编写即可&#xf…...

[c]比较月亮大小

本题的难点就是分情况讨论 #include<stdio.h> int main() {int n;scanf("%d",&n);int arr2[n];int p;for(int m0;m<n-1;m){scanf("%d",&arr2[m]);//输入n个数保存到数组}if(n1)//当输入一个数据时&#xff0c;输入0&#xff0c;可以判断…...

【Java 基础】16 泛型

文章目录 什么是泛型&#xff1f;泛型的声明泛型的使用泛型方法通配符和泛型上下界1&#xff09;通配符2&#xff09;泛型上下界 泛型的好处注意事项 泛型提供了一种在编写代码时更好地 支持类型安全的机制。通过泛型&#xff0c;我们可以编写更加 通用、 灵活、 可读性高的…...

Android framework定制1-->用户无操作一段时间,自动播放客户提供的视频,用户操作后退出播放

在PowerManagerService.java中监听用户操作&#xff0c;10秒无操作则打开预置的apk播放视频&#xff0c;直接上代码&#xff1a; --- a/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.javab/frameworks/base/services/core/java/com/andr…...

Vmware17虚拟机安装windows10系统

不要去什么系统之家之类的下载镜像&#xff0c;会不好安装&#xff0c;镜像被魔改过了&#xff0c;适合真实物理机上的系统在PE里安装系统&#xff0c;建议下载原版系统ISO文件 安装vmware17pro 下载地址https://dwangshuo.jb51.net/202211/tools/VMwareplayer17_855676.rar 解…...

Golang实践录:读取yaml配置文件

本文对 yaml 文件进行解析。 下载 yaml执行 go get github.com/spf13/viper 安装。 golang 有很多库可以解释 yaml 文件。本文选用 viper 进行解析&#xff0c;执行 go get github.com/spf13/viper 安装。 yaml语法规则 yaml对大小写敏感。yaml的层级关系只能使用空格缩进&a…...

oracle sql相关语法

SQL*PLUS 在SQL*PLUS执行&#xff0c;会在执行后显示查询的执行计划和统计信息 SET AUTOTRACE ON;SELECT * FROM your_table WHERE column_name value;SET AUTOTRACE OFF;PLSQL PLSQL查询sql界面&#xff0c;鼠标右键&#xff0c;点击执行计划&#xff0c;会出现sql的执行计…...

el-table,列表合并,根据名称列名称相同的品名将其它列值相同的进行合并

el-table,列表合并,根据名称列名称相同的品名将其它列值相同的进行合并,并且不能跨品名合并 如图 用到el-table合并行的方法合并 tableSpanMethod({ row, column, rowIndex, columnIndex }) {if (column.property "materielName") {//合并商品名const _row this…...

微信小程序显示二维码?

wxml <canvas style"width: 100%;height: 100%;margin-left: 20%;" id"Canvase" type"2d"></canvas> js // pages/code/code.js Page({/*** 页面的初始数据*/data: {code: ,},/*** 生命周期函数--监听页面加载*/onLoad(options) {…...

JavaWeb开发全流程笔记

JavaWeb 前端Web开发javaScript1.JS引入2.JS基础语法3.JS函数4.JS对象 BOMDOM文档对象模型JS事件监听VueVue常用指令Vue的生命周期 AjaxAxios 前端工程化环境准备NodeJS安装和Vue-cli安装vue项目Vue组件库Element组件的使用 Vue路由Nginx打包部署 后端Web开发MavenSpringBootHT…...

LLM;超越记忆《第 2 部分 》

一、说明 在这篇博客中&#xff0c;我深入研究了将大型语言模型&#xff08;LLM&#xff09;提升到基本记忆之上的数学框架。我们探索了动态上下文学习、连续空间插值及其生成能力&#xff0c;揭示了 LLM 如何理解、适应和创新超越传统机器学习模型。 LLM代表了人工智能的重大飞…...

Python中的加法测试题实现

随机生成5道10以内的加法测试题&#xff0c;用户在10秒内使用键盘输入答案。完成全部5道答题之后&#xff0c;计算机生成答题记录报告&#xff0c;并对答题情况进行分析&#xff0c;显示“答对了”&#xff0c;或“答错了”、并显示正确答案。如果未能按时完成&#xff0c;则显…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

JS设计模式(4):观察者模式

JS设计模式(4):观察者模式 一、引入 在开发中&#xff0c;我们经常会遇到这样的场景&#xff1a;一个对象的状态变化需要自动通知其他对象&#xff0c;比如&#xff1a; 电商平台中&#xff0c;商品库存变化时需要通知所有订阅该商品的用户&#xff1b;新闻网站中&#xff0…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖

在Vuzix M400 AR智能眼镜的助力下&#xff0c;卢森堡罗伯特舒曼医院&#xff08;the Robert Schuman Hospitals, HRS&#xff09;凭借在无菌制剂生产流程中引入增强现实技术&#xff08;AR&#xff09;创新项目&#xff0c;荣获了2024年6月7日由卢森堡医院药剂师协会&#xff0…...

无人机侦测与反制技术的进展与应用

国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机&#xff08;无人驾驶飞行器&#xff0c;UAV&#xff09;技术的快速发展&#xff0c;其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统&#xff0c;无人机的“黑飞”&…...