CRD版本迁移是否必须双向兼容?K8s创建旧版资源报错排查
问题原因解释
为什么Kubernetes会先转v2再转回v1
Kubernetes APIServer处理CR资源请求的固定流程决定了这个行为:
- 你以v1版本API提交创建请求时,APIServer首先会将接收到的v1资源转换为CRD配置的**
storage版本(也就是v2)**,才能持久化写入etcd,这就是第一次v1转v2请求的来源。 - 由于你发起请求使用的是v1版本API,APIServer需要将最终处理完成的资源对象按照请求的版本返回给客户端,因此会将刚写入etcd的v2资源再次转换为v1版本再返回,这就是第二次v2转v1请求的来源。你之前的webhook没有处理v2转v1的逻辑,直接返回失败,因此整个请求报错。
CRD不同版本是否必须互相兼容
按照Kubernetes CRD的设计规范,同一个CRD下所有标记为served: true的版本之间必须支持双向无损转换:要求任意版本之间互相转换再转回原版本时,不会出现信息丢失。
你当前v2版本直接移除字段的设计,本身就不符合版本兼容要求:
- 如果不需要再对外提供v1版本的访问能力,可以直接将v1版本的
served字段设置为false,停用v1 API入口,就不需要再维护v2转v1的转换逻辑。 - 如果需要保留v1 API的可用性,就必须实现双向转换逻辑,像你补充说明中用虚拟值填充v1缺失字段的方案,就是符合规范的实现方式,此时etcd中存储的是v2版本资源,客户端也能拿到符合v1版本结构的返回结果。
废弃v1版本的参考流程
如果后续要完全下线v1版本,可以按以下步骤操作:
- 先将v1版本标记为废弃,在CRD的v1版本定义中添加
deprecationWarning字段,提示用户尽快迁移到v2版本 - 待所有用户完成迁移后,将v1的
served设置为false,彻底关闭v1 API入口 - 后续可以逐步清理v1相关的转换逻辑
内容的提问来源于stack exchange,提问作者Mateusz Stompór
相关产品推荐
相关产品推荐

