Kubernetes 自定义控制器用于处理核心资源。然而,这些核心资源是不可编辑的。在许多情况下,您会希望引入您自己的资源,并且您可以完全控制它。 CRD(自定义资源定义)正是为此而设计的。创建的每个 CRD 资源都有很多样板代码。为了避免这种情况,可以使用 k8s.io/code-generator 自动生成 CRD 工作所需的所有informaer程序、listers程序等。
kubernetes/code-generator
is synced from k8s.io/code-generator
. Code changes are made in that location, merged into k8s.io/kubernetes
and later synced back to kubernetes/code-generator
.
下面我们演示怎么利用Kubernetes code-generator快速创建kubernetes CRD资源。
首先,假设我们要创建一个属于Group foo.com的 CRD,并且规范中有一个名为Kind “HelloType”的类型,其中包含“message”字段:hello world.如下所示:
# Definition --- apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: hellotypes.foo.com spec: group: foo.com version: v1 scope: Namespaced names: kind: HelloType shortNames: ht plural: hellotypes singular: hellotype# HelloType --- apiVersion: foo.com/v1 kind: HelloType metadata: name: superman-hello spec: message: hello world
生成此 CRD 资源代码,涉及2个步骤: 使用正确的代码生成器tag编写type定义代码 运行代码生成器自动创建客户代码,其中包括客户资源的clientset, informers和listers。
1、定义CRD type
创建一个名为 code-generator-demo 目录。我们将创建的框架文件的布局如下:
pkg/ ├── apis └── foo └── v1 ├── doc.go ├── register.go └── types.go
foo 是正在定义的新资源组,其下所有类型都属于foo.com。
如果资源版本低于1.0.0,则v1下的所有代码都可以放在foo目录下。任何其他版本,按照约定,在 foo 下创建一个单独的目录,例如 v1、v1beta1、v2。在此示例中,我们将为自定义资源创建版本v1。 foo/v1/doc.go
// +k8s:deepcopy-gen=package
// +k8s:defaulter-gen=TypeMeta
// +groupName=foo.compackage v1
另外两个标签表示为 struct TypeMeta 生成默认值并将组名称设置为“foo.com”。 foo/v1/types.go
package v1
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object// HelloType is a top-level type
type HelloType struct {
metav1.TypeMeta `json:",inline"`
// +optional
metav1.ObjectMeta `json:"metadata,omitempty"`
// +optional
Status HelloTypeStatus `json:"status,omitempty"`
// This is where you can define
// your own custom spec
Spec HelloSpec `json:"spec,omitempty"`
}// custom spec
type HelloSpec struct {
Message string `json:"message,omitempty"`
}// custom status
type HelloTypeStatus struct {
Name string
}// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// no client needed for list as it's been created in above
type HelloTypeList struct {
metav1.TypeMeta `json:",inline"`
// +optional
metav1.ListMeta `son:"metadata,omitempty"`Items []HelloType `json:"items"`
}
创建自定义类型“HelloType”。我们还定义自定义状态和规格。任何自定义类型还必须具有复数结构。在本例中,我们有“HelloTypeList”。
+可选表示该字段是可选的。该字段的数据可以为空。 foo/v1/register.go
package v1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)// Define your schema name and the version
var SchemeGroupVersion = schema.GroupVersion{
Group: "foo.com",
Version: "v1",
}var (
SchemeBuilder runtime.SchemeBuilder
localSchemeBuilder = &SchemeBuilder
AddToScheme = localSchemeBuilder.AddToScheme
)func init() {
// We only register manually written functions here. The registration of the
// generated functions takes place in the generated files. The separation
// makes the code compile even when the generated files are missing.
localSchemeBuilder.Register(addKnownTypes)
}// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(
SchemeGroupVersion,
&HelloType{},
&HelloTypeList{},
)scheme.AddKnownTypes(
SchemeGroupVersion,
&metav1.Status{},
)metav1.AddToGroupVersion(
scheme,
SchemeGroupVersion,
)return nil
}
好了,上面代码准备就绪,执行Go Modules。
go mod init code-generator-demo
go mod tidy
generate-groups.sh all "code-generator-demo/pkg/client" "code-generator-demo/pkg/apis" foo:v1
准备Dockerfile文件:
上述选项之一完成代码生成后,您的 pkg 文件夹结构将类似于:
pkg/ ├── apis │ └── foo │ ├── register.go │ └── v1 └── client ├── clientset │ └── versioned ├── informers │ └── externalversions └── listers └── foo
新创建的client文件夹包含所有生成的代码,类型的深层复制代码也将驻留在类型旁边的 v1 中。 恭喜您,您可以使用生成的clientset、自定义控制器的informers,就像通常使用kubernetes内部核心资源一样使用。
Reference: