为何清空ResourceVersion后Deployment可更新而自定义资源不行?
Kubernetes Deployment与自定义资源ResourceVersion处理差异解析
核心差异原因
Kubernetes对内置资源(比如Deployment)和自定义资源(CR)的更新请求做了差异化处理:
- 对于Deployment这类内置集群资源,提交更新请求时如果
metadata.resourceVersion为空,APIServer会自动先发起GET请求获取该资源的最新版本号,填充到请求对象后再执行更新操作,相当于把无版本的更新转换成带乐观锁的合法更新请求。 - 自定义资源则默认依赖CRD定义的验证规则,要求更新操作必须显式指定
resourceVersion,否则直接触发验证报错。
Deployment的特殊处理逻辑源码位置
这个自动填充逻辑位于APIServer的genericregistry模块中,具体实现逻辑在staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go文件的Update函数里:
func (e *Store) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error)
在该函数的处理流程中,会检查请求对象的resourceVersion是否为空:如果为空,就调用Get接口拉取目标资源的最新状态,提取其resourceVersion赋值给请求对象,之后再继续执行常规的更新验证和存储逻辑。
自定义资源无此逻辑的原因及替代方案
自定义资源的处理逻辑由CRD的配置和对应的控制器决定,默认未开启自动填充resourceVersion的功能。如果需要类似Deployment的行为,可以通过两种方式实现:
- 在CRD中设置
preserveUnknownFields: false,并自定义验证逻辑允许空的resourceVersion; - 在客户端侧提前获取目标资源的最新
resourceVersion,再携带该值发起更新请求。
内容的提问来源于stack exchange,提问作者wyz
相关产品推荐
相关产品推荐

