Skip to main content
There are three common ways to run migrations in your customers’ installs:

Run migrations in a Kubernetes Job

Add a suspended CronJob to your chart as a template. An action creates a Job from it after each deploy, so the migration runs once, with your app’s image, network access and credentials:
charts/api/templates/migrate-cronjob.yaml
Pass database details to the chart from your component config:
components/api/nuon.toml
components/values/api.yaml
The action runs on the runner, which has kubectl and a kubeconfig for the install’s cluster:
actions/api/api_migrate_job/api_migrate_job.toml
actions/api/api_migrate_job/migrate.sh
Keep in mind:
  • The action runs after the deploy. The Job template ships with the chart, so new pods start before the migration.
  • The migration logs land in the action run. You can see which migrations ran on each install from the dashboard.
  • Rerun it by hand from the dashboard with the manual trigger.

Run migrations in an init container

Add an init container to your chart that runs your migration tool from the new image:
charts/api/templates/deployment.yaml
Pass database details to the chart from your component config, as in the Kubernetes Job example. Keep in mind:
  • Set deploy_timeout longer than your slowest migration. A Helm chart component waits for its pods to be ready, for 30 minutes by default and up to 1 hour.
  • Gate Kubernetes manifest deploys on health. A Kubernetes manifest component finishes once the manifests are applied, before the init container completes. Set block_deploy to fail the deploy when the pods stay unhealthy.
  • Helm hooks also run. If your chart already migrates in a pre-upgrade hook Job, Nuon deploys run it.

Run migrations with an action and a container image

Use an action when the migration must finish before new pods start, or your app runs outside Kubernetes. When you set image on the action, its steps run inside a container image on the install runner. This example is for AWS. On Google Cloud and Azure, swap the registry block and the secret lookup for Google Artifact Registry and Secret Manager, or Azure Container Registry and Key Vault.
1

Publish your migrations image

Add the image as a container image component:
components/migrations_image/nuon.toml
If your app’s image already contains your migration binary, point image at that image’s component instead.
2

Define the action

Point image at the component and run the action before the api component deploys:
actions/api/api_migrate/api_migrate.toml
3

Write the script

The path in inline_contents is relative to actions/. The script reads the database password with the action’s role, then runs the migration:
actions/api/api_migrate/migrate.sh
Keep in mind:
  • The database must accept connections from the runner. The runner’s virtual machine sits in the install’s network on AWS, Google Cloud and Azure.
  • The action runs as the install’s default operation role unless you set role. That role needs read access to the database secret. See Operation roles.
  • A failed migration pauses the deploy. Someone has to retry or skip it. If they skip it, or three retries fail, the deploy goes ahead without the migration.
  • The action timeout defaults to 5 minutes and can be up to 1 hour.

Hold the deploy until the migration succeeds

In a runbook, a migration step that fails three times stops the runbook before the deploy:
runbooks/api_upgrade.toml
A runbook’s deploy step skips pre-deploy-component actions, so the migration runs once. Someone can still skip a failed step, and the runbook then moves on to the deploy. Start the runbook from the install’s Runbooks tab or with nuon runbooks create-run -i <install> -r api_upgrade. To restore the database if a migration goes wrong, add a snapshot action as the first step and give its role permission to create snapshots. To see each install’s migration version, add an action that prints your migration tool’s status.

Choose an approach

Use break glass for elevated database access

When you need to service your customer’s database urgently, such as resizing it or restoring a snapshot during an incident, your customer can switch on a break glass role. This AWS role can modify and reboot the database, and its policy denies every delete:
break_glass.toml
Set the action’s role to the break glass role:
actions/db/db_resize/db_resize.toml
If the role is switched off, this action runs as the default role and fails with permission errors. To fail fast instead, pick the role for the run: nuon actions create-run -i <install> -w db_resize --role-name <role>.
For Google Cloud and Azure role fields, and how your customer switches a role on, see Break glass.

Next steps