4、CRD版本迁移测试类型:功能测试、兼容性测试、回滚测试、性能测试、压力测试

CRD 版本迁移是 Operator 生命周期中最关键的风险操作之一。一次不完整的迁移可能导致集群中已有 CR 对象数据损坏、控制器循环崩溃、甚至 API Server 响应超时。因此,必须建立覆盖 功能、兼容性、回滚、性能 和 压力 五个维度的测试体系,才能保障迁移过程安全可控。

4.1 测试类型总览

下表从测试目标、执行时机、关键指标三个维度对比五种测试类型,便于团队在制定测试计划时快速对齐。

测试类型 测试目标 执行时机 关键指标
功能测试 验证 CRD 各版本下 CR 的 CRUD、校验、默认值、子资源行为正确 每次版本变更后 用例通过率 100%,无预期外错误
兼容性测试 保证新旧版本 CR 对象可互读、互写,存储版本切换后数据不丢失 版本发布前 数据无损、字段映射正确、无转换错误
回滚测试 验证从新版本回退到旧版本时,CR 对象和控制器状态可恢复 版本发布前 + 演练 回滚后集群状态与回滚前一致
性能测试 评估迁移过程中 API Server 响应延迟、存储写入吞吐、控制器 Reconcile 耗时 版本发布前 P99 延迟 < 2s,吞吐不下降超过 10%
压力测试 验证大规模 CR 对象下迁移的稳定性,发现资源泄漏或 OOM 风险 版本发布前 + 定期 无 OOM、无 goroutine 泄漏、CR 数量 10k+

4.2 功能测试

功能测试是版本迁移的基线。每个 CRD 版本(served: true)都必须独立通过完整的 CRUD 验证。

  • 创建测试:使用每个 served 版本创建 CR,验证 spec 字段默认值注入、校验准入、metadata 自动填充。
  • 读取测试:分别通过 kubectl get、kubectl get <crd> -o yaml、以及 Operator 内部 Informer 读取,确认字段完整。
  • 更新测试:修改 spec 和 status 字段,验证 subresource 路由正确(/status 更新不触发 spec 校验)。
  • 删除测试:验证 foreground / background 级联删除行为,以及 finalizer 处理逻辑。
⚠ 常见陷阱:如果新版本增加了 required 字段,但旧版本 CR 没有该字段,转换 Webhook 必须提供合理的默认值,否则读取旧 CR 时会报校验错误。

4.3 兼容性测试

兼容性测试的核心是验证 存储版本切换 和 多版本读写一致性。Kubernetes 只会将 CR 以 storage 版本写入 etcd,其他 served 版本通过转换 Webhook 实时转换。

💡 关键原则:所有 served 版本必须能无损转换为 storage 版本,且转换后再转回原版本时字段不丢失、语义不改变。

兼容性测试用例清单:

  1. 正向兼容:用旧版本创建 CR,用新版本读取,验证字段映射正确。
  2. 反向兼容:用新版本创建 CR,用旧版本读取,验证降级后字段不丢失。
  3. 存储版本切换:修改 CRD 的 storage 版本,触发 etcd 中所有 CR 的存储迁移,验证迁移后数据完整。
  4. 转换 Webhook 容错:模拟 Webhook 返回 500 或超时,验证 API Server 是否降级为拒绝请求(不应静默跳过转换)。
  5. 字段弃用测试:标记某字段为 deprecated,验证旧版本仍可读写该字段,新版本写入时被忽略或告警。
CRD 多版本兼容读写流程 旧版本 CR v1alpha1 转换 Webhook Mutate + Convert 新版本 CR v1 etcd 存储 storage 版本 兼容性检查点 ① 旧→新:字段映射完整,无丢失 ② 新→旧:降级后语义不变,无多余字段 ③ 存储切换:etcd 中所有 CR 重新写入,数据校验通过

4.4 回滚测试

