在kubernetes生态中,通过自定义CRD(CustomResourceDefinition)来扩展自定义资源,扩展集群的功能。通过执行kubectl get crd来获取kubernetes集群中安装的CRD资源,CRD扩展方式有效的扩展kubernetes生态。
在对资源定义的时候,通过GVK(Group-Version-Kind)来唯一的表示一种资源类型,可以看到如下的yaml中Deployment这个类型对应的Group为apps, 版本是v1
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
labels:
app.kubernetes.io/component: manager
name: project-controller-manager
namespace: default
在创建CRD的时候,需要定义一个版本,例如v1beta1,所有自定义资源对象最初都将存储在这个版本中,所有的client将会使用v1beta1 版本的API。随着资源对象的演进,会引入其他新的版本,例如v1beta2、v1、v2beta1、v2beta2等等,等某些api对象版本成熟,将会将历史版本的api对象设置成废弃的状态,最终移除对于废弃api对象的支持。对应的client去访问和操作api对象的时候需要根据不同版本的api去做调整,下面的内容是kubernetes中针对自定义CRD资源如何去做多版本的管理以及kubebuilder框架为我们提供了那些机制完成多版本资源的管理。
CRD资源支持对象支持多个版本
CustomResourceDefinition定义的时候,可以在spec.versions中定义多个版本的对象,例如可以自定义CronJob资源存在三个版本v1beta1、v1、v2beta1。
资源对象的版本可以三个状态
使用中:该版本的资源定义可以被使用
废弃状态:该版本的资源定义仍然可以被使用,但是已经处于不推荐使用状态,在未来将会被移除,处于该状态的资源对象,需要将其升级到新版本的对象
移除状态:该版本的资源对象已经无法被访问和使用
资源对象版本的管理可以参考kubernetes api管理规范去规划CRD资源对象的管理。Kubernetes 是一个 API 驱动的系统,API的版本号通常用于描述API的成熟阶段。
v1
正式发布(Generally available,GA,稳定版本)
v1beta1
Beta (预发布)
v1alpha1
Alpha (试验性)
不同版本对应的废弃和移除策略也是不一样的, 当某个API的实现达到一个新的GA稳定版本时(如v2),旧的GA版本(如v1)和Beta版本(例如v2beta1)将逐渐被废弃,Kubernetes建议废弃的时间如下。
对于旧的GA版本(如v1),Kubernetes建议废弃的时间应不少于12个月或3个大版本Release的时间,选择最长的时间。
对旧的Beta版本(如v2beta1),Kubernetes建议废弃的时间应不少于9个月或3个大版本Release的时间,选择最长的时间。
对旧的Alpha版本,则无须等待,可以直接废弃。
通过在自定义资源的时候指定字段标注出来那个版本的资源对象处于废弃状态,
当对该资源的已弃用版本发出API请求时,将在API响应中作为头返回一条警告消息。通过这个告警信息可以方便的对api版本进行治理。
另外可以在定义资源对象的时候,设置是否移除该版本的资源对象,如下图所示。可以通过调整这个字段来关闭该版本的资源对象,测试对该资源对象访问的组件是否工作正常,常常会在组件升级的过程中会去使用。
对象的版本与存储
Client端去访问资源对象的时候,需要指定对应的版本,废弃状态的版本以及正常使用的版本可以正常的访问,移除状态的版本无法访问。Client可以访问不同版本的api版本,通过版本之间的转换来支持多个版本的资源对象,不同版本的资源对象需要可以相互转换,并且转换的时候不能发生字段属性的丢失。 Kubebuilder中采用“hub and spoke”模型来管理不同版本的api转换
实心点表示某个版本的对象,需要实现不同版本资源的转换,kubebuilder中定义了某个版本是hub,如右边图中心的实心点,对象之间的转换需要通过hub version。Hub version也可以被称为storage version. Hub version在CRD可以通过设置版本对象中的storage: true来标志为hub。
对于CRD对象的版本之间的转换需要提供webhook来支持,在CRD对象定义中通过spec.conversion来定义webhook, webhook是外部一个服务。之后由kube-apiserver调用过程中对对象版本进行转换。Webhook支持URL或者Service Reference两种格式,下图为service reference为kubernetes集群中某个service.
当对象存在v1beta1、 v1、 v2beta1三个版本,v1为storage/hub version, client创建v1beta1的对象,kube-apiserver将会调用webhook完成v1beta1转换成v1格式的对象。之后存储的对象版本为v1版本。当client获取该对象的v2beta1版本的时候,kube-apiserver获取到存储的v1版本的时候,会调用webhook完成v1版本的格式转换成v2beta1版本,返回给client。
Kubebuilder支持多版本对象
通过kubebuilder初始化一个demo项目,演示如何在kubebuilder的框架下支持多个版本对象,以Changing things up - The Kubebuilder Book为例子。
# 创建project项目空间
mkdir project
cd project
# 初始化
kubebuilder init --domain tutorial.kubebuilder.io --repo tutorial.kubebuilder.io/project
##创建三个版本的api对象
# kubebuilder create api --group batch --version v1 --kind CronJob --force
# kubebuilder create api --group batch --version v2 --kind CronJob --force
# kubebuilder create api --group batch --version v3 --kind CronJob --force
##在v1对应的project/api/v1/cronjob_types.go中设置+kubebuilder:storageversion该v1版本为storage
##添加project/api/v1/cronjob_conversion.go
// Hub marks this type as a conversion hub.
func (*CronJob) Hub() {}
##添加project/api/v2/cronjob_conversion.go
// ConvertTo converts this CronJob to the Hub version (v1).
func (src *CronJob) ConvertTo(dstRaw conversion.Hub) error {
….
}
// ConvertFrom converts from the Hub version (v1) to this version.
func (dst *CronJob) ConvertFrom(srcRaw conversion.Hub) error {
…….
}
##添加project/api/v3/cronjob_conversion.go
// ConvertTo converts this CronJob to the Hub version (v1).
func (src *CronJob) ConvertTo(dstRaw conversion.Hub) error {
….
}
// ConvertFrom converts from the Hub version (v1) to this version.
func (dst *CronJob) ConvertFrom(srcRaw conversion.Hub) error {
…….
}
###添加一个webhook,来实现/convert
kubebuilder create webhook --group batch --version v1 --kind CronJob --conversion
Kubebuilder基于“hub and spoke”模型来实现对象之间的转换,如上个例子所示,我们需要实现v2<->v1, v1<->v3之间的ConvertTo、ConvertFrom函数
总结
Kubernetes 资源对象的版本定义对于kubernetes的成功起到了至关重要的作用,其中资源对象的多版本管理包括了kubernetes社区的思考和探索,对于其他系统的api对象的设计有很好的参考价值。
参考资料
Kubernetes 弃用策略 | Kubernetes
and setting up the webhooks - The Kubebuilder Book
(免责声明:本网站内容主要来自原创、合作伙伴供稿和第三方自媒体作者投稿,凡在本网站出现的信息,均仅供参考。本网站将尽力确保所提供信息的准确性及可靠性,但不保证有关资料的准确性及可靠性,读者在使用前请进一步核实,并对任何自主决定的行为负责。本网站对有关资料所引致的错误、不确或遗漏,概不负任何法律责任。
任何单位或个人认为本网站中的网页或链接内容可能涉嫌侵犯其知识产权或存在不实内容时,应及时向本网站提出书面权利通知或不实情况说明,并提供身份证明、权属证明及详细侵权或不实情况证明。本网站在收到上述法律文件后,将会依法尽快联系相关文章源头核实,沟通删除相关内容或断开相关链接。 )