Go K8s Server-Side Apply:声明式 API 实战
K8s 的 Server-Side Apply 让服务端做冲突合并。本文讲清 SSA 的原理、Go 实操、与 client side apply 的对比。
一、什么是 SSA?
Client-side apply = 客户端送完整 object;server 出现冲突由客户端解决。
Server-side Apply = 客户端送"fields manager",服务端合并;冲突由 server 拒绝或覆盖。
二、为什么用 SSA?
- 多客户端协同(CI、Operator、CLI)
- 防止意外覆盖
- 减少 client 复杂度
三、Go 实现 SSA
import"k8s.io/client-go/kubernetes"pod,_:=clientSet.CoreV1().Pods("default").Get(ctx,"my-pod",metav1.GetOptions{})pod.Spec.Containers[0].Image="myapp:v2"clientSet.CoreV1().Pods("default").Apply(ctx,pod,metav1.ApplyOptions{FieldManager:"my-operator",Force:true,},)四、SSA 与 patch 的区别
| 维度 | SSA | JSON Patch |
|---|---|---|
| 冲突解决 | server 合并 | 显式策略 |
| 字段管理 | fields manager | 无 |
| 适用 | 多客户端 | 单一客户端 |
五、Operator 中用 SSA
for_,pod:=rangedesiredPods{iferr:=cli.Apply(ctx,pod,metav1.ApplyOptions{FieldManager:"my-operator",});err!=nil{returnerr}}server 合并 + 记录 user。
六、fields manager 工作流
- 用户 A 部署,manager=
cli - 用户 B 部署,manager=
cli-second,server merge - 用户 C 部署,manager=
third,server 拒绝 with conflict
七、Conflict 处理
_,err:=cli.Apply(ctx,obj,metav1.ApplyOptions{Force:true})// Force=true 表示强制覆盖不设 Force 时遇到 conflict server 报 409。
八、实战:Mysql Operator
mysqlStateful:=&v1.MysqlCluster{ObjectMeta:ObjectMeta{Name:"db"},Spec:v1.MysqlClusterSpec{Version:"8.0",Replicas:3,},}err:=cli.Apply(ctx,mysqlStateful,...)每个 controller 维护自己 manager。
九、Kubectl 的 SSA 形式
kubectl apply --server-side --field-manager=mycli-fapp.yaml十、踩坑清单
- FieldManager 不要重复
- force 谨慎用
- dynamic client 也支持 SSA
十一、未来:声明式 API
- OpenAPI v3 验证
- 动态关联规则
十二、总结与展望
SSA 是云原生 API 的核心模型。Go client 与服务端协议成熟,未来会与 ResourceClaim 结合。
十三、参考文献
- K8s sigs.k8s.io/server-side-apply
- Programming Kubernetes book