本指南将通过一个完整的实验,系统性地介绍使用Kubebuilder框架开发Kubernetes Operator的全过程。实验将复用已有的Operator逻辑,重点展示从项目初始化到最终部署的完整工作流,并对过程中可能遇到的问题提供解决方案。
环境准备
本次实验旨在演示Kubebuilder项目的完整构建流程,其核心业务逻辑将采用已有的开源Operator代码。
1)前置知识
- 需要具备基础的Go语言知识。
- 了解Kubernetes Operator的基本概念。
2)实验环境与版本
基础要求:
- Go 版本 v1.23.0+
- Docker 版本 17.03 或更高
- kubectl 版本 v1.11.3+
- 可访问的 Kubernetes v1.11.3+ 集群
- Linux开发环境 (Kubebuilder未提供Windows版本)
3)安装Go环境
安装Go并配置国内代理,加速依赖下载。
echo “export GO111MODULE=on” >> ~/.profile
echo “export GOPROXY=https://goproxy.cn” >> ~/.profile
source ~/.profile
4)安装Kubebuilder
从GitHub Releases页面下载对应系统的二进制包并安装。
mv kubebuilder_linux_amd64 kubebuilder && chmod +x kubebuilder && mv kubebuilder /usr/local/bin/
初始化Kubebuilder项目工程
创建工作目录
mkdir -p /opt/code/kubebuilder-zcyw-demo
cd /opt/code/kubebuilder-zcyw-demo
创建Operator项目
# 初始化Go模块
go mod init github.com/yjcadmin/kubebuilder-zcyw-demo
# 初始化Kubebuilder项目
kubebuilder init --domain zcywapp.test
# 创建自定义资源API和控制器
kubebuilder create api --group zcywapp --version v1beta1 --kind Zcywwebapp
生成的项目结构解读
Kubebuilder生成的标准项目目录结构如下,其核心开发流程围绕以下几个部分展开:
- 在
api/<version>/<kind>_types.go 中定义CRD的API结构。
- 在
internal/controller/ 目录下的控制器文件中实现 Reconcile 调和逻辑。
- 通过
Makefile 中的命令生成代码和Kubernetes配置清单。
- 使用
config/ 目录下的YAML文件将CRD和控制器部署到Kubernetes集群。
开发CRD(自定义资源定义)
设计CRD规范
CRD的设计主要通过修改 api/v1beta1/zcywwebapp_types.go 文件完成。本实验旨在实现一个能根据声明自动创建Deployment、Service和Ingress的Operator。我们定义了以下字段:
EnableIngress: 布尔值,控制是否自动创建Ingress。
EnableService: 布尔值,控制是否自动创建Service。
Replicas: 整数,控制Deployment的副本数。
Image: 字符串,指定Deployment使用的容器镜像。
修改该文件后,与之关联的 zz_generated.deepcopy.go 文件通常会报错,需要通过命令重新生成代码。
生成CRD相关代码与配置
Kubebuilder利用 controller-gen 工具,通过 make 命令自动化生成代码和配置。
make manifests: 根据 *_types.go 的更改,重新生成CRD定义、RBAC权限清单及Webhook配置等YAML文件。
make generate: 重新生成DeepCopy等客户端相关代码。修改API类型后必须执行此命令。
进入项目根目录执行:
make manifests
make generate
执行后,zz_generated.deepcopy.go 文件的报错将会消失。
安装CRD到集群
生成的CRD可以通过以下命令安装到Kubernetes集群中:
# 安装CRD定义
make install
# 创建自定义资源(CR)实例
kubectl apply -f ./config/samples/zcywapp_v1beta1_zcywwebapp.yaml
首次应用示例YAML文件可能会失败,因为其中缺少我们在 zcywwebapp_types.go 中定义的字段。需要编辑 config/samples/zcywapp_v1beta1_zcywwebapp.yaml 文件,补全 spec 下的字段(如 enableIngress, enableService, replicas, image),然后再次执行上述命令。
验证CRD安装
使用以下命令验证CRD和CR是否已成功创建:
kubectl get Zcywwebapp
kubectl get crd | grep zcywapp
开发Controller(控制器)
Controller工作原理简述
Controller遵循Kubernetes声明式API和面向期望状态(Desired State)的编程模型。其核心是监听特定资源(包括内置资源和自定义资源)的变化事件,并驱动集群实际状态向期望状态收敛。Kubebuilder框架封装了复杂的List-Watch、队列处理、缓存等机制,开发者只需专注于在 Reconcile 函数中编写业务逻辑。
解读控制器文件
业务逻辑的核心在 internal/controller/zcywwebapp_controller.go。
Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) 函数:这是控制器的核心。任何被监听的资源发生变更,都会触发此函数的调用。在这里编写创建、更新或删除Deployment、Service、Ingress等资源的逻辑。
SetupWithManager(mgr ctrl.Manager) error 函数:用于向管理器注册控制器,并设置需要监听的资源。默认会Watch自定义的 Zcywwebapp 资源,你也可以添加对其他资源(如Pod、Deployment)的监听。
编写业务逻辑代码
本实验将参考一个开源示例(https://github.com/baidingtech/operator-lesson-demo)的业务逻辑。将示例中 app_controller.go 的主要逻辑复制到本项目的 zcywwebapp_controller.go 中,并根据实际的包路径和结构体名称进行相应修改(需要一定的Go语言基础)。
修改控制器代码后,建议再次运行 make manifests 和 make generate 以确保RBAC权限等配置同步更新。
本地测试Controller
在部署前,可在本地运行控制器进行测试。
- 确保CRD和示例CR已安装。
make install
kubectl apply -f ./config/samples/zcywapp_v1beta1_zcywwebapp.yaml
- 在项目根目录前台启动控制器。
make run
观察日志,如果业务逻辑正确,控制器会根据CR中的配置,自动创建对应的Deployment和Service。如果将CR中 enableIngress 设为 true,还会自动创建Ingress资源。你可以使用 kubectl get deployment,svc,ingress 命令进行验证。
部署Controller
构建控制器镜像
首先需要确保Docker已安装。使用项目提供的Makefile目标构建镜像:
make docker-build IMG=registry.cn-chengdu.aliyuncs.com/qiuyl01/zcywapp-controller:v1.3
也可以直接使用 docker build 命令。
推送镜像到仓库
docker push registry.cn-chengdu.aliyuncs.com/qiuyl01/zcywapp-controller:v1.3
配置RBAC权限
在控制器能成功操作Deployment、Service、Ingress等资源之前,需要为其配置足够的RBAC权限。这通过在 zcywwebapp_controller.go 文件的开头添加相应的注解来实现:
//+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=networking.k8s.io,resources=ingresses,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups="",resources=services,verbs=get;list;watch;create;update;patch;delete
添加后,执行 make manifests 会将这些注解生成到 config/rbac/ 目录下的YAML文件中。
部署到Kubernetes集群
使用 make deploy 命令,它会读取 config/ 目录下的清单,并部署所有必要资源(包括CRD、RBAC角色绑定、控制器Deployment等)。
make deploy IMG=registry.cn-chengdu.aliyuncs.com/qiuyl01/zcywapp-controller:v1.3
如需卸载,可执行 make undeploy。
验证部署结果
部署完成后,再次应用你的CR示例文件:
kubectl apply -f ./config/samples/zcywapp_v1beta1_zcywwebapp.yaml
此时,Operator应作为一个Pod运行在集群中(通常位于 kubebuilder-system 这类命名空间),并会根据CR的声明自动创建和管理相关的Deployment、Service和Ingress资源。
使用Kustomize导出统一部署文件
为了让用户更容易部署你的Operator,可以将所有分散的YAML资源文件合并为一个单一文件。
安装kustomize
从GitHub Releases下载并安装kustomize。
生成all-in-one.yaml文件
在项目根目录下,执行以下命令,利用 config/default 这个kustomization配置来构建最终清单:
kustomize build config/default > all-in-one-deploy.yaml
一键部署
用户只需运行一条命令即可完成Operator的安装:
kubectl apply -f all-in-one-deploy.yaml
之后,用户再创建自定义资源实例即可使用Operator的功能。
常见问题与解决方法
-
镜像构建时文件缺失
- 现象:
docker build 时,除了 go.mod 和 go.sum,其他文件未被复制进镜像。
- 原因:项目根目录下的
.dockerignore 文件排除了这些文件。
- 解决:临时重命名或删除
.dockerignore 文件后再构建镜像。
-
执行kubebuilder create api报错
- 现象:使用较旧的Kubebuilder v3.10.0时可能报错。
- 解决:升级到更新的版本(如v4.10.1)后问题解决。
-
控制器权限不足
- 现象:部署后控制器日志报错,提示对
deployments、services 等资源没有 create、update 权限。
- 解决:确保已在控制器Go代码文件中添加了正确的
//+kubebuilder:rbac 注释,并重新执行了 make manifests 以更新RBAC配置。
-
模板文件在容器中找不到
- 现象:控制器运行时提示模板文件不存在。
- 原因:Dockerfile构建镜像时未将模板目录复制到容器内,或运行用户权限不足。
- 解决:
- 在Dockerfile中添加复制模板文件的指令:
COPY internal/controller/template/ internal/controller/template/。
- 注释掉Dockerfile中可能限制权限的
USER 65532:65532 指令。
通过以上步骤,你已经完成了使用Kubebuilder开发并部署一个基础Kubernetes Operator的完整流程。后续更复杂的业务逻辑实现,则依赖于对Go语言、Kubernetes API以及特定业务需求的深入理解。
参考资源