Page
Prepare your bare metal cluster for migration
Now we will tackle the process of migrating Red Hat OpenShift clusters from bare metal nodes to bare metal nodes using hosted control planes architecture. At its core, it’s very similar to transitioning your Red Hat OpenShift Service on AWS (ROSA) clusters, but with a few key step changes.
Note
If you wish to only transition from Red Hat OpenShift Service on AWS (classic) to Red Hat OpenShift Service on AWS with hosted control planes, please refer to this resource.
Prerequisites:
- Administrator access to your cluster and the destination cluster.
- Access to the same S3 buckets that hold any backups you make from your source cluster.
- Access to OpenShift APIs for Data Protection (OADP).
In this lesson, you will:
- Access your clusters and retrieve the config files.
- Export your cluster resources.
- Configure S3 storage.
Accessing your cluster
To begin, you need to use your cluster-admin access to get specific files from both your source and target clusters. In this example, we’ll refer to the following:
- Source cluster name:
pm-cluster(standalone OpenShift, 6 nodes) - Target cluster name:
bm-hosted-cluster(hosted control planes cluster, 2 worker nodes)
Log in to the hosted cluster and save kubeconfig using the following commands.
Note
Adjust the kubeconfig file paths (~/kubeconfig-pm-cluster and ~/kubeconfig-bm-hosted-cluster) throughout this guide to match your actual file locations.
oc login https://api.pm-cluster.example.com:6443 --username=admin
oc config view --flatten > ~/kubeconfig-pm-clusterNext, log in to the hosted cluster and save kubeconfig:
oc login https://api.bm-hosted-cluster.example.com:6443 --username=admin
oc config view --flatten > ~/kubeconfig-bm-hosted-clusterVerify access to both clusters:
export KUBECONFIG=~/kubeconfig-pm-cluster
oc whoami
oc get nodesexport KUBECONFIG=~/kubeconfig-bm-hosted-cluster
oc whoami
oc get nodesNow that we’ve verified access, it’s time to export our resources for moving.
Export cluster-scoped, role-based access control (RBAC) resources
Now we’ll export our RBAC resources for our application that’s being moved over. These are necessary because ClusterRole and ClusterRoleBinding are cluster-scoped and not in any namespace.
Note
OADP namespace backups only include namespace-scoped resources. Cluster-scoped resources (ClusterRoles, ClusterRoleBindings) are NOT included in the backup and must be exported separately.
Export cluster-scoped RBAC resources for your application:
export KUBECONFIG=~/kubeconfig-pm-clusterFind
ClusterRolesfor your application:oc get clusterrole | grep cert-discoveryExpected output:
cert-discovery-role 2025-11-06T11:53:23Z cert-discovery-binding ClusterRole/cert-discovery-roleExport the resources we just found to YAML files using both of the following commands:
oc get clusterrole cert-discovery-role -o yaml > /tmp/clusterrole-cert-discovery.yamloc get clusterrolebinding cert-discovery-binding -o yaml > /tmp/clusterrolebinding-cert-discovery.yamlNext, we’ll verify the files were created:
ls -lh /tmp/cluster*.yaml
It’s important to keep these files, as they will be applied to the target cluster in a later step before we restore. Without these permissions, the application will fail with “403 Forbidden” errors later.
Alternative export method (Optional)
Instead of manually exporting RBAC resources, you can include them in the OADP backup by labeling them first and using includedClusterScopedResources in the Backup spec.
Label the cluster-scoped RBAC resources:
export KUBECONFIG=~/kubeconfig-pm-clusterAdd app label to
ClusterRole:oc label clusterrole cert-discovery-role app=cert-discoveryAdd app label to
ClusterRoleBinding:oc label clusterrolebinding cert-discovery-binding app=cert-discoveryVerify labels were added:
oc get clusterrole cert-discovery-role --show-labelsoc get clusterrolebinding cert-discovery-binding --show-labelsFinally, we’ll modify the Backup spec we previously addressed in the first route.
apiVersion: velero.io/v1 kind: Backup metadata: name: cert-discovery-app-backup namespace: openshift-adp spec: includedNamespaces: - cert-discovery-app includedClusterScopedResources: - clusterroles - clusterrolebindings labelSelector: matchLabels: app: cert-discovery storageLocation: default ttl: 720h0m0s defaultVolumesToFsBackup: false
The benefits of using this alternative export method means RBAC resources are automatically included in the backup, no manual export/apply steps are needed, and RBAC resources are restored with the OADP Restore Custom Resource (the OpenShift object you create to tell OADP to restore from a backup).
Note
If you use this approach, you can skip the later step for applying cluster-scoped RBAC, as it will be handled automatically during restore.
Expected migration flow
Before we begin, it is important to make sure that your S3 storage is set to the following:
- AWS S3 bucket:
cert-discovery-management-app - Region:
eu-north-1 - IAM credentials with read/write permissions
As for the migration itself, there are a few things to consider with the methods we’re using:
- Workload migration, not control plane backup. OADP installed on both clusters directly.
- HyperShift plugin not needed for this use case.
- RBAC requires manual handling. OADP namespace backups don't include cluster-scoped resources.
- Two-step process: Apply cluster-scoped RBAC first → Then restore namespace-scoped resources.
Flow example below:
Source: pm-cluster (Standalone) Target: bm-hosted-cluster
├── OADP installed │
├── cert-discovery-app ├── OADP installed
│ ├── Deployment │
│ ├── Service │
│ ├── Route │
│ ├── PVC (10Gi, 210MB DB) │
│ └── ServiceAccount │
│ │
├── Cluster-scoped RBAC │
│ ├── ClusterRole ────────────────┐ │
│ └── ClusterRoleBinding ─────────┼─┐ │
│ │ │ │
├── Export RBAC (manual) ───────────┘ │ │
│ │ │
├── Create Backup ──────┐ │ │
│ │ │ │
│ ▼ │ │
│ AWS S3 Bucket │ │
│ (eu-north-1) │ │
│ │ │ │
│ │ └──────┼──▶ Apply RBAC first (manual)
│ │ │
│ └────────────────────┼──▶ Restore (namespace-scoped)
│ │
└────────────────────────────────────────────┼── cert-discovery-app
│ ├── Deployment
│ ├── Service
│ ├── Route
│ ├── PVC (10Gi, DB restored)
│ └── ServiceAccount
│
└── Cluster-scoped RBAC
├── ClusterRole
└── ClusterRoleBindingNow that we have our privileges sorted and have an idea of how our migration will work, it’s time to begin the operator installation.