生成 CRD(自定义资源定义)

Kubebuilder 使用一个名为 controller-gen 的工具来生成实用代码和 Kubernetes 对象的 YAML,比如自定义资源定义(CustomResourceDefinitions)。

为此,它使用特殊的“标记注释“(以 // + 开头的注释)来指示有关字段、类型和包的附加信息。在自定义资源定义(CRD)的情况下,这些信息通常来自于你的 _types.go 文件。有关标记的更多信息,请参见 标记参考文档

Kubebuilder 提供了一个 make 目标来运行 controller-gen 并生成 CRD:make manifests

当你运行 make manifests 时,应该可以在 config/crd/bases 目录下看到生成的 CRD。make manifests 还可以生成许多其他的构件—更多细节请查看 标记参考文档

验证

CRD 支持使用 validation 部分中的 OpenAPI v3 架构 进行 声明式验证.

一般来说,验证标记可以附加到字段或类型上。如果您在定义复杂的验证、需要重用验证或需要验证切片元素,通常最好定义一个新类型来描述您的验证。

例如:

type ToySpec struct {
	// +kubebuilder:validation:MaxLength=15
	// +kubebuilder:validation:MinLength=1
	Name string `json:"name,omitempty"`

	// +kubebuilder:validation:MaxItems=500
	// +kubebuilder:validation:MinItems=1
	// +kubebuilder:validation:UniqueItems=true
	Knights []string `json:"knights,omitempty"`

	Alias   Alias   `json:"alias,omitempty"`
	Rank    Rank    `json:"rank"`
}

// +kubebuilder:validation:Enum=狮子;狼;龙
type Alias string

// +kubebuilder:validation:最小值=1
// +kubebuilder:validation:最大值=3
// +kubebuilder:validation:排除最大值=false
type Rank int32

附加打印机列

从 Kubernetes 1.11 开始,kubectl get 可以向服务器请求显示哪些列。对于自定义资源定义(CRD),这可以用于提供有用的特定类型信息,类似于内置类型所提供的信息。

显示的信息可以通过您的 CRD 上的 additionalPrinterColumns 字段 进行控制,该字段由 CRD 的 Go 类型上的 +kubebuilder:printcolumn 标记控制。

例如,在以下示例中,我们添加字段以显示有关骑士的信息,以及来自验证示例的等级和别名字段:

// +kubebuilder:printcolumn:name="别名",type=string,JSONPath=`.spec.alias`
// +kubebuilder:printcolumn:name="等级",type=integer,JSONPath=`.spec.rank`
// +kubebuilder:printcolumn:name="勇敢逃跑",type=boolean,JSONPath=`.spec.knights[?(@ == "罗宾爵士")]`,description="当危险抬起丑陋的头颅时,他勇敢地转身逃跑",priority=10
// +kubebuilder:printcolumn:name="年龄",type="日期",JSONPath=".metadata.creationTimestamp"
type Toy struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   ToySpec   `json:"spec,omitempty"`
	Status ToyStatus `json:"status,omitempty"`
}

子资源

从 Kubernetes 1.13 开始,CRDs 可以选择实现 /status/scale 子资源

一般建议您在所有具有状态字段的资源中使用 /status 子资源。

两个子资源都有相应的 标记.

状态

状态子资源是通过 +kubebuilder:subresource:status 启用的。当启用时,主资源的更新不会更改状态。同样,状态子资源的更新只能更改状态字段,不能更改其他内容。

例如:

// +kubebuilder:subresource:status
type Toy struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   ToySpec   `json:"spec,omitempty"`
	Status ToyStatus `json:"status,omitempty"`
}

规模

通过 +kubebuilder:subresource:scale 启用 scale 子资源。启用后,用户将能够使用 kubectl scale 命令来缩放您的资源。如果 selectorpath 参数指向标签选择器的字符串形式,则水平 Pod 自动扩缩器 (HorizontalPodAutoscaler) 将能够对您的资源进行自动扩缩。

例如:

type CustomSetSpec struct {
	Replicas *int32 `json:"replicas"`
}

type CustomSetStatus struct {
	Replicas int32 `json:"replicas"`
    Selector string `json:"selector"` // this must be the string form of the selector
}


// +kubebuilder:subresource:status
// +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas,selectorpath=.status.selector
type CustomSet struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   CustomSetSpec   `json:"spec,omitempty"`
	Status CustomSetStatus `json:"status,omitempty"`
}

多个版本

从 Kubernetes 1.13 开始,您可以在 CRD 中定义多个版本的 Kind,并使用一个 webhook 在它们之间进行转换。

有关此过程的更多详细信息,请参见 多版本教程

默认情况下,Kubebuilder 禁用了为 CRD 中的 Kind 不同版本生成不同的验证,以便与旧版本的 Kubernetes 兼容。

如果使用 v1beta CRD,您需要将 makefile 中的 CRD_OPTIONS ?= "crd:trivialVersions=true,preserveUnknownFields=false 这一行更改为 CRD_OPTIONS ?= crd:preserveUnknownFields=false;如果使用 v1(推荐),则更改为 CRD_OPTIONS ?= crd

然后,您可以使用 +kubebuilder:storageversion 标记 来指示 API 服务器应该使用的用于存储数据的 GVK

在内部实现上

Kubebuilder 自动生成用于运行 controller-gen 的 make 规则。该规则会使用 Go 模块通过 go install 自动安装 controller-gen,如果它不在您的路径中。

如果你想查看 controller-gen 的具体操作,也可以直接运行它。

每个 controller-gen 的“生成器“都由 controller-gen 的一个选项控制,使用与标记相同的语法。controller-gen 还支持不同的输出“规则“,以控制输出的方式和去向。请注意 manifests 制作规则(略微简化,仅生成 CRD):

# 为 CRD 生成清单
manifests: controller-gen
	$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=配置/CRD/基础

它使用 output:crd:artifacts 输出规则来指示与 CRD 相关的配置(非代码)工件应最终放在 config/crd/bases 中,而不是 config/crd

要查看包括生成器在内的所有 controller-gen 选项,请运行

$ controller-gen -h

或者,欲了解更多详情:

$ controller-gen -hhh