Skip to main content

CRD versioning and migration plan

crd versioning infographic

Bloodraven's API is currently shipstream.io/v1alpha1. This page sets the compatibility contract expected before promoting the API to v1beta1 and then v1.

Current state: v1alpha1

v1alpha1 means the API is usable for pilots and early production evaluation, but the schema is still allowed to change. Consumers should:

  • Pin the operator and chart version.
  • Commit generated manifests rather than relying on floating chart refs.
  • Review release notes before applying CRD updates.
  • Avoid depending on undocumented fields or status internals.

Bloodraven will preserve data-plane safety across upgrades, but it does not yet promise wire-compatible CRD evolution for every alpha field.

Promotion criteria for v1beta1

Move to v1beta1 only after these are true:

  1. A conversion webhook exists and is covered by envtest.
  2. All fields that may be renamed, reshaped, or removed from v1alpha1 have a documented migration path.
  3. Defaults and validation rules are stable enough to support server-side dry-run in production pipelines.
  4. The chart installs webhook Service, Deployment flags, CA injection, and RBAC without manual post-install steps.
  5. Generated CRDs in config/crd/bases/ and charts/bloodraven/crds/ are checked for drift in CI.
  6. Backward compatibility is tested against at least one real older CR fixture per managed resource.

Promotion criteria for v1

Move to v1 only after v1beta1 has survived real upgrades and the following compatibility contract is acceptable:

  • No breaking spec-field removals within v1.
  • Additive spec fields are allowed.
  • Status fields may grow additively; existing documented status fields keep their meaning.
  • Enum values are not removed without a deprecation window.
  • Defaults do not change in a way that causes existing manifests to reconcile into different data-plane behavior.
  • Destructive operations remain gated by explicit confirmation fields or annotations.

Conversion strategy

Bloodraven should use hub-and-spoke conversion with the newest stable API as the hub.

Initial shape:

v1alpha1 <-> internal hub <-> v1beta1

After v1 exists:

v1alpha1 <-> internal hub <-> v1beta1 <-> v1

The webhook must be lossless for fields that still exist in the target version. If a field has no equivalent, conversion should preserve it via annotations only when there is a concrete rollback requirement; otherwise the release notes must call out the one-way migration.

Deprecation policy

Use this policy once v1beta1 exists:

Change typePolicy
Add optional spec fieldAllowed in any minor release.
Add status fieldAllowed in any minor release.
Rename spec fieldAdd replacement first; support both through at least one minor release; remove only before v1 or in a new API version.
Remove enum valueDeprecate in docs and events first; reject new usage only after one minor release; keep conversion for old objects.
Change defaultTreat as breaking unless old behavior is unsafe. Require release-note callout and migration guidance.
Change log/event contractUpdate Log schema and release notes in the same PR.

Storage-version migration

When introducing a new stored version:

  1. Serve both old and new versions in the CRD.
  2. Deploy the conversion webhook before changing storage: true.
  3. Mark the new version as storage.
  4. Run Kubernetes' storage-version migrator or force a safe read/write of all objects.
  5. Verify status.storedVersions no longer lists the retired storage version before removing it from the CRD.

Operational checks:

kubectl get crd mysqlfailovergroups.shipstream.io \
-o jsonpath='{.status.storedVersions}{"\n"}'

kubectl get mysqlfailovergroups -A -o yaml >/tmp/bloodraven-cr-backup.yaml

Always take an object backup before storage-version migration. This is a Kubernetes API safety net, not a MySQL data backup.

Release-note requirements

Every release that changes the CRD schema must include:

  • A list of added, changed, deprecated, and removed fields.
  • Whether make manifests changes config/crd/bases/ and chart CRDs.
  • Whether a conversion webhook upgrade order is required.
  • A kubectl apply --server-side --dry-run=server command users can run against representative manifests.
  • Any data-plane behavior change caused by new defaults.

Compatibility tests

Before declaring v1beta1, add tests that:

  • Decode old v1alpha1 YAML fixtures and convert them to the hub.
  • Convert hub objects back to v1alpha1 and v1beta1 without losing preserved fields.
  • Install the CRD and webhook in envtest.
  • Exercise status subresource writes across served versions.
  • Validate that destructive fields still require confirmation after conversion.

What not to do

  • Do not silently change field meaning while keeping the same name.
  • Do not make the chart install a CRD version that the running operator cannot reconcile.
  • Do not remove a served version until every supported upgrade path has a conversion route.
  • Do not rely on Helm alone for storage-version migration; Helm updates CRD YAML but does not rewrite existing objects.