Creating a ROSA HCP cluster
Prerequisites
-
Install the required tools and set up the prerequisite infrastructure using the ROSA Setup guide.
-
Export the following:
export EXP_ROSA=true export EXP_MACHINE_POOL=true -
Create a management cluster using the Quick Start Guide.
IAM Role Configuration
Note: This step is only required when using a ROSA HCP or OCP cluster as the management cluster.
Configure the IAM role authentication for the CAPA controller following the directions here.
Authentication
The CAPA controller requires service account credentials to provision ROSA HCP clusters.
Note: If you already have a service account, you can skip these steps.
- Create a service account by visiting https://console.redhat.com/iam/service-accounts.
- For every newly created service account, make sure to activate the account using the ROSA command line tool.
First, log in using your newly created service account:
rosa login --client-id ... --client-secret ... - Then activate your service account:
rosa whoami
Permissions
-
Create a new kubernetes secret with the service account credentials to be referenced later by the
ROSAControlPlanekubectl create secret generic rosa-creds-secret \ --from-literal=ocmClientID='....' \ --from-literal=ocmClientSecret='eyJhbGciOiJIUzI1NiIsI....' \ --from-literal=ocmApiUrl='https://api.openshift.com'Note: The secret must be created in the same namespace where your ROSA resources will be deployed. Alternatively, to consume the secret without the need to reference it from your
ROSAControlPlane, name your secretrosa-creds-secretand create it in the CAPA manager namespace (usuallycapa-system)kubectl -n capa-system create secret generic rosa-creds-secret \ --from-literal=ocmClientID='....' \ --from-literal=ocmClientSecret='eyJhbGciOiJIUzI1NiIsI....' \ --from-literal=ocmApiUrl='https://api.openshift.com'
Creating the cluster
-
Prepare the environment:
export OPENSHIFT_VERSION="4.20.11" # check available versions with: rosa list versions --hosted-cp export AWS_REGION="us-west-2" export AWS_AVAILABILITY_ZONE="us-west-2a" export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) export AWS_CREATOR_ARN=$(aws sts get-caller-identity --query Arn --output text) -
Create the
ROSARoleConfigandROSANetworkresources.The
ROSARoleConfigautomates the creation of the AWS IAM resources required by ROSA HCP clusters:- Account roles: Installer, Support, and Worker IAM roles (e.g.
<prefix>-HCP-ROSA-Installer-Role) - Operator roles: IAM roles for cluster operators including ingress, image registry, storage, network, kube cloud controller, node pool management, control plane operator, and KMS provider
- OIDC provider: A managed OpenID Connect provider used for operator role authentication
The
ROSANetworkautomates the creation of the VPC networking infrastructure via an AWS CloudFormation stack, including:- A VPC with the specified CIDR block
- Public and private subnet pairs for each availability zone
- Associated networking resources (internet gateway, NAT gateways, route tables)
Note: The
prefixfield has a maximum length of 4 characters.cat <<EOF > rosa-role-network.yaml apiVersion: infrastructure.cluster.x-k8s.io/v1beta2 kind: ROSARoleConfig metadata: name: "role-config" namespace: "capa-system" spec: accountRoleConfig: prefix: "rosa" version: "4.20.11" operatorRoleConfig: prefix: "rosa" credentialsSecretRef: name: rosa-creds-secret oidcProviderType: Managed --- apiVersion: infrastructure.cluster.x-k8s.io/v1beta2 kind: ROSANetwork metadata: name: "rosa-vpc" namespace: "capa-system" spec: region: "us-west-2" stackName: "rosa-hcp-net" availabilityZones: - "us-west-2a" - "us-west-2b" - "us-west-2c" cidrBlock: 10.0.0.0/16 EOFkubectl apply -f rosa-role-network.yamlVerify the
ROSARoleConfigwas successfully created. The status should contain theaccountRolesRef,oidcID,oidcProviderARNandoperatorRolesRef:kubectl get rosaroleconfig role-config -o yamlExample expected status:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2 kind: ROSARoleConfig metadata: name: "role-config" namespace: "capa-system" spec: ... status: accountRolesRef: installerRoleARN: arn:aws:iam::123456789012:role/rosa-HCP-ROSA-Installer-Role supportRoleARN: arn:aws:iam::123456789012:role/rosa-HCP-ROSA-Support-Role workerRoleARN: arn:aws:iam::123456789012:role/rosa-HCP-ROSA-Worker-Role conditions: - lastTransitionTime: "2025-11-03T18:12:09Z" status: "True" type: Ready - lastTransitionTime: "2025-11-03T18:12:09Z" message: RosaRoleConfig is ready reason: Created severity: Info status: "True" type: RosaRoleConfigReady oidcID: anyoidcanyoidctuq4b oidcProviderARN: arn:aws:iam::123456789012:oidc-provider/oidc.os1.devshift.org/anyoidcanyoidctuq4b operatorRolesRef: controlPlaneOperatorARN: arn:aws:iam::123456789012:role/rosa-kube-system-control-plane-operator imageRegistryARN: arn:aws:iam::123456789012:role/rosa-openshift-image-registry-installer-cloud-credentials ingressARN: arn:aws:iam::123456789012:role/rosa-openshift-ingress-operator-cloud-credentials kmsProviderARN: arn:aws:iam::123456789012:role/rosa-kube-system-kms-provider kubeCloudControllerARN: arn:aws:iam::123456789012:role/rosa-kube-system-kube-controller-manager networkARN: arn:aws:iam::123456789012:role/rosa-openshift-cloud-network-config-controller-cloud-credentials nodePoolManagementARN: arn:aws:iam::123456789012:role/rosa-kube-system-capa-controller-manager storageARN: arn:aws:iam::123456789012:role/rosa-openshift-cluster-csi-drivers-ebs-cloud-credentialsVerify the
ROSANetworkwas successfully created. The status should contain the created subnets:kubectl get rosanetwork rosa-vpc -o yamlExample expected status:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2 kind: ROSANetwork metadata: name: "rosa-vpc" namespace: "capa-system" spec: ... status: conditions: - lastTransitionTime: "2025-11-03T18:15:05Z" reason: Created severity: Info status: "True" type: ROSANetworkReady subnets: - availabilityZone: us-west-2a privateSubnet: subnet-084ebac3893fc14ff publicSubnet: subnet-0ec9fa706a26519ee - availabilityZone: us-west-2b privateSubnet: subnet-07727689065612f6e publicSubnet: subnet-0bb2220505b16f606 - availabilityZone: us-west-2c privateSubnet: subnet-002e071b9624727f3 publicSubnet: subnet-049fa2a528d896356 - Account roles: Installer, Support, and Worker IAM roles (e.g.
-
Create the
AWSClusterControllerIdentityresource:cat <<EOF > aws-cluster-controller-identity.yaml apiVersion: infrastructure.cluster.x-k8s.io/v1beta2 kind: AWSClusterControllerIdentity metadata: name: "default" spec: allowedNamespaces: {} # matches all namespaces EOFkubectl apply -f aws-cluster-controller-identity.yaml -
Create the
Cluster,ROSACluster, andROSAControlPlaneresources:cat <<EOF > rosa-cluster.yaml apiVersion: cluster.x-k8s.io/v1beta2 kind: Cluster metadata: name: "rosa-hcp-1" spec: clusterNetwork: pods: cidrBlocks: ["192.168.0.0/16"] infrastructureRef: apiGroup: infrastructure.cluster.x-k8s.io kind: ROSACluster name: "rosa-hcp-1" controlPlaneRef: apiGroup: controlplane.cluster.x-k8s.io kind: ROSAControlPlane name: "rosa-hcp-1-control-plane" --- apiVersion: infrastructure.cluster.x-k8s.io/v1beta2 kind: ROSACluster metadata: name: "rosa-hcp-1" spec: {} --- apiVersion: controlplane.cluster.x-k8s.io/v1beta2 kind: ROSAControlPlane metadata: name: "rosa-hcp-1-control-plane" spec: credentialsSecretRef: name: rosa-creds-secret rosaClusterName: rosa-hcp-1 domainPrefix: rosa-hcp rosaRoleConfigRef: name: role-config # reference to the ROSARoleConfig created above version: "4.20.11" region: "us-west-2" rosaNetworkRef: name: "rosa-vpc" # reference to the ROSANetwork created above network: machineCIDR: "10.0.0.0/16" podCIDR: "10.128.0.0/14" serviceCIDR: "172.30.0.0/16" defaultMachinePoolSpec: instanceType: "m5.xlarge" autoscaling: maxReplicas: 6 minReplicas: 3 additionalTags: env: "demo" EOFkubectl apply -f rosa-cluster.yaml -
Check the
ROSAControlPlanestatus:kubectl get ROSAControlPlane rosa-hcp-1-control-plane NAME CLUSTER READY rosa-hcp-1-control-plane rosa-hcp-1 trueThe ROSA HCP cluster can take around 40 minutes to be fully provisioned.
-
After provisioning has completed, verify the
ROSAMachinePoolresources were successfully created:kubectl get ROSAMachinePool NAME READY REPLICAS workers-0 true 1 workers-1 true 1 workers-2 true 1Note: The number of default
ROSAMachinePoolresources corresponds to the number of availability zones configured. -
To add an additional
ROSAMachinePool, save the following to a filerosa-machinepool-extra.yaml:cat <<EOF > rosa-machinepool-extra.yaml apiVersion: cluster.x-k8s.io/v1beta2 kind: MachinePool metadata: name: "rosa-hcp-1-workers-extra" spec: clusterName: "rosa-hcp-1" replicas: 2 template: spec: clusterName: "rosa-hcp-1" bootstrap: dataSecretName: "" infrastructureRef: apiGroup: infrastructure.cluster.x-k8s.io kind: ROSAMachinePool name: "workers-extra" --- apiVersion: infrastructure.cluster.x-k8s.io/v1beta2 kind: ROSAMachinePool metadata: name: "workers-extra" spec: nodePoolName: "workers-extra" version: "4.20.11" instanceType: "m5.xlarge" autoRepair: true EOFkubectl apply -f rosa-machinepool-extra.yaml
Deleting a ROSA HCP cluster
To delete a ROSA HCP cluster, delete the Cluster and ROSAControlPlane resources. This will also clean up the associated ROSACluster, MachinePool, and ROSAMachinePool resources:
kubectl delete -n <namespace> cluster/rosa-hcp-1 --wait=false
kubectl delete -n <namespace> rosacontrolplane/rosa-hcp-1-control-plane
After the cluster has been fully deleted, you can clean up the ROSARoleConfig and ROSANetwork resources:
kubectl delete rosaroleconfig role-config
kubectl delete rosanetwork rosa-vpc
see ROSAControlPlane CRD Reference for all possible configurations.