Upgrading Patterns

3 min read

Patterns are immutable at a version. Upgrading means publishing a new version and consumers opting in — on their own schedule, one by one.


Layer 1: Upgrading a Motif

A new Motif version adds inputs, changes behavior, or fixes a bug. Backwards-compatible changes use defaults so existing consumers don’t need to update their CRs.

# web-service v1.1.0 — adds probeProfile and probePath
inputs:
  - name: probeProfile
    default: "standard"    # same behavior as before — existing CRs unaffected
  - name: probePath
    default: "/health"

Push alongside the old version:

ork push web-service:v1.1.0 ./01-motifs/web-service/
ork inspect web-service:v1.1.0 --motifs
# web-service  v1.1.0  Motif   ← new
# web-service  v1.0.0  Motif   ← still there, unchanged

Old and new coexist. No Katalog is broken. No consumer is forced to upgrade.


Layer 2: A Katalog follows the Motif

The Katalog bumps one import line — web-service:v1.0.0web-service:v1.1.0 — and exposes the new inputs in its CRD spec:

# webapp-operator v1.1.0 — wires probeProfile and probePath through from spec
imports:
  - motif: oci://ghcr.io/myorg/motifs/web-service:v1.1.0
    with:
      probeProfile: "{{ .spec.probeProfile }}"    # new optional field
      probePath: "{{ .spec.probePath }}"          # new optional field

The simulate gate confirms the upgrade is backwards-compatible:

ork simulate
# ✓ 2/2 assertions passed — same resources, probe is configuration not a new resource

E2E confirms it works in a real cluster:

ork e2e
# ✓ PASS

Push:

ork push webapp-operator:v1.1.0 ./
ork inspect webapp-operator:v1.1.0
# Simulate: ✓ Verified  E2E: ✓ Verified

Deploy the upgrade

Bump the import in the Komposer:

imports:
  registry:
    - oci://ghcr.io/myorg/katalogs/webapp-operator:v1.1.0   # was v1.0.0
ork generate bundle -f komposer.yaml -o bundle-v1.1.0.yaml
kubectl apply -f bundle-v1.1.0.yaml

kubectl rollout restart deployment/orkestra-runtime -n orkestra-system
kubectl rollout status deployment/orkestra-runtime -n orkestra-system

Existing CRs continue reconciling — the new optional inputs default to the same behavior as before. No CR migration.


Rollback

# Revert komposer.yaml to webapp-operator:v1.0.0
ork generate bundle -f komposer.yaml -o bundle-rollback.yaml
kubectl apply -f bundle-rollback.yaml
kubectl rollout restart deployment/orkestra-runtime -n orkestra-system

v1.1.0 is still in the registry. Untouched. Rollback doesn’t delete it.


Version isolation: two Katalogs, same cluster

Platform teams choose their upgrade schedule. One team may stay on v1.0.0 while another runs v1.1.0 — in the same Orkestra runtime, managing the same CRD.

webapp-operator:v1.0.0  → web-service:v1.0.0  (platform team — pinned)
webapp-operator:v1.1.0  → web-service:v1.1.0  (your team — upgraded)

Each Katalog’s configuration lives in its own ConfigMap slice. Bumping one does not touch the other. When the platform team is ready, they upgrade on their own timeline.

This is the distribution model: the registry stores both versions permanently. Upgrading is a deliberate act in each consumer.


Rollback safety

Before upgrading in production, ork plan shows what would change:

ork plan -f komposer.yaml --bundle bundle-v1.1.0.yaml
# ~ deployment/my-webapp: readinessProbe added (http /health profile standard)
# No deletions. No CRD schema changes.

Non-destructive changes (adding probes, updating images) are safe to apply without cluster disruption. Destructive changes (removing fields, changing CRD groups) require more care — check what downstream operators watch before upgrading.


Try it

ork init --pack registry-guide
cd 07-upgrade

# Follow the steps in the README