Kubernetes CRD 控制器开发系列 Part 1: 初识 CRD 和 Operator 框架

文章介绍了关于 CRD controller 开发的目的、框架以及开源 kubebuilder 脚手架的简单使用。


1.Custom Resource Define

Custom Resource Define 简称 CRD,是 Kubernetes(v1.7+)为提高可扩展性,让开发者去自定义资源的一种方式。CRD 资源可以动态注册到集群中,注册完毕后,用户可以通过 kubectl 来创建访问这个自定义的资源对象,类似于操作 Pod 一样。不过需要注意的是 CRD 仅仅是资源的定义而已,需要一个对应的控制器去监听 CRD 的各种事件来添加自定义的业务逻辑。

2.YAML 文件格式

我们可以定义一个如下所示的 CRD 资源清单文件:

 1# crd-demo.yaml
 2apiVersion: apiextensions.k8s.io/v1
 3kind: CustomResourceDefinition
 4metadata:
 5  # name 必须匹配下面的spec字段:<plural>.<group>  
 6  name: crontabs.stable.example.com
 7spec:
 8  # group 名用于 REST API 中的定义:/apis/<group>/<version>  
 9  group: stable.example.com
10  # 列出自定义资源的所有 API 版本  
11  versions:
12  - name: v1beta1  # 版本名称,比如 v1、v2beta1 等等    
13    served: true  # 是否开启通过 REST APIs 访问 `/apis/<group>/<version>/...`    
14    storage: true # 必须将一个且只有一个版本标记为存储版本    
15    schema:  # 定义自定义对象的声明规范      
16      openAPIV3Schema:
17        description: Define CronTab YAML Spec
18        type: object
19        properties:
20          spec:
21            type: object
22            properties:
23              cronSpec:
24                type: string
25              image:
26                type: string
27              replicas:
28                type: integer
29  # 定义作用范围:Namespaced(命名空间级别)或者 Cluster(整个集群)  
30  scope: Namespaced
31  names:
32    # kind 是 singular 的一个驼峰形式定义,在资源清单中会使用    
33    kind: CronTab
34    # plural 名字用于 REST API 中的定义:/apis/<group>/<version>/<plural>    
35    plural: crontabs
36    # singular 名称用于 CLI 操作或显示的一个别名    
37    singular: crontab
38    # shortNames 相当于缩写形式    
39    shortNames:
40    - ct

我们在创建资源的时候,肯定不是任由我们随意去编写 YAML 文件的,当我们把上面的 CRD 文件提交给 Kubernetes 之后,Kubernetes 会对我们提交的声明文件进行校验,从定义可以看出 CRD 是基于 OpenAPI v3 schem 进行规范的。

使用 kubectl 来创建这个 CRD 资源清单:

1[root@master ~]# kubectl apply -f crd-demo.yaml
2customresourcedefinition.apiextensions.k8s.io/crontabs.stable.example.com created

然后我们就可以使用这个 API 端点来创建和管理自定义的对象,这些对象的类型就是上面创建的 CRD 对象规范中的 CronTab。 现在在 Kubernetes 集群中我们就多了一种新的资源叫 crontabs.stable.example.com,我们就可以使用它来定义一个 CronTab 资源对象了,这个自定义资源对象里面可以包含的字段我们在定义的时候通过 schema 进行了规范,比如现在我们来创建一个如下所示的资源清单:

1# crd-crontab-demo.yaml
2apiVersion: "stable.example.com/v1beta1"
3kind: CronTab
4metadata:
5  name: my-new-cron-object
6spec:
7  cronSpec: "* * * * */5"
8  image: my-awesome-cron-image

直接创建这个对象:

1[root@master ~]# kubectl apply -f crd-crontab-demo.yaml
2crontab.stable.example.com/my-new-cron-object created

我们就可以用 kubectl 来管理我们这里创建 CronTab 对象了,比如:

1[root@master ~]# kubectl get ct  # 简写
2NAME                 AGE
3my-new-cron-object   42s
4[root@master ~]# kubectl get crontab
5NAME                 AGE
6my-new-cron-object   88s

3.kubebuilder 脚手架使用

创建一个目录,然后在里面运行 kubebuilder init 命令,初始化一个新项目。

1$ cd go/src/github.com/peterliao96
2$ mkdir builder-demo
3$ cd builder-demo
4# 开启 go modules
5$ export GO111MODULE=on
6$ export GOPROXY=https://goproxy.cn
7$ kubebuilder init --domain ydzs.io --owner peterliao96 --repo github.com/peterliao96/builder-demo
8# 创建一个新的 API(组/版本)为 “webapp/v1”,并在上面创建新的 Kind(CRD) “Guestbook”
9$ kubebuilder create api --group webapp --version v1 --kind Guestbook

上面的命令会创建文件 api/v1/guestbook_types.go,该文件中定义相关 API ,而针对于这一类型 (CRD) 的业务逻辑生成在 controller/guestbook_controller.go 文件中。 我们可以根据自己的需求去修改资源对象的定义结构,修改 api/v1/guestbook_types.go 文件:

 1// api/v1/guestbook_types.go
 2package v1
 3
 4import (
 5	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 6)
 7
 8// EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!
 9// NOTE: json tags are required.  Any new fields you add must have json tags for the fields to be serialized.
10
11// GuestbookSpec defines the desired state of Guestbook
12type GuestbookSpec struct {
13	// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
14	// Important: Run "make" to regenerate code after modifying this file
15
16	// Foo is an example field of Guestbook. Edit guestbook_types.go to remove/update
17	Foo string `json:"foo,omitempty"`
18}
19
20// GuestbookStatus defines the observed state of Guestbook
21type GuestbookStatus struct {
22	// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
23	// Important: Run "make" to regenerate code after modifying this file
24}
25
26//+kubebuilder:object:root=true
27//+kubebuilder:subresource:status
28
29// Guestbook is the Schema for the guestbooks API
30type Guestbook struct {
31	metav1.TypeMeta   `json:",inline"`
32	metav1.ObjectMeta `json:"metadata,omitempty"`
33
34	Spec   GuestbookSpec   `json:"spec,omitempty"`
35	Status GuestbookStatus `json:"status,omitempty"`
36}
37
38//+kubebuilder:object:root=true
39
40// GuestbookList contains a list of Guestbook
41type GuestbookList struct {
42	metav1.TypeMeta `json:",inline"`
43	metav1.ListMeta `json:"metadata,omitempty"`
44	Items           []Guestbook `json:"items"`
45}
46
47func init() {
48	SchemeBuilder.Register(&Guestbook{}, &GuestbookList{})
49}

本文摘录于 Kubernetes 开发课文档中的 CRD介绍kubebuilder 介绍

翻译: