前言
kubebuilder是一个快速实现kubernetes Operator的框架,通过kubebuilder我们能够快速定义CRD资源和实现controller逻辑。我们可以简单地将operator理解为:operator=crd+controller。
kubebuilder自身携带了两个工具:controller-runtime与controller-tools,我们可以通过controller-tools来生成大部分的代码,从而我们可以将我们的主要精力放置在CRD的定义和编写controller的reconcile逻辑上。所谓的reconcile,即调谐,是指将资源的status通过一系列的操作调整至与定义的spec一致。
从整体来看,通过kubebuilder来实现operator大致可分为以下步骤:
- 创建工作目录,初始化项目
- 创建API,填充字段
- 创建Controller,编写核心调谐逻辑(Reconcile)
- 创建Webhook,实现接口(可选)
- 验证测试
- 发布到集群中
最佳实践
我们以创建一个mysql的operator来作为最佳实践的例子。我们期望这个mysql-operator能够实现deployment创建和更新,以及mysql实例数的扩缩容。
环境准备
组件检查
确保实践环境中拥有以下组件:
- go version v1.15+.
- docker version 17.03+.
- kubectl version v1.11.3+.
- kustomize v3.1.0+
- 能够访问 Kubernetes v1.11.3+ 集群
安装kubebuilder
curl -L -o kubebuilder https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH)
chmod +x kubebuilder && mv kubebuilder /usr/local/bin/
创建项目
初始化项目
kubebuilder init --domain tutorial.kubebuilder.io
创建kubebuilder项目之前必须要先有go project,否则会报错。
创建完成之后,我们可以看到此时项目中多了许多的代码,其中:
- go.mod: 我们的项目的 Go mod 配置文件,记录依赖库信息。
- Makefile: 用于控制器构建和部署的 Makefile 文件
- PROJECT: 用于生成组件的 Kubebuilder 元数据
创建API
kubebuilder create api --group batch --version v1 --kind Mysql
Create Resource [y/n]
y
Create Controller [y/n]
y
编写CRD资源
编写CRD资源的定义主要是在mysql_types.go文件中,编写controller逻辑主要是在mysql_controller.go文件中。
我们首先编写CRD的定义。我们简单地用一个yaml文件来描述我们所期望的定义:
apiVersion: batch.tutorial.kubebuilder.io/v1
kind: Mysql
metadata:
name: mysql-sample
spec:
replicas: 1
image: flyer103/mysql:5.7
command: [ "/bin/bash", "-ce", "tail -f /dev/null" ]
我们需要在mysql_types.go文件中定义我们的spec和status。
定义spec
// MysqlSpec defines the desired state of Mysql
type MysqlSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
Name string `json:"name,omitempty"`
Image string `json:"image,omitempty"`
Command []string `json:"command,omitempty" protobuf:"bytes,3,rep,name=command"`
// +optional
//+kubebuilder:default:=1
//+kubebuilder:validation:Minimum:=1
Replicas *int32 `json:"replicas,omitempty" protobuf:"varint,1,opt,name=replicas"`
}
定义status
我们在这里针对code重新定义了string类型。
type MySqlCode string
const (
SuccessCode MySqlCode = "success"
FailedCode MySqlCode = "failed"
)
// MysqlStatus defines the observed state of Mysql
type MysqlStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
Code MySqlCode `json:"code,omitempty"`
Replicas int32 `json:"replicas"`
ReadyReplicas int32 `json:"readyReplicas"`
}
添加kubectl展示参数标记
像 //+kubebuilder:object:root
这样的以//+
开头的注释在kubebuilder
中被称为元数据标记,这些标记的作用就是告诉controller-tools生成额外的信息。
//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas,selectorpath=.status.labelSelector
//+kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.code",description="The phase of game."
//+kubebuilder:printcolumn:name="DESIRED",type="integer",JSONPath=".spec.replicas",description="The desired number of pods."
//+kubebuilder:printcolumn:name="CURRENT",type="integer",JSONPath=".status.replicas",description="The number of currently all pods."
//+kubebuilder:printcolumn:name="READY",type="integer",JSONPath=&