kubebuilder 中文文档由云原生社区主导翻译。任何问题可以在这儿提issue。issue模版可以参考这个

从 v1 版本迁移到 v2 版本

在继续后续操作之前要确保你了解Kubebuilder v1 版本和 v2 版本之间的不同

请确保你根据安装指导安装了迁移所需的组件。

迁移 v1 项目的推荐方法是创建一个新的 v2 项目,然后将 API 和 reconciliation 代码拷贝过来。 这种转换就像一个原生的 v2 项目。然后,在某些情况下,是可以进行就地升级的(比如,复用 v1 项目 的层级结构,升级 controller-runtime 和 controller-tools)。

让我们来看一个[v1 项目例子][v1-project]并且将其迁移至 Kubebuilder v2。最后,我们会有一些 东西看起来像v2 项目例子

准备

我们将需要明确 group,vresion,kind 和 domain 都是什么。

让我们看看我们目前的 v1 项目的结构:

pkg/
├── apis
│   ├── addtoscheme_batch_v1.go
│   ├── apis.go
│   └── batch
│       ├── group.go
│       └── v1
│           ├── cronjob_types.go
│           ├── cronjob_types_test.go
│           ├── doc.go
│           ├── register.go
│           ├── v1_suite_test.go
│           └── zz_generated.deepcopy.go
├── controller
└── webhook

我们所有的 API 信息都存放在 pkg/apis/batch 目录下,因此我们可以在那儿查找以 获取我们需要知道的东西。

cronjob_types.go 中,我们可以找到

type CronJob struct {...}

register.go 中,我们可以找到

SchemeGroupVersion = schema.GroupVersion{Group: "batch.tutorial.kubebuilder.io", Version: "v1"}

把这些集合起来,我们能够得到 kind 是 CronJob,group-version 是 batch.tutorial.kubebuilder.io/v1

初始化一个 v2 项目

现在,我们需要初始化一个 v2 项目。然而,在此之前,如果在 gopath 中我们没有找到 go 模块, 那么我们需要初始化一个新的 go 模块。

go mod init tutorial.kubebuilder.io/project

接下来,我们可以用 kubebuilder 来完成项目的初始化:

kubebuilder init --domain tutorial.kubebuilder.io

迁移 APIs 和 Controllers

接下来,我们将重新生成 API 类型和 controllers。因为两者我们都需要,当向我们询问 我们想要生成哪些部分时,我们需要输入 yes 来同时生成 API 和 controller。

kubebuilder create api --group batch --version v1 --kind CronJob

如果你在使用多 group,迁移的时候就需要一些手动工作了。更多详细信息可以 查看这个

迁移 APIs

现在,让我们把 API 的定义部分从 pkg/apis/batch/v1/cronjob_types.go 拷贝 至 api/v1/cronjob_types.go。我们仅仅需要拷贝 SpecStatus 字段的实现部分。

我们可以用 +kubebuilder:object:root=true 来替代 +k8s:deepcopy-gen:interfaces=... 标记 (这个在Kubebuilder 中废弃了)。

我们不再需要以下的标记了(他们不再被使用,是 KubeBuilder 一些老版本的遗留产物)。

// +genclient
// +k8s:openapi-gen=true

我们的 API 类型看起来应该像下面这样:

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// CronJob is the Schema for the cronjobs API
type CronJob struct {...}

// +kubebuilder:object:root=true

// CronJobList contains a list of CronJob
type CronJobList struct {...}

迁移 Controllers

现在,让我们将 controller reconciler 的代码从 pkg/controller/cronjob/cronjob_controller.go 迁移至 controllers/cronjob_controller.go

我们需要拷贝

  • ReconcileCronJob 结构体中的字段到 CronJobReconciler
  • Reconcile 函数的内容。
  • rbac 相关标记到一个新文件。
  • func add(mgr manager.Manager, r reconcile.Reconciler) error 下的代码 到 func SetupWithManager

迁移 Webhooks

如果你还没有webhook,你可以跳过此章节。

Core 类型和外部 CRDs 的 Webhooks

如果你在使用 Kubernetes core 类型(比如 Pods),或者不属于你的一个外部 CRD 的 webhooks, 你可以参考内置类型的 controller-runtime 例子,然后做一些类似的事情。 Kubebuilder 不会为这种情形生成太多,但是你可以用 controller-runtime 中的一些库。

为我们的 CRDs 自动生成 Webhooks

现在让我们为我们的 CRD (CronJob) 自动生成 webhooks。我们需要运行以下命令并指定 --defaulting--programmatic-validation 参数(因为我们的测试项目使用 defaulting 和 validating webhooks):

kubebuilder create webhook --group batch --version v1 --kind CronJob --defaulting --programmatic-validation

取决于有多少 CRDs 需要 webhooks,我们或许需要为不同的 Group-Version-Kinds 多次执行上述的命令。

现在,我们需要为每一个 webhook 来拷贝逻辑。对于 validating webhooks,我们需要将 pkg/default_server/cronjob/validating/cronjob_create_handler.go 文件中 func validatingCronJobFn 内容拷贝至 api/v1/cronjob_webhook.go 文件中的 func ValidateCreate,对于 update 来说也是一样的。

类似的,我们将 func mutatingCronJobFn 拷贝至 func Default

Webhook 标记

当自动生成 webhooks 时,Kubebuilder v2 添加了以下标记:

// 这些是 v2 标记

// 这些是关于 mutating webhook 的
// +kubebuilder:webhook:path=/mutate-batch-tutorial-kubebuilder-io-v1-cronjob,mutating=true,failurePolicy=fail,groups=batch.tutorial.kubebuilder.io,resources=cronjobs,verbs=create;update,versions=v1,name=mcronjob.kb.io

...

// 这些是关于 validating webhook 的
// +kubebuilder:webhook:path=/validate-batch-tutorial-kubebuilder-io-v1-cronjob,mutating=false,failurePolicy=fail,groups=batch.tutorial.kubebuilder.io,resources=cronjobs,verbs=create;update,versions=v1,name=vcronjob.kb.io

默认的 verbs 是 verbs=create;update。我们需要确保 verbs 和我们所需要的是一致的。 比如,如果我们仅仅想验证 creation,那么我们就需要将 verbs 改成 verbs=create

我们也需要确保 failure-policy 是不变的。

如下所示的标记将不再被使用(因为他们和自部署证书配置有关,这些在 v2 被移除了):

// v1 markers
// +kubebuilder:webhook:port=9876,cert-dir=/tmp/cert
// +kubebuilder:webhook:service=test-system:webhook-service,selector=app:webhook-server
// +kubebuilder:webhook:secret=test-system:webhook-server-secret
// +kubebuilder:webhook:mutating-webhook-config-name=test-mutating-webhook-cfg
// +kubebuilder:webhook:validating-webhook-config-name=test-validating-webhook-cfg

在 v1 中,一个单个的 webhook 标记可能会被拆分成多个段落。但是在 v2 中,每一个 webhook 必须由一个单个的标记来表示。

其他

v1 中如果对 main.go 有任何手动更新,我们需要将修改同步至新的 main.go 中。我们还 需要确保所有需要的 schemes 已经被注册了。

如果在 config 目录下有一些额外的清单被添加进来,同样需要做同步。

如果需要的话在 Makefile 中修改镜像名字。

验证

最后,我们可以运行 makemake docker-build 来确保一些都运行正常。