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

使用C#编写k8s CRD Controller

本文项目地址:k8s-crd - Repos (azure.com)

CRD

CRD指的是Custom Resource Definition。开发者更多的关注k8s对于容器的编排与调度,这也是k8s最初惊艳开发者的地方。而k8s最具价值的地方是它提供了一套标准化、跨厂商的 API、结构和语义。

k8s将它拥有的一切看作是资源,而它提供了操作资源的标准 API。我们可以使用api部署容器,进行调度,可以设置ingress 网络,可以操作volumes 做持久化存储等。

定制资源(Custom Resource)是对 Kubernetes API 的扩展。k8s内置了pod,services,configmap等资源,而用户则可以利用CRD和API,来对k8s的功能进行扩展。

声明式 API

k8s使用声明式API,声明式API与命令式API最大的区别在于:

  • 命令式API是同步的,即时的,当服务收到命令之后就会去执行,并且将结果返回。

  • 而声明式API则是向服务提交对象的配置信息,表达期望得到的对象状态,再由服务选择时机去完成。

例如,当我们使用kubectl apply 命令之后,此时可能会因令牌过期导致无法拉取image或者HelmRelease,因为k8s使用的是声明式api,用户期待的状态已经被提交,k8s会在令牌刷新成功之后最终实现用户期望。

CRD Controller

创建 CRD 不需要编程,只需要编写合规的yaml文件。

而实现CRD对象所想要的功能则需要CRD Controller来完成。编写k8s Controller并非go或者python的专利,这篇博客则是要讲如何使用C#来编写一个CRD Controller。

CRD能用来做什么?

CRD可以用来声明服务所需要或者所具有的资源。这里我们假设一个场景:

我们的服务中需要用到对象存储,来存储客户照片,或者一些大文件。通常我们会在项目中配置对象存储服务的路径,访问所需要的账号密码等,更重要的是,我们需要确定对象存储服务的类型:使用公司机房搭建的minio,还是使用云服务厂商提供的对象存储服务,配置显然是不同的。

这时我们就可以使用k8s CRD来屏蔽掉这类基础设施的实现细节。

想想看,如果我们只需要在服务的yaml中声明用来存储文件的Bucket Name和Service Name,具体使用哪种存储方式由当前所在的k8s集群来决定,存储地址自动生成在configmap中,账号密码也可以自动创建并生成secret,同时存储对象的Bucket也会自动被创建出来,是不是很方便呢?

这个只包含了Bucket Name和Service Name的yaml就是我们要创建的CRD,而这个目标则需要由对应的CRD Controller来完成。

C#实现CRD Controller

KubeOps

KubeOps是用dotnet编写的kubernetes operator SDK。和Go语言的sdk相比,它提供了相同甚至更多功能,它已经包含了对kubernetes-client/csharp 官方C# Client类库的引用。

我们可以使用命令安装KubeOps项目模板:

dotnet new --install KubeOps.Templates::*

之后我们就可以在VS中新建一个KubeOps operators 项目了。

Object Storage Operator

按约定,用来承载CRD Controller的服务一般被称为Operator,例如Helm Operator。

CRD Entity

打开刚才创建的项目,在Entities目录下编辑CRD对象对应的C#类型定义。

 [KubernetesEntity(Group = "mahua.crd.com", ApiVersion = "v1", Kind = "Bucket")]public class V1BucketEntity : CustomKubernetesEntity<V1BucketEntity.V1BucketEntitySpec, V1BucketEntity.V1BucketEntityStatus>{public class V1BucketEntitySpec{public string ServiceName { get; set; } = string.Empty;public string BucketName { get; set; } = string.Empty;}public class V1BucketEntityStatus{public string Status { get; set; } = string.Empty;}}

需要注意的是Attribute中Group相当于该CRD所在的组织类型,只有符合定义就可以了。

Kind相当于CRD的name,如同我们使用kubectl get pod -A 一样,创建CRD之后,我们就可以使用kubectl get bucket -A来查看集群当前的bucket定义。

CRD YAML

重新生成项目(自行处理掉项目中报错的地方),我们可以看到在config/crds目录下已经为我们自动生成了Bucket CRD YAML,我们可以按照CRD规范,对其进行简单修改,并部署

