KubeBuilder 简明教程
安装
访问官方仓库下载已经编译好的二进制文件: Releases · kubernetes-sigs/kubebuilder (github.com)
- 本文编写的时候 kubebuilder 已经推出了 v3.0.0-rc.0 版本,所以为了避免刚写完新版就已经 release 了的尴尬情况,本文直接使用的是 3.0 版本
- 下载好了之后记得将对应文件加入 PATH 当中
安装成功之后使用 kubebuilder version 可以查看安装的版本信息
- ❯ kubebuilder version
- Version: main.version{KubeBuilderVersion:"3.0.0-rc.0", KubernetesVendor:"1.19.2", GitCommit:"90fe4124c4c6965c6bfac63339888956952cda90", BuildDate:"2021-04-08T17:36:28Z", GoOs:"linux", GoArch:"amd64"}
项目初始化
先创建一个空文件夹,然后在文件夹内执行下方命令
- kubebuilder init –domain lailin.xyz –repo github.com/mohuishou/blog-code/k8s-operator/02-kubebuilder
- –-domain lailin.xyz 我们的项目的域名
- –repo xxx 是仓库地址,同时也是 go mode中的repo地址
如果你 golang 版本过低或者过高都有可能出现下方的错误信息,我这里是因为使用的 1.16 版本太高了
- 2021/04/25 20:47:14 failed to initialize project: unable to run pre-scaffold tasks of "base.go.kubebuilder.io/v3": go version 'go1.16' is incompatible because 'requires 1.13 <= version < 1.16'. You can skip this check using the –skip-go-version-check flag
这种情况下可以添加 –skip-go-version-check 忽略这个错误,但是还是建议使用官方推荐的版本
- kubebuilder init –domain lailin.xyz –repo github.com/mohuishou/blog-code/k8s-operator/02-kubebuilder –skip-go-version-check
项目目录
- .
- ├── Dockerfile
- ├── Makefile # 这里定义了很多脚本命令,例如运行测试,开始执行等
- ├── PROJECT # 这里是 kubebuilder 的一些元数据信息
- ├── config
- │ ├── default # 一些默认配置
- │ ├── manager # 部署 crd 所需的 yaml
- │ ├── prometheus # 监控指标数据采集配置
- │ └── rbac # 部署所需的 rbac 授权 yaml
- ├── go.mod
- ├── go.sum
- ├── hack
- │ └── boilerplate.go.txt
- └── main.go
创建 api
- kubebuilder create api –group apps –version v1 –kind Application
执行之后我们可以发现项目结构发生了一些变化
- .
- ├── api
- │ └── v1
- │ ├── application_types.go # 这里是定义 spec 的地方
- │ ├── groupversion_info.go # GV 的定义,一般无需修改
- │ └── zz_generated.deepcopy.go
- ├── config
- │ ├── crd # 自动生成的 crd 文件,不用修改这里,只需要修改了 v1 中的 go 文件之后执行 make generate 即可
- │ ├── default
- │ ├── manager
- │ ├── prometheus
- │ ├── rbac
- │ └── samples # 这里是 crd 示例文件,可以用来部署到集群当中
- ├── controllers
- │ ├── application_controller.go # 在这里实现 controller 的逻辑
- │ └── suite_test.go # 这里写测试
实现 Controller
定义 CR
- // api/v1/application_types.go
- // ApplicationSpec defines the desired state of Application
- type ApplicationSpec struct {
- // INSERT ADDITIONAL SPEC FIELDS – desired state of cluster
- // Important: Run "make" to regenerate code after modifying this file
- // Product 该应用所属的产品
- Product string `json:"product,omitempty"`
- }
修改之后我们执行一下 make manifests generate 可以发现已经生成了相关的字段,并且代码中的字段注释也就是 yaml 文件中的注释
- # config/crd/bases/apps.lailin.xyz_applications.yaml
- ……
- properties:
- product:
- description: Product 该应用所属的产品
- type: string
- ……
实现 controller
kubebuilder 已经帮我们实现了 Operator 所需的大部分逻辑,我们只需要在 Reconcile 中实现业务逻辑就行了
- // controllers/application_controller.go
- func (r *ApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
- _ = r.Log.WithValues("application", req.NamespacedName)
- r.Log.Info("app changed", "ns", req.Namespace)
- return ctrl.Result{}, nil
- }
逻辑修改好之后,我们先执行 make install 安装 CRD,然后执行 make run运行 controller
- go run ./main.go
- 2021-04-25T21:55:55.578+0800 INFO controller-runtime.metrics metrics server is starting to listen {"addr": ":8080"}
- 2021-04-25T21:55:55.579+0800 INFO setup starting manager
- 2021-04-25T21:55:55.579+0800 INFO controller-runtime.manager starting metrics server {"path": "/metrics"}
- 2021-04-25T21:55:55.579+0800 INFO controller-runtime.manager.controller.application Starting EventSource {"reconciler group": "apps.lailin.xyz", "reconciler kind": "Application", "source": "kind source: /, Kind="}
- 2021-04-25T21:55:55.680+0800 INFO controller-runtime.manager.controller.application Starting Controller {"reconciler group": "apps.lailin.xyz", "reconciler kind": "Application"}
- 2021-04-25T21:55:55.680+0800 INFO controller-runtime.manager.controller.application Starting workers {"reconciler group": "apps.lailin.xyz", "reconciler kind": "Application", "worker count": 1}
然后我们部署一个测试的 crd kubectl apply -f config/samples/apps_v1_application.yaml
- apiVersion: apps.lailin.xyz/v1
- kind: Application
- metadata:
- name: application-sample
- spec:
- # Add fields here
- product: test
然后可以看到之前写的日志逻辑已经触发
- 2021-04-25T21:57:12.618+0800 INFO controllers.Application app changed {"ns": "default"}
Kubebuilder 注释
在生成的代码当中我们可以看到很多 //+kubebuilder:xxx 开头的注释,对 Go 比较熟悉的同学应该知道这些注释是给对应的代码生成器服务的,在 Go 中有一个比较常用的套路就是利用 go gennerate生成对应的 go 代码。
kubebuilder 使用 controller-gen 生成代码和对应的 yaml 文件,这其中主要包含 CRD 生成、验证、处理还有 WebHook 的 RBAC 的生成功能,下面我简单介绍一下,完整版可以看 kubebuilder 的官方文档
CRD 生成
- //+kubebuilder:subresource:status 开启 status 子资源,添加这个注释之后就可以对 status进行更新操作了
- //+groupName=nodes.lailin.xyz 指定 groupname
- //+kubebuilder:printcolumn 为 kubectl get xxx 添加一列,这个挺有用的
- ……
CRD 验证,利用这个功能,我们只需要添加一些注释,就给可以完成大部分需要校验的功能
-
//+kubebuilder:default:=
给字段设置默认值 - //+kubebuilder:validation:Pattern:=string 使用正则验证字段
- ……
Webhook
- //+kubebuilder:webhook 用于指定 webhook 如何生成,例如我们可以指定只监听 Update 事件的 webhook
RBAC 用于生成 rbac 的权限
- //+kubebuilder:rbac