如何编写Kubernetes自定义控制器实现对云端VM资源的操作?
开发步骤建议
第一步:定义CRD(自定义资源定义)
先将你预期的VM资源结构转换成标准CRD YAML,明确所有字段的属性约束:
- spec内的
vmname设为必填字符串类型,用于存储用户自定义的云VM名称 - status段开放
vmId(字符串类型,存储云厂商返回的VM唯一标识)、cpuUtilization(整数类型,存储监控采集的CPU使用率)两个字段,同时开启status子资源权限,避免更新状态时意外覆盖spec配置。
CRD编写完成后部署到K8s集群,验证可以正常通过kubectl get vm命令查询资源。
第二步:生成客户端代码
直接复用sample-controller自带的代码生成工具链即可:
- 在项目
pkg/apis目录下创建samplecontroller.k8s.io/v1alpha1组版本目录,写入VM类型的Go结构体定义,注意补充// +k8s:deepcopy-gen这类代码生成标签 - 运行项目内
hack/update-codegen.sh脚本,自动生成clientset、lister、informer等必需的客户端代码,无需手动编写。
第三步:编写控制器核心逻辑
控制器核心是处理VM资源的增删改事件,对应你需要的三个核心能力:
- 创建逻辑:当informer监听到新的VM资源创建事件时,先判断status中是否存在
vmId,如果不存在则调用对应云厂商的Go SDK创建VM,创建成功后将云厂商返回的vmId回写到VM资源的status中。 - 更新逻辑:监听VM资源的更新事件,对比新旧资源的spec字段,如果
vmname等配置发生变更,调用云厂商SDK更新对应VM的配置,更新完成后同步更新status;如果需要定期同步CPU利用率这类监控数据,可以启动一个定时协程,每隔固定时间拉取所有VM对应云实例的监控数据,批量更新status中的cpuUtilization字段。 - 删除逻辑:监听VM资源的删除事件,读取status中的
vmId调用云厂商SDK删除对应VM实例,这里要注意新增删除finalizer避免资源残留:创建VM时先给VM资源添加自定义finalizer(例如samplecontroller.k8s.io/vm-protection),删除时先判断是否存在该finalizer,先完成云侧VM删除操作,成功后再移除finalizer,K8s会自动完成VM资源的最终清理。
第四步:测试验证
- 先本地运行控制器验证逻辑:kubectl apply一个VM资源,确认云侧自动创建对应VM、status正确回写
vmId;修改spec的vmname配置,确认云侧配置同步更新;kubectl delete VM资源,确认云侧VM同步删除。 - 本地验证通过后将控制器打包成镜像,用Deployment部署到集群中,配置对应RBAC权限(需要给控制器开放VM资源的增删改查、status更新权限)即可正常上线使用。
注意事项
- 做好幂等处理:控制器重启可能会重复接收创建事件,调用云SDK前先判断是否已完成创建(检查status是否存在
vmId),避免重复创建VM。 - 错误重试:调用云SDK失败时将事件重新入队重试,sample-controller自带的workqueue已经支持重试机制,直接复用即可。
- 权限最小化:控制器使用的云访问密钥只开放VM增删改查的必要权限,不要配置额外权限降低安全风险。
内容的提问来源于stack exchange,提问作者john snowker
相关产品推荐
相关产品推荐