为CRD添加名称缩写

部署CRD YAML并测试

Mock ObjectStorageManager

我在这里Mock了一个ObjectStorageManager,在监听到集群中的Bucket资源变化时做出响应,正如前面所说的:确定对象存储服务地址;生成secret;并在对象存储服务中创建出需要的Buckcet。

因为KubeOps已经集成了kubernetes-client/csharp,我们可以直接在服务中注入IKubernetesClient来完成所需要的k8s操作。

        public async Task RegisterBucketAsync(V1BucketEntity bucketEntity){if (bucketEntity?.Metadata is null || bucketEntity.Spec is null){throw new ArgumentNullException();}await CreateSecretAsync(bucketEntity.Spec.ServiceName,bucketEntity.Spec.BucketName,bucketEntity.Metadata.NamespaceProperty,_environment.EnvironmentName);}private async Task RegisterBucketAsync(string serviceName, string bucketName, string @namespace, string environmentName){var secretName = GetSecretName(serviceName, bucketName);var url = MockObjectStorageUrl(environmentName);var account = MockObjectStorageAccount(serviceName);await MockCreateBucketAsync(bucketName);var secretEntity = CreateBucketSecret(@namespace, serviceName, secretName, url, account.UserName, account.Password);var secret = await _client.Get<V1Secret>(secretName, @namespace);if (secret == null){await _client.Create(secretEntity);}}

CRD Controller

因为Template已经为我们搭建好了项目基架,我们只需在BucketController当中注入需要的ObjectStorageManager服务即可。

ReconcileAsync方法会不断监视Bucket CRD的状态并执行,我们利用类库内置的IFinalizerManager服务为其添加finalizers 。

finalizers的作用我之前的博客已经提到过了K8s-Finalizers。Bucket作为基础设施用于持久化存储,有必要为其设置finalizers 。

[EntityRbac(typeof(V1BucketEntity), Verbs = RbacVerb.All)]public class BucketController : IResourceController<V1BucketEntity>{private readonly ILogger<BucketController> _logger;private readonly IFinalizerManager<V1BucketEntity> _finalizerManager;private readonly ObjectStorageManager _objectStorageManager;public BucketController(ILogger<BucketController> logger, IFinalizerManager<V1BucketEntity> finalizerManager,ObjectStorageManager objectStorageManager){_logger = logger;_finalizerManager = finalizerManager;_objectStorageManager = objectStorageManager;}public async Task<ResourceControllerResult?> ReconcileAsync(V1BucketEntity entity){_logger.LogInformation($"entity {entity.Name()} called {nameof(ReconcileAsync)}.");await _finalizerManager.RegisterFinalizerAsync<BucketFinalizer>(entity);await _objectStorageManager.RegisterBucketAsync(entity);return ResourceControllerResult.RequeueEvent(TimeSpan.FromSeconds(15));}}

验证CRD Controller

my-test-bucket.yaml

我们可以编写YAML来模拟一个需要对象存储服务的service部署后的场景。

apiVersion: "mahua.crd.com/v1"
kind: Bucket
metadata:name: my-test-bucket
spec:bucketName: "user-photo"serviceName: "my-app"

kubectl apply

我们可以注意到此时my-test-bucket是没有finalizers的,按照设计,当我们启动Operator会自动为其添加finalizers并生成secret。

Debug ObjectStorage.Operator

我们可以看到finalizers已经被添加,而且我们想要的对象存储服务的secret也自动生成了出来。

结论

这里就是通过一个简单的例子,为大家介绍k8s CRD的一些基本概念,以及如何使用C#来实现一个CRD Controller。CRD为我们扩展K8s提供了条件,在项目中我们可以根据需要来选择实现。

相关文章:

使用C#编写k8s CRD Controller

本文项目地址&#xff1a;k8s-crd - Repos (azure.com)CRDCRD指的是Custom Resource Definition。开发者更多的关注k8s对于容器的编排与调度&#xff0c;这也是k8s最初惊艳开发者的地方。而k8s最具价值的地方是它提供了一套标准化、跨厂商的 API、结构和语义。k8s将它拥有的一切…...

