kubebuilder 实战
完整项目开发流程
bash
# 1. 初始化项目
mkdir myapp-operator && cd myapp-operator
go mod init github.com/mycompany/myapp-operator
kubebuilder init --domain mycompany.io --repo github.com/mycompany/myapp-operator
# 2. 创建 API
kubebuilder create api \
--group apps \
--version v1alpha1 \
--kind MyApp \
--resource \
--controller
# 3. 创建 Webhook
kubebuilder create webhook \
--group apps \
--version v1alpha1 \
--kind MyApp \
--defaulting \
--validation
# 4. 编辑类型定义
vim api/v1alpha1/myapp_types.go
# 5. 生成代码
make generate # 生成 DeepCopy 方法
make manifests # 生成 CRD、RBAC、Webhook YAML
# 6. 本地测试
make install # 安装 CRD 到集群
make run # 本地运行 Controller
# 7. 构建镜像
make docker-build docker-push IMG=my-registry/myapp-operator:v0.1.0
# 8. 部署到集群
make deploy IMG=my-registry/myapp-operator:v0.1.0main.go 结构
go
func main() {
// 注册类型
utilruntime.Must(appsv1alpha1.AddToScheme(scheme))
// 创建 Manager
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
Metrics: metricsserver.Options{BindAddress: ":8080"},
HealthProbeBindAddress: ":8081",
LeaderElection: true,
LeaderElectionID: "myapp-operator-leader",
})
// 注册 Reconciler
if err = (&controller.MyAppReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "无法创建 Controller")
os.Exit(1)
}
// 注册 Webhook
if err = (&appsv1alpha1.MyApp{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, "无法创建 Webhook")
os.Exit(1)
}
// 健康检查
mgr.AddHealthzCheck("healthz", healthz.Ping)
mgr.AddReadyzCheck("readyz", healthz.Ping)
// 启动
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
setupLog.Error(err, "启动失败")
os.Exit(1)
}
}测试
go
// internal/controller/myapp_controller_test.go
var _ = Describe("MyApp Controller", func() {
Context("创建 MyApp", func() {
It("应该创建对应的 Deployment", func() {
myApp := &appsv1alpha1.MyApp{
ObjectMeta: metav1.ObjectMeta{
Name: "test-app",
Namespace: "default",
},
Spec: appsv1alpha1.MyAppSpec{
Image: "nginx:1.25",
Replicas: 2,
},
}
Expect(k8sClient.Create(ctx, myApp)).Should(Succeed())
// 等待 Deployment 创建
deploy := &appsv1.Deployment{}
Eventually(func() error {
return k8sClient.Get(ctx, types.NamespacedName{
Name: "test-app",
Namespace: "default",
}, deploy)
}, timeout, interval).Should(Succeed())
Expect(*deploy.Spec.Replicas).Should(Equal(int32(2)))
Expect(deploy.Spec.Template.Spec.Containers[0].Image).Should(Equal("nginx:1.25"))
})
})
})bash
# 运行测试(需要 envtest)
make test
# 查看测试覆盖率
go tool cover -html=cover.out常用 Makefile 目标
makefile
make generate # 生成 DeepCopy 代码
make manifests # 生成 CRD/RBAC/Webhook YAML
make install # 安装 CRD 到集群
make uninstall # 卸载 CRD
make run # 本地运行
make test # 运行测试
make build # 构建二进制
make docker-build docker-push IMG=xxx # 构建推送镜像
make deploy IMG=xxx # 部署到集群
make undeploy # 从集群卸载