Kubebuilder 入门上手
Kubebuilder 是由 Kubernetes SIG API Machinery 官方维护的 Controller / Operator 开发脚手架,官方文档
背景与定位
在 Kubebuilder 出现之前,开发 K8s Controller 需要直接使用 client-go,手动搭建 Informer、WorkQueue、LeaderElection 等基础设施,样板代码量极大,且缺乏统一的项目结构规范。
Kubebuilder 解决了这两个问题:
- 底层:将 client-go 的复杂性封装进 controller-runtime,提供 Manager、Reconciler、Client、Cache 等高层抽象
- 上层:提供 CLI 脚手架,一条命令生成符合社区规范的项目结构、CRD 定义、RBAC 清单、Dockerfile、Makefile
三者的关系:
Kubebuilder CLI(脚手架)
↓ 生成项目骨架,引入
controller-runtime(框架库)
↓ 封装
client-go(K8s 官方 Go 客户端)
↓ 调用
K8s API Server
架构概览
下图展示了 Kubebuilder 各核心概念之间的关系(来源:Kubebuilder Book — Architecture):
整体可以分为三个层次:
用户代码层(Kubebuilder 脚手架生成)
| 组件 | 说明 |
|---|---|
| Types / CRD | 用 Go struct 定义自定义资源的 Spec 和 Status,make manifests 生成对应 CRD YAML |
| Reconciler | 业务逻辑实现,接收触发事件后对比期望状态与实际状态并驱动收敛 |
| Webhook | 可选,在资源写入 API Server 前做 Defaulting(补全默认值)或 Validation(合法性校验) |
框架层(controller-runtime)
| 组件 | 说明 |
|---|---|
| Manager | 整个进程的运行容器,统一管理 Cache、Client、Controller、Webhook Server 的生命周期,并负责 Leader Election |
| Cache(Informer) | 基于 client-go Informer 实现的本地缓存,通过 List/Watch 与 API Server 保持同步;Read 操作走 Cache,不直接打 API Server |
| Controller | 订阅 Cache 的变化事件,将触发的对象 key 压入 WorkQueue,再由 Reconciler 逐一消费 |
| Client | 对 K8s API 的高层封装:读操作默认走 Cache,写操作(Create / Update / Delete)直接调用 API Server |
| Webhook Server | 嵌入 Manager 的 HTTP(S) 服务,承接 API Server 发来的 AdmissionReview 请求 |
K8s 控制面层
| 组件 | 说明 |
|---|---|
| API Server | 所有资源变更的入口;Informer 通过 Watch 接口与之保持长连接,Webhook 请求也由其发出 |
| etcd | K8s 持久化存储,所有资源对象的最终落点 |
事件驱动流程:
API Server(资源变更)
↓ Watch 事件
Cache / Informer(本地缓存更新)
↓ 触发事件处理器
Controller WorkQueue(入队 NamespacedName)
↓ 消费
Reconciler.Reconcile()
├── r.Client.Get() → 读 Cache
├── 对比期望 vs 实际
└── r.Client.Update() → 写 API Server → 回到顶部
版本演变
| 大版本 | 发布时间 | 核心变化 |
|---|---|---|
| v1 | 2018 | 初代版本,项目结构较原始,直接依赖 client-go,无 controller-runtime |
| v2 | 2019 | 引入 controller-runtime,重构项目结构,统一 Reconciler 接口,奠定现代 Controller 开发模式 |
| v3 | 2021 | 引入插件系统(Plugin),支持多 Group API,脚手架可扩展性大幅提升 |
| v4 | 2023 | 当前主力版本。要求 Go 1.21+,移除废弃 API,优化脚手架生成内容,与 controller-runtime v0.17+ 对齐 |
v1 和 v2 已停止维护,新项目请直接使用 v4。v3 仍有历史文档可查:legacy docs。
版本兼容性
Kubebuilder、controller-runtime、K8s 三者版本紧密绑定。controller-runtime 遵循每个 K8s 次版本发一个次版本的策略(k8s.io/* v0.N 对应 K8s 1.N)。
controller-runtime 与 K8s / Go 的兼容矩阵:
| controller-runtime | K8s 版本 | 最低 Go 版本 |
|---|---|---|
| v0.24 | 1.36 | 1.26 |
| v0.23 | 1.35 | 1.25 |
| v0.22 | 1.34 | 1.24 |
| v0.21 | 1.33 | 1.24 |
| v0.20 | 1.32 | 1.23 |
| v0.19 | 1.31 | 1.22 |
| v0.18 | 1.30 | 1.22 |
| v0.17 | 1.29 | 1.21 |
Kubebuilder 与 controller-runtime 的对应关系:
| Kubebuilder | controller-runtime | K8s | Go |
|---|---|---|---|
| v4.x(当前) | v0.17 ~ v0.24 | 1.29+ | 1.21+ |
| v3.x | v0.14 ~ v0.16 | 1.26 ~ 1.28 | 1.17+ |
| v2.x | v0.8 ~ v0.13 | 1.14 ~ 1.25 | 1.13+ |
新项目选 Kubebuilder v4 + controller-runtime 最新次版本,与目标集群的 K8s 次版本对齐即可。例如集群是 K8s 1.31,选 controller-runtime v0.19,Go ≥ 1.22。
核心概念
K8s 资源标识:GVK 与 GVR
在 K8s 中,每种资源都由 GVK(Group / Version / Kind)唯一标识,而在 API 路径中则用 GVR(Group / Version / Resource)表示。
| 字段 | 含义 | 示例 |
|---|---|---|
| Group | API 组,core 组资源(Pod、Service)使用空字符串 "" | apps、batch、"" |
| Version | API 版本 | v1、v1beta1、v1alpha1 |
| Kind | 资源类型,单数形式 | Deployment、Pod |
| Resource | API 路径中的资源名,复数形式 | deployments、pods |
以一个 Deployment 为例:
apiVersion: apps/v1 # Group=apps, Version=v1
kind: Deployment # Kind=Deployment,Resource=deployments
GVK vs GVR 的使用场景:
- GVK:用于 Controller、Scheme 注册、代码中操作资源类型时
- GVR:用于动态客户端(
dynamic.Client)、kubectl、REST API 路径中
框架核心组件
| 概念 | 说明 |
|---|---|
| Manager | 整个 Controller 的运行容器,负责 Leader Election、缓存、客户端、信号处理 |
| Reconciler | 业务逻辑入口,实现 Reconcile(ctx, req) 接口,每次 Watch 到变化时被调用 |
| Client | 与 K8s API Server 交互,支持 Get / List / Create / Update / Delete |
| Cache | 本地缓存(基于 Informer),Watch 对象变化触发事件,Read 操作走缓存不直接打 API Server |
| Scheme | 类型注册表,把 Go struct 和 K8s GVK 关联起来 |
安装
brew 只提供最新版,需要精确匹配 K8s 版本时推荐直接下载二进制(见上方兼容矩阵找对应版本)。
下载指定版本(推荐):
# 自动识别架构,替换 VERSION 为目标版本,如 v4.1.1(对应 K8s 1.30)
VERSION=v4.1.1
ARCH=$(uname -m | sed 's/x86_64/amd64/')
curl -L -o kubebuilder \
"https://github.com/kubernetes-sigs/kubebuilder/releases/download/${VERSION}/kubebuilder_darwin_${ARCH}"
chmod +x kubebuilder
sudo mv kubebuilder /usr/local/bin/
brew 安装最新版:
brew install kubebuilder
验证:
kubebuilder version
Go 版本要求 ≥ 1.21(建议与目标 controller-runtime 版本对齐,见上方兼容矩阵)。
初始化项目
mkdir my-controller && cd my-controller
kubebuilder init \
--domain example.com \ # 资源 Group 的域名后缀,CRD Group 格式为 <group>.<domain>
# 例如 domain=jaco.live,group=core → apps.jaco.live
# 无 CRD 的项目此参数仅影响命名,填公司域名即可
--repo github.com/example/my-controller # Go module 路径,对应 go.mod 的 module 字段
# 填 GitLab/GitHub 实际仓库路径
生成的项目结构:
my-controller/
├── cmd/
│ └── main.go # Manager 启动入口
├── internal/
│ └── controller/ # Reconciler 实现放这里
├── config/ # RBAC、Deployment 等 K8s 清单
├── Makefile # make run / make docker-build / make deploy
├── Dockerfile
└── go.mod
生成 Controller
有 CRD 的场景
kubebuilder create api \
--group apps \ # API Group,最终 CRD 的 group 为 <group>.<domain>,如 apps.example.com
--version v1alpha1 \ # API Version,新资源建议从 v1alpha1 开始,稳定后升到 v1beta1/v1
--kind MyApp \ # 资源类型名,单数大驼峰,对应 YAML 里的 kind 字段
--controller=true \ # 同时生成 Reconciler 骨架文件
--resource=true # 生成 CRD types 定义文件(api/<version>/<kind>_types.go)
执行后会生成:
api/v1alpha1/myapp_types.go— CRD 的 Go struct 定义internal/controller/myapp_controller.go— Reconciler 骨架