加强 Kubernetes 能力:利用 CRD 定义多版本资源的实现方式
姚灿武,Rancher 中国研发工程师,拥有 7 年云计算领域经验,热衷开源技术,在云原生相关技术领域拥有丰富的开发和实践经验。
CRD,即自定义资源定义(Custom Resource Definition),是 Kubernetes API 中一个强大的扩展机制。通过 CRD,用户可以定义自己的资源类型,来扩展 Kubernetes 的 API 和资源类型。CRD 定义可以用于创建多个版本的资源,这对于 Kubernetes 集群的演变和升级非常有用。
在本文中,我们将介绍 Kubernetes CRD 的版本概念和使用方法;讨论如何在 CRD 中定义多个版本的资源,并讨论资源数据存储和数据转换的实现方式。最后,我们将介绍如何开发 CRD webhook,以便在 Kubernetes 中实现 CRD 版本兼容。
多版本 CRD
多版本 CRD 是指在 CRD 中定义多个版本的 API,每个版本的 API 可以有自己的规则,这样就可以在不影响旧版本应用程序的情况下,对新版本应用程序进行更新和升级。
要创建多版本 CRD,我们需要定义一个 Custom Resource Definition 对象,该对象包含多个 version 字段。每个 version 字段都有一个 schema,其中包含了自定义资源的属性和规则。
通过一个例子来说明,以下是一个单版本 CRD 示例:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:name: foos.sample.webhook.io
spec:conversion:strategy: Nonegroup: sample.webhook.ionames:kind: FoolistKind: FooListplural: foosshortNames:- foo- foossingular: fooscope: Namespacedversions:- name: v1schema:openAPIV3Schema:properties:apiVersion:type: stringkind:type: stringmetadata:type: objecttype: objectserved: truestorage: true
文件中规定版本信息以及资源的名称、类型等信息。通过 kubectl apply 命令,可以将该 CRD 文件应用到 Kubernetes 集群中,从而在集群中创建一个新的资源类型 Foo,例如:
apiVersion: sample.webhook.io/v1
kind: Foo
metadata:name: foo-sample
上述自定义资源 Foo 只有一个 v1 版本,如果我们需要更新自定义资源中的某个字段,就需要更新 Foo 的版本,例如更新为 v2 版本,就要在 CRD 文件中添加 v2 版本的定义,例如:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:name: foos.sample.webhook.io
spec:versions:- name: v1schema:openAPIV3Schema:properties:apiVersion:type: stringkind:type: stringmetadata:type: objecttype: objectserved: truestorage: false- name: v2schema:openAPIV3Schema:properties:alias:type: stringapiVersion:type: stringkind:type: stringmetadata:type: objecttype: objectserved: truestorage: true
在上述 CRD 文件中,我们定义了两个版本,v1 和 v2。v2 相比 v1 新增了一个 alias 字段。
资源数据存储
为确保 Kubernetes 能够正确地将自定义资源持久化到存储中,并且能够正确地从存储中读取和还原自定义资源。CRD 中定义了 spec.versions.storage 字段,用于指示使用哪个版本的 CRD 持久化到存储中。在一个 CRD 定义中,只能有一个版本的 storage 字段的值为 true。
上述例子中,我们定义了两个版本,v1 和 v2。v1 版本 storage 字段为 false,v2 版本 storage 字段为 true,这表明 Kubernetes etcd 中存储的是 v2 版本的资源数据。
那么对于未被选定的版本的数据如何存储呢?以上面 foo-sample
为例,我们来看下 etcd 中是怎么存储的,结果如下:
/registry/sample.webhook.io/foos/default/foo-sample
{"apiVersion":"sample.webhook.io/v2","kind":"Foo","metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"sample.webhook.io/v1\",\"kind\":\"Foo\",\"metadata\":{\"annotations\":{},\"name\":\"foo-sample\",\"namespace\":\"default\"}}\n"},"creationTimestamp":"2023-05-22T09:49:03Z","generation":1,"managedFields":[{"apiVersion":"sample.webhook.io/v1","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:annotations":{".":{},"f:kubectl.kubernetes.io/last-applied-configuration":{}}}},"manager":"kubectl-client-side-apply","operation":"Update","time":"2023-05-22T09:49:03Z"}],"name":"foo-sample","namespace":"default","uid":"3360f129-31f7-4a3f-8991-7694524d9a78"}}
第一行是 foo-sample
的 key,第二行是 foo-sample
json 格式表示的内容,其中 apiVersion
为 sample.webhook.io/v2
,这表明即便 v1 版本的资源也以 v2 版本的格式存储。
数据转换
当自定义资源支持多个版本时,因为只能以某一个版本的格式进行存储,所以需要在存储的版本和提供的版本之间进行转换,实现多版本兼容。
- 如果转换涉及模式变更, 并且需要自定义逻辑,则应该使用 Webhook 来完成。在 CRD 中配置 webhook 示例如下:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
...
spec: conversion: strategy: Webhook webhook: clientConfig: caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJ2akNDQVdPZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQkdNUnd3R2dZRFZRUUtFeE5rZVc1aGJXbGoKYkdsemRHVnVaWEl0YjNKbk1TWXdKQVlEVlFRRERCMWtlVzVoYldsamJHbHpkR1Z1WlhJdFkyRkFNVFk0TkRjegpPRGswTXpBZUZ3MHlNekExTWpJd056QXlNak5hRncwek16QTFNVGt3TnpBeU1qTmFNRVl4SERBYUJnTlZCQW9UCkUyUjVibUZ0YVdOc2FYTjBaVzVsY2kxdmNtY3hKakFrQmdOVkJBTU1IV1I1Ym1GdGFXTnNhWE4wWlc1bGNpMWoKWVVBeE5qZzBOek00T1RRek1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRUZYWDQzaEZRdjRyOApKelR1UkJ0b3lqUmRtWjhIRkExbWZnOXJnTWVlNnVXZ20wMXBNR3lSRnFna3Z1RHF5RUlMTUtCRDduQ2IrVFp3CitBR3loVWhTV0tOQ01FQXdEZ1lEVlIwUEFRSC9CQVFEQWdLa01BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0hRWUQKVlIwT0JCWUVGRzg2VnpCcW1wRUcrUWlrS0d1SGNIQlJwS2R3TUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDSVFDaQp5SFFyeGNXN3dUM0dwRWhyNklQQWpXWDVJOSt4Y0dkUGQzQURKS0hwZ2dJaEFJQmhTc00xd1hxMU80VUlaWWZwCkNWVkxwaCtvUVMvMzI5OHMwS0VqWW9FTAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== service: name: webhook-sample namespace: default path: /v1/webhook/conversion port: 443 conversionReviewVersions: - v1
- 如果没有模式变更,则可使用默认的
None
转换策略,为不同版本提供服务时只有apiVersion
字段会被改变。
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
...
spec:...conversion:strategy: None
CRD webhook 开发
与 Admission Webhook一样,CRD webhook 也是一个 HTTP 回调,webhook service 就是一个 HTTP 服务。接口结构如下:
// ConversionReview describes a conversion request/response.
type ConversionReview struct {metav1.TypeMeta `json:",inline"`// request describes the attributes for the conversion request.// +optionalRequest *ConversionRequest `json:"request,omitempty" protobuf:"bytes,1,opt,name=request"`// response describes the attributes for the conversion response.// +optionalResponse *ConversionResponse `json:"response,omitempty" protobuf:"bytes,2,opt,name=response"`
}
Harvester 项目组在 harvester webhook框架中增加了 CRD webhook 的支持,开发者只需要实现 Converter
接口并把它注册到 webhook server 中,然后启动 webhook server 即可。
// Converter is a interface to convert object to the desired version
type Converter interface {GroupResource() schema.GroupResourceConvert(Object *unstructured.Unstructured, desiredAPIVersion string) (*unstructured.Unstructured, error)
}
具体开发细节请参考示例 webhook sample。
总 结
在实际产品进化演变过程中,多版本兼容一直是一个重要的问题。Kubernetes CRD 采用选定某一个版本进行持久化,并使用 webhook 实现多版本数据转换的策略来解决多版本兼容性问题。在 Kubernetes 外的其他项目中,这种策略也值得学习借鉴。
参 考
Versions in Custom Resource Definitions:https://kubernetes.io/zh-cn/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definition-versioning
相关文章:
加强 Kubernetes 能力:利用 CRD 定义多版本资源的实现方式
姚灿武,Rancher 中国研发工程师,拥有 7 年云计算领域经验,热衷开源技术,在云原生相关技术领域拥有丰富的开发和实践经验。 CRD,即自定义资源定义(Custom Resource Definition),是 Ku…...