回滚测试是版本迁移的“安全气囊”。一旦生产环境发现严重问题,必须能快速恢复到上一个稳定版本。回滚测试应覆盖以下场景:

  • CRD 回滚:将 CRD 的 spec.versions 列表恢复到旧版本配置,验证 API Server 重新加载后旧版本可正常服务。
  • 存储版本回滚:如果存储版本已切换,回滚时需要再次切换存储版本,并触发全量 CR 重新写入 etcd。
  • 控制器回滚:将 Operator Deployment 回退到旧版本镜像,验证控制器能正确处理新旧混合的 CR 对象。
  • 数据完整性校验:回滚后对全量 CR 做快照对比,确保没有字段被静默丢弃或篡改。
🚨 回滚失败常见原因:
1. 新版本删除了旧版本中的字段,回滚后该字段永久丢失。
2. 转换 Webhook 在新版本中引入了副作用(如修改 status),回滚后旧版本无法处理已变更的 status。
3. CRD 的 spec.preserveUnknownFields 设置不当,导致未知字段被裁剪。

4.5 性能测试

性能测试关注迁移过程中控制平面的负载变化。重点测量以下指标:

指标 测量方法 基准值(参考) 告警阈值
API Server 响应延迟 使用 kubectl 批量创建/更新 CR,记录 P50/P99 延迟 P99 < 500ms P99 > 2s
转换 Webhook 耗时 在 Webhook 日志中输出处理时间,聚合 P99 P99 < 100ms P99 > 500ms
etcd 写入吞吐 监控 etcd 的 db 大小和写入 QPS QPS > 1000 QPS 下降 > 30%
控制器 Reconcile 队列深度 暴露 Operator metrics,观察 work_queue_depth 平均 < 10 持续 > 100
📊 性能测试工具推荐:
kubectl-stress 用于批量 CR 操作;vegeta 或 wrk 用于 API Server 压测;Operator 自身暴露的 Prometheus metrics 用于控制器性能监控。

4.6 压力测试

压力测试模拟极端规模下的版本迁移行为,暴露资源泄漏、OOM、etcd 存储爆炸等隐患。

典型压力场景:

  1. 大规模 CR 存储迁移:预先创建 10,000+ 个 CR 对象,然后修改 CRD 的 storage 版本,观察 etcd 写入压力和迁移完成时间。
  2. 并发读写混合:在迁移过程中持续执行 CR 的创建、更新、删除操作,验证 API Server 和 Webhook 不会因并发导致死锁。
  3. Webhook 背压测试:模拟 Webhook 响应缓慢(人为增加 1s 延迟),验证 API Server 的客户端限流和超时重试机制是否正常工作。
  4. 控制器 Reconcile 风暴:迁移完成后,所有 CR 的 resourceVersion 发生变化,触发大量 Reconcile 请求,验证 Operator 的限速和批量处理能力。
压力测试架构与风险点 压力源 10k+ CR / 高并发 API Server 限流 / 超时 转换 Webhook 背压 / 超时 etcd 写入风暴 压力测试关注的风险点 🔴 API Server OOM:大量 CR 转换导致内存暴涨,触发 OOMKill 🔴 Webhook 雪崩:Webhook 响应超时 → API Server 重试 → 流量放大 → 级联故障 🔴 etcd 存储爆炸:存储迁移时全量 CR 重新写入,db 大小临时翻倍 🔴 控制器 goroutine 泄漏:大量 Reconcile 请求导致协程无法正常退出

4.7 测试执行策略建议

在实际项目中,建议按以下优先级和频率执行五类测试:

  • 每次代码提交:功能测试(CI 流水线中运行,覆盖所有 served 版本)。
  • 每次版本发布前:兼容性测试 + 性能测试(在预发环境执行,数据量不低于生产 10%)。
  • 每季度或大版本变更:回滚测试 + 压力测试(需要独立的高负载测试集群)。
  • 生产变更前:至少执行一次完整的回滚演练,确保回滚剧本可执行。
📌 最终建议:将五类测试用例编写为 端到端(E2E)测试套件,集成到 CI/CD 流水线中。使用 ginkgo + kind 或 envtest 搭建隔离测试环境,确保每次 CRD 版本变更都能自动触发全量验证。