Ansible---playbook剧本

目录 引言&#xff1a;什么是playbook&#xff1f; 一、Playbook 1.1、playbook中的核心元素 1.2、playbook中的基础组件 1.3、playbook格式说明 1.4、实例&#xff1a;httpd服务剧本 二、playbook中的模块 2.1、Templates 模块 2.2、tags 模块 2.3、Roles 模块 引言&…...

Delphi 中TImageCollection和TVirtualImageList 控件实现high-DPI

一、概述RAD Studio允许你通过使用TImageCollection组件和TVirtualImageList组件&#xff0c;在你的Windows VCL应用程序中包含缩放、高DPI、多分辨率的图像。这两个组件位于Windows 10面板中&#xff1a;注意&#xff1a;如果你使用FireMonkey进行跨平台应用&#xff0c;请看T…...

Ros中如何给UR5配置自定义工具 | 在Rviz中给UR5机器人装载定义工具 | UR5配置自定义末端执行器

前言 在学习和项目研究的过程中&#xff0c;我需要在Ur5e上装上工具&#xff0c;以对现实场景进行仿真。网上会有一些装载/配置现成的夹爪&#xff0c;例如Robotiq等。但和我们装载自定义工具的场景还有些差异&#xff0c;因此写一篇博客记录&#xff0c;可能有偏差。如果有问…...

数据库 delete 表数据后,磁盘空间为什么还是被一直占用?

插&#xff1a; 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 坚持不懈&#xff0c;越努力越幸运&#xff0c;大家一起学习鸭~~~ 最近有个上位机获取下位机上报数据的项目&#xff0c…...

docker-微服务篇

docker学习笔记1.docker简介1.1为什么会出现docker&#xff1f;1.2docker理念1.3虚拟机&#xff08;virtual machine&#xff09;1.4容器虚拟化技术1.5一次构建到处运行2.docker安装2.1前提条件2.2docker基本构成2.3docker安装步骤*2.4测试镜像3.docker常用命令3.1 启动docker3…...

图像优化篇

目录&#xff08;1&#xff09;矢量图&#xff08;2&#xff09;位图 2.1 分辨率2&#xff0c;图像格式格式选择建议&#xff1a;&#xff08;1&#xff09;矢量图 被定义为一个对象&#xff0c;包括颜色&#xff0c;大小&#xff0c;形状&#xff0c;以及屏幕位置等属性&…...

在surface go 2上安装ubuntu 20.04

在surface go 2上安装ubuntu 20.04 1.制作安装盘 下载ubuntu系统的iso文件 使用Rufus软件将u盘制作为ubuntu系统的安装盘 2.在surface go 2上操作 禁用快速启动 在 Windows 中&#xff0c;禁用“电源选项”中的“快速启动”>选择电源按钮的功能 禁用 Bitlocker 在 Wi…...

Java:SpringMVC的使用(1)

目录第一章、SpringMVC基本了解1.1 概述1.2 SpringMVC处理请求原理简图第二章、SpringMVC搭建框架1、搭建SpringMVC框架1.1 创建工程【web工程】1.2 导入jar包1.3 编写配置文件(1) web.xml注册DispatcherServlet(2) springmvc.xml(3) index.html1.4 编写请求处理器【Controller…...

自动化测试岗位求职简历编写规范+注意事项,让你的简历脱颖而出

目录 前言 1.个人信息 2.教育背景(写最高学历) 3.个人技能(按精通/掌握/熟练/了解层次来写) 4.工作经历 5.工作经验/项目经历 6.自我评价 总结 前言 挑选一个阅读舒适度不错的模板 HR和面试官看的简历多&#xff0c;都是快速阅读&#xff0c;舒适度特别重要&#xff1b…...

C 字符串

在 C 语言中&#xff0c;字符串实际上是使用空字符 \0 结尾的一维字符数组。因此&#xff0c;\0 是用于标记字符串的结束。空字符&#xff08;Null character&#xff09;又称结束符&#xff0c;缩写 NUL&#xff0c;是一个数值为 0 的控制字符&#xff0c;\0 是转义字符&#…...

【每日一题Day115】LC2335装满杯子需要的最短总时长 | 贪心

