环境准备
本次实验将采用已有的Operator代码逻辑进行套用,从而完整演示从零开始使用Kubebuilder开发一个Operator的完整流程。
1)前置知识
- 需要有 Go 语言基础。
- 了解什么是K8s 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/
初始化 kububuilder 项目工程
创建工作目录
mkdir -p /opt/code/kubebuilder-zcyw-demo
cd /opt/code/kubebuilder-zcyw-demo
创建一个 Operator 项目
# 创建 mod
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/zcywwebapp_types.go 定义 CRD 的 API 结构;
- 在
internal/controller/*_controller.go 实现 Reconcile 调和逻辑;
- 通过
Makefile 生成代码、配置;
- 通过
config/ 目录的 YAML 将 CRD 和控制器部署到 Kubernetes 集群中运行。
开发 CRD
设计 CRD
设计 CRD 主要是修改 zcywwebapp_types.go 文件,根据自己的 Operator 要实现的功能定义属性字段。
本示例旨在通过一个CRD资源自动创建Deployment,并可选择是否自动创建Service和Ingress。定义如下字段:
EnableIngress: 是否自动创建 Ingress
EnableService: 是否自动创建 Service
Replicas: 控制 Deployment 副本数
Image: 控制 Deployment 的镜像
修改文件后,相关的生成代码 zz_generated.deepcopy.go 会报错,需要通过命令重新生成。
生成 CRD 相关代码
通过make命令生成必要的代码和配置文件。
cd /opt/code/kubebuilder-zcyw-demo
# 生成Kubernetes清单文件、CRD、RBAC等配置
make manifests
# 生成客户端、DeepCopy等代码
make generate

安装 CRD
将生成的CRD安装到Kubernetes集群中。
cd /opt/code/kubebuilder-zcyw-demo
# 将 CRD 安装到 Kubernetes 集群
make install
# 运行自定义的 CR 资源
kubectl apply -f ./config/samples/zcywapp_v1beta1_zcywwebapp.yaml
首次运行CR示例时可能会因字段不匹配报错,需要按zcywwebapp_types.go中的定义,补充config/samples/zcywapp_v1beta1_zcywwebapp.yaml文件中的字段。

补充后再次执行安装命令。
验证 CRD
查看自定义的CRD和CR资源是否创建成功。
kubectl get Zcywwebapp
kubectl get crd | grep zcywapp

开发 Controller
Operator的核心是控制器(Controller),它负责监听自定义资源的变化并执行相应的业务逻辑,这是云原生应用扩展的常见模式。
Controller 工作原理
Controller 基于“面向期望状态”的编程模型工作。

工作流程简述:监听资源变化 -> 事件入队 -> 从本地缓存获取对象 -> 执行Reconcile调和逻辑,使当前状态向期望状态收敛。
解读 *_controller.go 文件
业务逻辑编写主要在 internal/controller/zcywwebapp_controller.go 文件中。
Reconcile 方法:这是控制器的核心,任何被监听资源的变化都会触发此方法,业务逻辑在此编写。
SetupWithManager 方法:用于向管理器(Manager)注册控制器,并设置需要监听的资源类型(如自定义CRD、Pod、Deployment等)。
编写业务逻辑代码
参考已有的开源Operator逻辑(如 baidingtech/operator-lesson-demo 中的app_controller.go),将其复制到本项目的zcywwebapp_controller.go中,并根据项目结构(如包名、资源类型名)进行适当修改。
编写完成后,需再次生成代码和清单。
make manifests
make generate
测试 Controller
确保CRD和CR已安装,然后在本地运行控制器进行测试。
cd /opt/code/kubebuilder-zcyw-demo
make install
kubectl apply -f ./config/samples/zcywapp_v1beta1_zcywwebapp.yaml
# 前台启动控制器
make run

观察日志及集群,检查是否根据CR的配置自动创建了Deployment、Service和Ingress。

部署 Controller
本地测试通过后,将控制器打包为镜像并部署到集群。
构建与推送镜像
make docker-build IMG=registry.cn-chengdu.aliyuncs.com/qiuyl01/zcywapp-controller:v1.3
docker push registry.cn-chengdu.aliyuncs.com/qiuyl01/zcywapp-controller:v1.3
部署
在控制器代码文件中添加操作Deployment、Service、Ingress所需的RBAC注解。
//+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
执行部署命令,将CRD和控制器Pod部署到集群。
make deploy IMG=registry.cn-chengdu.aliyuncs.com/qiuyl01/zcywapp-controller:v1.3

验证
应用CR示例,验证部署的Operator功能是否正常。
kubectl apply -f ./config/samples/zcywapp_v1beta1_zcywwebapp.yaml
检查集群中是否自动创建了对应的Deployment、Service等资源。
使用 Kustomize 导出部署文件
为简化用户部署流程,可以将所有部署资源整合为单个YAML文件。
1)安装 kustomize
从 GitHub Releases 下载。
2)生成整合的部署文件
kustomize build config/default > all-in-one-deploy.yaml
3)使用整合文件部署
kubectl apply -f all-in-one-deploy.yaml
这种方式属于 DevOps 中常见的应用打包和部署实践,便于分发和版本管理。
过程中出现的问题与解决方法
-
镜像构建时文件缺失
- 问题:Docker构建时,除了
go.mod和go.sum外的文件未复制到镜像中。
- 解决:检查并临时重命名或修改项目根目录下的
.dockerignore文件。
-
执行kubebuilder create api报错
- 问题:使用了较旧的Kubebuilder版本(v3.10.0)。
- 解决:升级到最新的稳定版本(如v4.10.1)后执行成功。
-
权限不足错误
- 问题:控制器运行时缺乏对Deployment、Service等资源的操作权限。
- 解决:在
*_controller.go文件中为Reconcile方法添加对应的RBAC注解(如上文所示),并重新执行make manifests生成RBAC配置。
-
模板文件找不到
- 问题:控制器代码依赖的模板文件在容器中不存在。
- 解决:在Dockerfile中添加COPY指令,将模板目录复制到镜像内;若出现权限问题,可暂时注释掉
USER 65532:65532指令。
参考