Migrating Applications from ARO Standard to ARO HCP with Migration Toolkit for Applications (MTA)
This content is authored by Red Hat experts, but has not yet been tested on every supported configuration. This guide has been validated on OpenShift 4.21. Operator CRD names, API versions, and console paths may differ on other versions.
Azure Red Hat OpenShift with hosted control planes (ARO HCP) runs the control plane in a Microsoft managed Azure subscription rather than your own. Because that is a different architecture, there is no in-place upgrade path from ARO Standard to ARO HCP. Moving to HCP means building a new cluster and migrating your workloads onto it.
The Migration Toolkit for Applications (MTA) provides mta-ops, a standalone CLI that migrates workload manifests and persistent volume data between OpenShift clusters.
This guide is a walkthrough using five sample workloads, not a template to run unchanged against production. It shows the sequence, the verification points, and the failure modes, using applications whose data you can predict and check.
Advanced topics such as workload identity, custom networking, and air-gapped or S3 mediated transfers are out of scope. For those, see the MTA documentation .
Prerequisites
- An ARO Standard cluster and an ARO HCP cluster
oc, with cluster-admin on both clustersgit,python3, andcurl, used by commands in this guide- The
mta-opsCLI, downloaded from the Red Hat Developer portal (select the Ops CLI archive for your operating system, not the analyzer CLI) - An Azure Disk and an Azure Files storage class on both clusters
Registry Access
-
Both clusters able to pull from
registry.redhat.io, which is wheremta-opsruns its transfer pods from.On ARO Standard this comes from the cluster-wide pull secret, added at creation or with Add or update your Red Hat pull secret .
On ARO HCP that secret is service managed, so add a cluster-wide additional pull secret instead.
1. Connect to both clusters
mta-ops talks to both clusters in one operation and identifies them by context name, so both must be in your kubeconfig at the same time.
Log in to the ARO Standard cluster, then record its context:
Log in to the ARO HCP cluster, then record its context:
Confirm the two variables point at different clusters, not the same one twice:
From here every command names its cluster explicitly with --context.
2. Deploy the sample applications on ARO Standard
Clone the repository and check out the tested commit:
Each application pairs an Azure Disk (ReadWriteOnce) volume with an Azure Files (ReadWriteMany) volume, so a migration has to handle both access modes:
| Application | Azure Disk (RWO) | Azure Files (RWX) | Migration case it proves |
|---|---|---|---|
| Retail Orders | PostgreSQL database | Catalog images | A StatefulSet database beside a multi-replica frontend on a shared volume |
| Document Portal | MariaDB metadata | Document library | Three web replicas writing concurrently to one volume |
| Artifact Repository | Redis index cache | Artifact store | Separate writer and reader tiers sharing a volume |
| Analytics Reports | PostgreSQL warehouse | Report output | A CronJob writing a volume that a Deployment serves |
| Media Pipeline | Redis job queue | Media store | Three workers writing concurrently, the heaviest RWX case |
Three components write continuously once running: transcode-worker in media-pipeline, artifact-uploader in build-artifacts, and the nightly-report CronJob in analytics-reports. That is deliberate: it means the volumes hold real data to migrate, and it is why they are deployed last on the target.
Verify the applications are running
Long running pods should be Running and ready.
You should see ten Bound claims, five on the Azure Disk class and five on Azure Files.
Seed data you can verify later
The sample databases start with an empty schema, so a structural check would pass against an empty target. Seed a known dataset to compare afterwards:
3. Export, transform, and render the manifests
Retail Orders
Document Portal
Artifact Repository
Analytics Reports
Media Pipeline
4. Prepare the clusters for migration
Create the target namespaces in the ARO HCP Cluster
Add a storage class for the Azure Files volumes
Azure Files is an SMB share and presents every file as a fixed owner rather than tracking POSIX ownership. The mta-ops transfer pod runs under the UID OpenShift assigns to its namespace, so if the share is mounted as a different owner the copy cannot set file metadata and fails.
This guide mounts each share as the UID of the namespace it serves. Because OpenShift allocates a different UID range per namespace, that means one storage class per namespace. The 0777 modes keep the share readable and writable by the application containers, which run under a different UID from the mount owner. This is the configuration used here, not a general requirement: Microsoft documents
other Azure File storage class options
that may suit your environment better.
5. Stage the Azure Files volumes
Staging copies the bulk of the data while the source keeps running, shortening the cutover window:
The Azure Disk volumes are attached to running pods and cannot be copied yet. They are transferred during cutover.
6. Stop the source applications
mta-ops copies volumes file by file, so the source has to be stopped before the authoritative transfer. Scale the workloads down and suspend the CronJobs:
A successful scale only records intent, so wait until the pods are actually gone:
7. Transfer all volumes
Re-run the five Azure Files transfers from step 5. With the source stopped, this pass is the authoritative one.
Then transfer the five Azure Disk volumes:
List the claims on the target and check each one by namespace, class, and status:
8. Deploy the workloads on ARO HCP, writers last
The transfers already created the claims, so drop those manifests, hold the three writers back so they cannot modify the migrated data before you have checked it, and apply the rest:
9. Verify the migration
Wait for the workloads to roll out, then confirm all ten claims are Bound and on the storage class you intended:
Pod status does not prove the data arrived. Check the rows you seeded in step 2, which must come back as 1000, and the shared volume, which should hold the files the workers wrote before cutover:
Finally, every route should answer 200:
10. Resume the writers
Once the comparisons pass, start the deferred components:
Confirm they start and begin producing data:
From this point the applications generate new data on the target.
11. Accept the migration, then clean up
Keep the source cluster intact and its applications stopped until you have accepted the target. Leaving the source cluster running is not by itself a rollback plan.
Once the applications have been accepted on HCP and your rollback window has passed:
Rolling back after the target has accepted writes is not simply a matter of restarting the source. Anything written on HCP after cutover exists only there and would have to be reconciled by hand.