生成 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 支持使用 OpenAPI v3 schema 在 validation 段中进行声明式验证。
通常,验证标记可能会关联到字段或者类型。如果你定义了复杂的验证,或者如果你需要重复使用验证,亦或者你需要验证切片元素,那么通常你最好定义一个新的类型来描述你的验证。
例如:
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=Lion;Wolf;Dragon
type Alias string
// +kubebuilder:validation:Minimum=1
// +kubebuilder:validation:Maximum=3
// +kubebuilder:validation:ExclusiveMaximum=false
type Rank int32
打印其它信息列
从 Kubernetes 1.11 开始,kubectl get 可以询问 Kubernetes 服务要展示哪些列。对于 CRD 来说,可以用 kubectl get 来提供展示有用的特定类型的信息,类似于为内置类型提供的信息。
你 CRD 的 [additionalPrinterColumns 字段][kube-additional-printer-columns] 控制了要展示的信息,它是通过在给 CRD 的 Go 类型上标注 +kubebuilder:printcolumn 标签来控制要展示的信息。
比如下面的验证例子,我们添加字段来显示 knights,rank 和 alias 字段的信息
// +kubebuilder:printcolumn:name="Alias",type=string,JSONPath=`.spec.alias`
// +kubebuilder:printcolumn:name="Rank",type=integer,JSONPath=`.spec.rank`
// +kubebuilder:printcolumn:name="Bravely Run Away",type=boolean,JSONPath=`.spec.knights[?(@ == "Sir Robin")]`,description="when danger rears its ugly head, he bravely turned his tail and fled",priority=10
// +kubebuilder:printcolumn:name="Age",type="date",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 中 CRD 可以选择实现 /status 和 /scale 这类子资源。
通常推荐你在所有资源上实现 /status 子资源的时候,要有一个状态字段。
两个子资源都有对应的[标签][crd markers]。
状态
通过 +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 来启用。启用后,用户可以使用 kubectl scale 来对你的资源进行扩容或者缩容。如果 selectorpath 参数被指定为字符串形式的标签选择器,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 的不同版本产生不同的验证,这都是为了兼容老版本的 Kubernetes。
如果需要,你要通过修改 makefile 中的命令:把 CRD_OPTIONS ?= "crd:trivialVersions=true 修改为 CRD_OPTIONS ?= crd。
这样,你就可以使用 +kubebuilder:storageversion 标签 来告知 GVK 这个字段应该被 API 服务来存储数据。
写在最后
KubeBuilder 会制定规则来运行 controller-gen。如果 controller-gen 不在 go get 用来下载 Go 模块的路径下的时候,这些规则会自动的安装 controller-gen。
如果你想知道它到底做了什么,你也可以直接运行 controller-gen。
每一个 controller-gen “生成器” 都由 controller-gen 的一个参数选项控制,和标签的语法一样。比如,要生成带有 “trivial versions” 的 CRD(无版本转换的 webhook),我们可以执行 controller-gen crd:trivialVersions=true paths=./api/...。
controller-gen 也支持不同的输出“规则”,以此来控制如何及输出到哪里。注意 manifests 生成规则(是只生成 CRD 的简短写法):
# 生成 CRD 清单
manifests: controller-gen
$(CONTROLLER_GEN) crd:trivialVersions=true paths="./..." output:crd:artifacts:config=config/crd/bases
它使用了 output:crd:artifacts 输出规则来表示 CRD 关联的配置(非代码)应该在 config/crd/bases 目录下,而不是在 config/crd 下。
运行如下命令可以看到 controller-gen 的所有支持参数:
$ controller-gen -h
或者,可以执行以下命令,获取更多详细信息:
$ controller-gen -hhh
