Skip to content

Handle stateful migration prompts safely

This content is for the v0.1 version. Switch to the latest version for up-to-date documentation.

Kix stops a deployment when one stateful resource replaces another in the same package slot. Treat this as a data-migration gate, not as an ordinary confirmation prompt.

The migration gate applies only when one stateful resource replaces another. If a stateful resource is removed without a replacement, Kix treats it as an ordinary orphan. Running with --prune deletes it without a migration prompt. See Deploy with dry-run, timeouts, pruning, and log/TUI output modes to see how the plan reports orphans before deletion.

The example changes the data/volume package from PersistentVolumeClaim/media-v1 at 5Gi to PersistentVolumeClaim/media-v2 at 10Gi.

Review the pair before contacting the cluster

Section titled “Review the pair before contacting the cluster”

This example exports the current definition with its Kix provenance so it can stand in for the old side of an offline diff:

Run in kix-examples/
❱ kix export how-to-stateful-migration --for audit --out stateful-before
Building cluster 'how-to-stateful-migration'...
  Evaluating cluster 'how-to-stateful-migration'...
  Building 'how-to-stateful-migration'...
  building '/nix/store/zrnclwmb0f1aaps855p0qf14113dhbbn-k8s-activation-how-to-stateful-migration.drv'...
  Reading package index...
  Loading store graph...
  Reading 2 packages...
  Discovering cluster-level resources...
  Computing cross-package dependencies...

  Exported 8 resources to stateful-before (audit (kix provenance preserved))

Compare the replacement definition with that saved state:

Run in kix-examples/ Output excerpt
❱ kix diff how-to-stateful-migration --from stateful-before Show output
+ PersistentVolumeClaim/media-v2@data
- PersistentVolumeClaim/media-v1@data
Stateful migrations detected (1):
~ data/volume: PersistentVolumeClaim/media-v1 -> PersistentVolumeClaim/media-v2 (size changed: 5Gi -> 10Gi)
source: PersistentVolumeClaim/data/media-v1
target: PersistentVolumeClaim/data/media-v2
Data migration is not automated. Review the source and target resources above and migrate the data before deploying with --accept-migrations.
(exit code: 2)

Check the logical slot, source, target, and reason. Kix reports this pair because both resources have lifecycle = "stateful", occupy the same data/volume slot, and have different Kubernetes identities.

Choose a procedure supported by the workload and storage provider. Before changing the deployment:

  1. make a recoverable backup or snapshot;
  2. stop or quiesce writers;
  3. copy or restore the data into the target;
  4. verify the target data independently;
  5. record how to return consumers to the source.

Kix detects the replacement but does not perform these steps. The exact copy and verification commands depend on the application, volume provider, and access mode, so they should live in the service’s migration runbook.

An ordinary deployment refuses the pair even when --yes is present:

Run in kix-examples/
❱ kix deploy how-to-stateful-migration -y Show output
Building cluster 'how-to-stateful-migration'...
Cluster how-to-stateful-migration: 8 manifests
Connecting to cluster...
Active activation: how-to-stateful-migration-w2a1afvarsca (w2a1afva...)

Stateful migrations detected (1):
  ~ data/volume: PersistentVolumeClaim/media-v1 -> PersistentVolumeClaim/media-v2 (size changed: 5Gi -> 10Gi)
      source: PersistentVolumeClaim/data/media-v1
      target: PersistentVolumeClaim/data/media-v2

Refusing to deploy: stateful migration pairs detected but --accept-migrations was not passed.
Data migration is NOT yet automated. Review the pairs above, handle the data out-of-band, then re-run with --accept-migrations.
(exit code: 1)

--yes skips the general deploy confirmation. It does not acknowledge data loss risk.

After the data has been migrated and verified, repeat the API-server dry run with the separate acknowledgement:

Run in kix-examples/
❱ kix deploy how-to-stateful-migration --accept-migrations --dry-run -y Show output
Building cluster 'how-to-stateful-migration'...
Cluster how-to-stateful-migration: 8 manifests
Connecting to cluster...
Active activation: how-to-stateful-migration-w2a1afvarsca (w2a1afva...)

Stateful migrations detected (1):
  ~ data/volume: PersistentVolumeClaim/media-v1 -> PersistentVolumeClaim/media-v2 (size changed: 5Gi -> 10Gi)
      source: PersistentVolumeClaim/data/media-v1
      target: PersistentVolumeClaim/data/media-v2

--accept-migrations set: proceeding with deploy. kix will NOT copy data; consumers on new backing will start empty.

  data
    ~ volume 1.0.0 (1 changed, 1 added, 1 removed)

  Plan: 1 updated, 1 unchanged
  Resources: 3 real content, 0 dep-affected
  1 orphaned (kept; pass --prune to delete)
    - PersistentVolumeClaim/media-v1@data

Dry run — no changes will be applied.
plan: 8 nodes
  + PersistentVolumeClaim/media-v2@data created
  ✔ PersistentVolumeClaim/media-v2@data ready
  ~ PackageInstance/volume@data configured
  ✔ PackageInstance/volume@data ready
  + Activation/how-to-stateful-migration-a620ys0axp58 created
  ✔ Activation/how-to-stateful-migration-a620ys0axp58 ready

prune: 1 orphaned resources kept (warn-only; pass --prune to delete)
  - PersistentVolumeClaim/media-v1@data

Dry run complete: 2 created, 1 configured, 5 unchanged, 0 failed

--accept-migrations only allows the deployment to continue. It does not copy data or verify that the target contains it. The warning about an empty target is literal when the out-of-band migration has not happened.

Review the rest of the deployment plan. Do not add --prune while the source PVC is still part of the rollback plan. Pruning has no separate safeguard for stateful resources. Once the source PVC becomes an orphan, Kix deletes it like any other orphan.

Run the acknowledged deployment without --dry-run:

Run in kix-examples/
❱ kix deploy how-to-stateful-migration --accept-migrations

Confirm the application is using the target and validate its data before retiring the source. Remove the old PVC only after the recovery window and according to the storage provider’s reclaim policy.

See Preview changes with kix diff for the ordinary diff workflow.