装满杯子需要的最短总时长【LC2335】 You have a water dispenser that can dispense cold, warm, and hot water. Every second, you can either fill up 2 cups with different types of water, or 1 cup of any type of water. You are given a 0-indexed integer array amo…...

Flink流计算处理-旁路输出

使用Flink做流数据处理时&#xff0c;除了主流数据输出&#xff0c;还自定义侧流输出即旁路输出&#xff0c;以实现灵活的数据拆分。 定义旁路输出标签 首先需要定义一个OutputTag&#xff0c;代码如下&#xff1a; // 这需要是一个匿名的内部类&#xff0c;以便我们分析类型…...

nginx正向代理的配置和使用

nginx正向代理的配置和使用 nginx正向代理的配置和使用nginx正向代理的配置和使用安装包准备下载nginx安装包下载正向代理模块的包版本与模块对照表部署nginx服务上传nginx包和正向模块包解压,改名安装nginx配置正向代理创建nginx用户检查nginx配置并启动nginx服务所在服务器验…...

Oracle Trace File Analyzer 介绍及简单使用

一、什么是Oracle Trace File Analyzer Oracle Autonomous Health Framework(AHF) 包含 Oracle ORAchk, Oracle EXAchk, and Oracle Trace File Analyzer(TFA). AHF工具包包含了Oracle常用的多种诊断工具&#xff0c;如 ORAchk, Oracle EXAchk, and Oracle Trace File Analyzer…...

面试实战篇 | 快手本地生活,结合项目谈Redis实战项目场景?MySQL InnoDB存储引擎如何工作的?策略模式?

本期是【你好&#xff0c;面试官】系列文章的第21期&#xff0c;持续更新中…。 《你好&#xff0c;面试官》系列目前已经连载20篇了&#xff0c;据说看了这个系列的朋友都拿到了大厂offer~ 你好&#xff0c;面试官 | 你真的理解面向 “对象”&#xff1f;你好&#xff0c;面…...

Hadoop之——WordCount案例与执行本地jar包

目录 一、WordCount代码 (一)WordCount简介 1.wordcount.txt (二)WordCount的java代码 1.WordCountMapper 2.WordCountReduce 3.WordCountDriver (三)IDEA运行结果 (四)Hadoop运行wordcount 1.在HDFS上新建一个文件目录 2.新建一个文件&#xff0c;并上传至该目录下…...

利用git reflog 命令来查看历史提交记录,并使用提交记录恢复已经被删除掉的分支

一.问题描述 当我们在操作中手误删除了某个分支&#xff0c;那该分支中提交的内容也没有了&#xff0c;我们可以利用git reflog这个命令来查看历史提交的记录从而恢复被删除的分支和提交的内容 二.模拟问题 1.创建git仓库&#xff0c;并提交一个文件 [rootcentos7-temp /da…...

【软件测试】大厂测试开发你真的了解吗?测试开发养成记......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 在一些大公司里&…...

Redis中的hash结构和扩容机制

1.rehash原理 hash包含两个数据结构为字典数组ht[0]和ht[1]。其中ht[0]用来存放数据&#xff0c;ht[1]在rehash时使用。 扩容时&#xff0c;ht[1]的大小为第一个大于等于ht[0].used*2的2的幂次方的数&#xff1b; 收缩时&#xff0c;ht[1]的大小为第一个大于等于ht[0].used的…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

MongoDB学习和应用(高效的非关系型数据库)

一丶 MongoDB简介 对于社交类软件的功能&#xff0c;我们需要对它的功能特点进行分析&#xff1a; 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具&#xff1a; mysql&#xff1a;关系型数据库&am…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

MyBatis中关于缓存的理解

MyBatis缓存 MyBatis系统当中默认定义两级缓存&#xff1a;一级缓存、二级缓存 默认情况下&#xff0c;只有一级缓存开启&#xff08;sqlSession级别的缓存&#xff09;二级缓存需要手动开启配置&#xff0c;需要局域namespace级别的缓存 一级缓存&#xff08;本地缓存&#…...

stm32wle5 lpuart DMA数据不接收

配置波特率9600时&#xff0c;需要使用外部低速晶振...