Breadcrumb

  1. Red Hat Interactive Learning Portal
  2. OpenShift learning
  3. Migrating applications from Red Hat OpenShift classic clusters to hosted control plane clusters
  4. Prepare your bare metal cluster for migration

Migrating applications from Red Hat OpenShift classic clusters to hosted control plane clusters

Learn how you can migrate your applications from Red Hat OpenShift classic to a more modernized cluster.

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-cluster

Next, 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-cluster

Verify access to both clusters:

export KUBECONFIG=~/kubeconfig-pm-cluster
oc whoami
oc get nodes
export KUBECONFIG=~/kubeconfig-bm-hosted-cluster
oc whoami
oc get nodes

Now 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.

  1. Export cluster-scoped RBAC resources for your application:

    export KUBECONFIG=~/kubeconfig-pm-cluster
  2. Find ClusterRoles for your application:

    oc get clusterrole | grep cert-discovery
  3. Expected output:

    cert-discovery-role                                                                             2025-11-06T11:53:23Z
    cert-discovery-binding                                                                          ClusterRole/cert-discovery-role
  4. Export 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.yaml
    oc get clusterrolebinding cert-discovery-binding -o yaml > /tmp/clusterrolebinding-cert-discovery.yaml
  5. Next, 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.

  1. Label the cluster-scoped RBAC resources:

    export KUBECONFIG=~/kubeconfig-pm-cluster
  2. Add app label to ClusterRole:

    oc label clusterrole cert-discovery-role app=cert-discovery
  3. Add app label to ClusterRoleBinding:

    oc label clusterrolebinding cert-discovery-binding app=cert-discovery
  4. Verify labels were added:

    oc get clusterrole cert-discovery-role --show-labels
    oc get clusterrolebinding cert-discovery-binding --show-labels
  5. Finally, 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
                                                 └── ClusterRoleBinding

Now that we have our privileges sorted and have an idea of how our migration will work, it’s time to begin the operator installation. 

Previous resource
Overview: Migrating applications from Red Hat OpenShift classic clusters to hosted control plane clusters
Next resource
Install OADP on your management cluster