生成 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