区块链应用 DApp 开发需要掌握的技能
文章目录 前言为什么要开发 DAppDApp 的优势DApp 应用范围DApp 开发者技能 前言 前面区块链系列的文章中介绍了区块链技术、智能合约、web3js,Solidity 编程语言,在开发者的角度就是要基于这些知识在Web3时代去开发一个 DApp(去中心化应用程…...

关于新版本selenium定位元素报错:‘WebDriver‘ object has no attribute ‘find_element_by_id‘等问题
由于一段时间没有使用Selenium,当再次使用时发现之前写的Selenium元素定位的代码运行之后会报错,发现是Selenium更新到新版本(4.x版本)后,以前的一些常用的代码的语法发生了改变,当然如果没有更新过或是下载…...
c++通过自然语言处理技术分析语音信号音高
对于语音信号的音高分析,可以使用基频提取技术。基频是指一个声音周期的重复率,也就是一个声音波形中最长的周期。 通常情况下,人的声音基频范围是85Hz到255Hz。根据语音信号的基频可以推断出其音高。 C中可以使用数字信号处理库或语音处理库…...

[pymc3][python]pymc3安装后测试代码2
测试环境: pymc33.11.2 代码: import numpy as np import pymc3 as pm import matplotlib.pyplot as pltif __name__ __main__:# 生成随机数据np.random.seed(123)x np.linspace(0, 1, 100)y 0.5 * x np.random.normal(0, 0.1, size100)# 定义概率…...

Go语言time库,时间和日期相关的操作方法
time库 用于处理时间、日期和时区的核心库。在实际开发中,常常需要与时间打交道,例如记录日志、处理时间差、计算时间间隔等等。因此,掌握time库的使用方法对于Go开发者来说非常重要。 在Go语言中,时间表示为time.Time类型&…...

JVM总结笔记
JVM JVM是什么?JVM 的主要组成部分JVM工作流程JVM内存模型直接内存与堆内存的区别:堆栈的区别Java会存在内存泄漏吗?简述Java垃圾回收机制垃圾收集算法轻GC(Minor GC)和重GC(Full GC)新生代gc流程JVM优化与JVM调优 JVM是什么? JVM是Java Virtual Mach…...
C++ 缓存再排序,解决多线程处理后的乱序问题,不知道思路对不对[挠下巴]
C 缓存再排序,解决多线程处理后的乱序问题,不知道思路对不对[挠下巴] 使用map默认会根据key排序的原理作缓存,队列满了依次推出,抛弃掉过时的数据 #include <functional> #include <iostream> #include <map> #…...
华为数通HCIA-地址分类及子网划分
ip地址(逻辑地址) 作用:唯一标识一张网卡 特点:设备天生没有,需要人为配置,可以随时修改 格式:点分十进制 大小:32bit 组成:网络位主机位 网络位:用于标…...

Linux第七章之gdb与makefile使用
一、Linux调试器-gdb使用 1.1背景 程序的发布方式有两种,debug模式和release模式Linux gcc/g出来的二进制程序,默认是release模式要使用gdb调试,必须在源代码生成二进制程序的时候, 加上-g 选项[重要] 1.2开始使用 …...

Mycat-Balance使用指南
MyCAT Balance是一个Java NIO的高性能负载均衡器,可以替代普通的硬件的交换机或其LVS类似的复杂机制,实现MyCAT集群的负载均衡。 MyCAT Balance的配置文件在conf目录下,frontend-conf.为前端配置,包括绑定的端口等,js…...

玩转顺序表——【数据结构】
在C语言学习中,我们经常会遇见增删查改等一系列操作,而这些操作全都与线性表关联,没有线性表将会对这些操作完成的十分艰难!那今天就让我们来了解一下顺序表如何增删查改!!! 目录 1.线性表 2…...
SSE(Server-Sent Events,服务器推送事件)和sockets(套接字)通信区别
SSE(Server-Sent Events,服务器推送事件)和sockets(套接字)都是用于实现实时通信的技术,但它们具有不同的特点和应用场景。 SSE 的优点: 简单易用:SSE 是基于HTTP协议的一种实时通…...

【设计模式——学习笔记】23种设计模式——代理模式Proxy(原理讲解+应用场景介绍+案例介绍+Java代码实现)
介绍 基础介绍 代理模式为一个对象提供一个代理对象,以控制对这个对象的访问。即通过代理对象访问目标对象,这样做的好处是:可以在不修改目标对象代码的基础上,增强额外的功能操作,即扩展目标对象的功能被代理的对象…...

大学英语四新视野 课后习题+答案翻译 Unit1~Unit8
Unit 1 Text A: Words in use 2022年6月16日 20:57 1 As the gender barriers crumbled, the number of women working as lawyers, doctors, or bankers began to increase significantly from the mid-20th century. 随着性别障碍的消除,从20世纪中期开始&am…...

Java入门指南:Java语言优势及其特点
目录 1. Java语言简介及发展概述 2. Java语言的优势 2.1 可移植性 2.2 面向对象 2.3 安全性 2.4 大量类库 3. Java语言与C/C的区别 4. 初识Java程序入口之main方法 5. 注释、标识符、关键字 5.1 注释 5.2 标识符 5.3 关键字 1. Java语言简介及发展概述 Java是一种面…...

Jenkins 节点该如何管理?
Jenkins 拥有分布式构建(在 Jenkins 的配置中叫做节点),分布式构建能够让同一套代码在不同的环境(如:Windows 和 Linux 系统)中编译、测试等 Jenkins 的任务可以分布在不同的节点上运行 节点上需要配置 Java 运行时环境,JDK 版本大于 1.5 节…...

hugging face下载数据集
开始直接执行这个,下载下来的图片打不开 git clone https://huggingface.co/datasets/diffusers/dog-example 解决办法: 安装git lfs 1. curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash 2. sudo apt…...
解决Django报错 : No module named ‘MySQLdb‘
Django的版本是2.0,Python的版本号是3.6.4 在models.py创建好了模型类之后使用命令:python manage.py makemigrations 进行迁移,但是突然报错:ImportError:No module named MySQLdb 查询了相关资料发现python2.x版本是支持mysql…...

【Docker】Docker的优势、与虚拟机技术的区别、三个重要概念和架构及工作原理详细讲解
前言 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。 作者简介: 辭七七…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...

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

【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...

GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...