当前位置: 首页 > 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的…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...