使用kubebuilder和code-generator构建你的crd套件
什么是Kubebuilder
Kubebuilder 是一个基于 CRD(Custom Resource Definitions,自定义资源定义)构建 Kubernetes API 的框架。它允许开发者使用 CRD 来构建 Kubernetes API、Controller 和 Admission Webhook。Kubebuilder 的主要目的是简化 Kubernetes API 和工具的构建过程,减少样板代码的编写,使得开发者可以更专注于业务逻辑的实现。
Kubebuilder 的工作流程大致如下:
创建一个新的工程目录。 创建一个或多个资源 API CRD 并将字段添加到资源中。 在控制器中实现协调循环(reconcile loop),watch 额外的资源。 在集群中运行测试(自动安装 CRD 并自动启动控制器)。 更新引导集成测试测试新字段和业务逻辑。 使用用户提供的 Dockerfile 构建和发布容器。
什么是code-generator
Kubernetes code-generator 是一个代码生成工具集合,它位于 Kubernetes 代码库中的 staging/src/k8s.io/code-generator 包中,这个工具的主要目的是自动化生成与 Kubernetes 相关的客户端库、API 服务器(API server)和其他与 Kubernetes 相关的代码,以提高代码的可维护性和一致性,减少重复代码的开发工作。
code-generator 的主要功能包括:
自动生成客户端库 clientset:通过定义自定义资源的 API 规范,code-generator 可以自动生成用于访问和操作这些自定义资源的客户端库。 自动生成 API 服务器代码:可以根据自定义资源的 API 规范,自动生成与之对应的 API 服务器代码,使得开发者可以快速构建自己的自定义资源的 API 服务器,并将其部署到 Kubernetes 集群中。 自动生成 DeepCopy 方法:对于 Kubernetes 对象,深拷贝是一种常见的操作,用于创建对象的副本。 自动生成其他辅助代码:除了上述功能外,code-generator 还可以生成其他与 Kubernetes 相关的辅助代码,如列表(List)、转换器(Converter)等。 code-generator 包含多个生成工具(gen tools),例如:
deepcopy-gen:为每个类型生成 DeepCopy 方法。 client-gen:生成类型化客户端集合(typed client sets)。 informer-gen:生成基于 Kubernetes API 资源的 Informer。 lister-gen:生成 Kubernetes API 资源的 Lister。 register-gen:自动生成 API 资源类型的注册表代码。 conversion-gen:用于生成 Kubernetes 对象之间的转换器(Converter)。 openapi-gen:用于生成 Kubernetes API 的 OpenAPI 规范。
综上,这两个工具都可以提升我们管理CRD的效率。首先我们使用Kubebuilder生成我们想要的crd对应的type和对应的crd文件。code-generator可以帮助我们生成与api交互需要的资源,比如lister。
接下来老高会讲解如何使用kubebuilder和code-generator构建你的crd套件。
使用kubebuilder生成骨架
骨架就是一个项目的雏形,kubebuilder为我们提供了相对合理的目录结构,所以赶紧参考Quick Start准备好kubebuilder的运行环境,下一步就开始生成我们的测试项目了。
初始化项目
# 创建目录
mkdir my-crd && cd my-crd
# 初始化
kubebuilder init --domain github.com --repo github.com/phpgao/crd
# 修改项目支持多group
kubebuilder edit --multigroup=true
如果出现类似
invalid go version '1.22.0': must match format 1.23
的提示,请升级go的版本到最新
此时,我们的项目结构应该如下(忽略了不重要的文件)
.
├── Dockerfile
├── Makefile
├── PROJECT
├── README.md
├── bin
├── config
│ ├── default
│ │ ├── kustomization.yaml
│ │ ├── manager_metrics_patch.yaml
│ │ └── metrics_service.yaml
│ ├── manager
│ │ ├── kustomization.yaml
│ │ └── manager.yaml
│ ├── network-policy
│ │ ├── allow-metrics-traffic.yaml
│ │ └── kustomization.yaml
│ ├── prometheus
│ │ ├── kustomization.yaml
│ │ └── monitor.yaml
│ └── rbac
│ ├── kustomization.yaml
│ ├── leader_election_role.yaml
│ ├── leader_election_role_binding.yaml
│ ├── metrics_auth_role.yaml
│ ├── metrics_auth_role_binding.yaml
│ ├── metrics_reader_role.yaml
│ ├── role.yaml
│ ├── role_binding.yaml
│ └── service_account.yaml
├── go.mod
├── go.sum
└── hack
└── boilerplate.go.txt
创建第一个API(GVK)
此时老高希望生成两个版本的Kind=Job,version=v1+v1alpha1,group=task。 然后再生成一个Kind=CronJob,version=v1,group=apps。
# 是否创建资源(yes) 是否生成控制器(no)
# INFO Create Resource [y/n]
# y
# INFO Create Controller [y/n]
# n
kubebuilder create api --group task --version v1 --kind Job --controller=false --resource
kubebuilder create api --group task --version v1alpha1 --kind Job --controller=false --resource
kubebuilder create api --group apps --version v1 --kind CronJob --controller=false --resource
根据Changing things up的描述,当存在多个api版本的时候需要指定一个版本作为storage版本,storage 字段用于标识哪个版本的自定义资源是存储在 etcd 中的版本。当你有多个版本的 CRD 时,Kubernetes 需要知道哪个版本应该用于存储在其底层的 etcd 数据库中。所以我们需要在生成的
api/task/v1/job_types.go
给Job结构体添加// +kubebuilder:storageversion
的注释,否则make manifests时会报错。
生成相关定义
# 修改api/apps/v1/cronjob_types.go
// CronJobStatus defines the observed state of CronJob
type CronJobStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
// Foo is an example field of CronJob. Edit cronjob_types.go to remove/update
Foo string `json:"foo,omitempty"`
}
# 然后执行
make manifests
cat config/crd/bases/apps.phpgao.com_cronjobs.yaml
# 可以发现对应的字段已经更新
至此,我可能已经可以部署crd到集群中了。
下一节我们让crd"动起来",生成clientset,lister,informer。
code-generator
准备工作
我们把code-generator项目克隆到本地
git submodule add https://github.com/kubernetes/code-generator.git
补充文件
把这个文件放到util下,保存为gen.go
mkdir util
wget https://gist.githubusercontent.com/phpgao/9404c323fe2c74d2862701ac4c6e4dc8/raw/cce6d8096e32fb6755f459a038e120523ea87005/gen.go -O gen.go
mv gen.go util
# 在项目根目录执行下面的命令
go run util/gen.go
下载并执行update.sh
wget https://gist.githubusercontent.com/phpgao/9404c323fe2c74d2862701ac4c6e4dc8/raw/ecb1c008432dbd22f75a39a30b352c6fa2401ec3/update-codegen.sh -O update-codegen.sh
# 第一个参数为包名+pkg
bash update-codegen.sh github.com/phpgao/crd/pkg