Deploying ROSA HCP in a Shared VPC Pattern
This content is authored by Red Hat experts, but has not yet been tested on every supported configuration.
Red Hat OpenShift Service on AWS (ROSA) with Hosted Control Planes (HCP) supports a shared VPC deployment pattern where the cluster’s networking infrastructure (VPC, subnets, Route 53 hosted zones) lives in a centralized networking account while the ROSA cluster is owned by a separate workload account. This pattern is common in enterprises that use a hub-and-spoke networking model with AWS Organizations.
This tutorial walks through deploying a private ROSA HCP cluster in a shared VPC using the rosa and aws CLI tools, including customer-managed KMS encryption for etcd and node volumes.
Note: A Terraform automation is available as an alternative to the manual CLI steps. See the appendix at the end of this tutorial.
Architecture
The shared VPC pattern separates infrastructure ownership across two AWS accounts:
- Shared VPC Account (VPC Owner / Networking)
- VPC, Subnet, NAT Gateway, Internet Gateway
- Cluster Account (Cluster Creator / Workload)
- Red Hat SRE (Managed)
- HCP Control Plane: runs in Red Hat AWS account
- PrivateLink VPC Endpoint: connects to worker VPC
Key design points:
- The HCP control plane runs in a Red Hat-managed AWS account and connects to the worker nodes via a PrivateLink VPC endpoint created in the shared VPC.
- Route 53 private hosted zones in the shared VPC account handle DNS for both internal HCP communication and application ingress.
- Cross-account access is mediated through IAM roles with explicit trust policies — no VPC peering or Transit Gateway required.
- A customer-managed KMS key in the cluster account encrypts both etcd and EBS volumes.
Prerequisites
| Tool | Version | Purpose |
|---|---|---|
| AWS CLI | v2 | AWS resource management |
rosa CLI | >= 1.2.49 | ROSA role, OIDC, and cluster creation |
oc CLI | latest | Cluster access (post-install) |
jq | latest | JSON parsing |
AWS requirements:
- Two AWS accounts in the same AWS Organization (or a single account for testing):
- VPC Owner account: owns the VPC, subnets, Route 53 zones, and shared VPC IAM roles
- Cluster Creator account: owns the ROSA subscription, account roles, operator roles, and KMS key
- AWS CLI profiles configured for both accounts
- Resource sharing enabled from the management account for your organization
- Sufficient quotas: at least 3
m5.xlargeinstances, 1 Elastic IP, 1 NAT Gateway, 2 Route 53 hosted zones - OpenShift version 4.17.9 or later
Tip: For testing, both accounts can be the same AWS account. The tutorial indicates where you can skip cross-account steps in that scenario.
IAM Roles and Policies Reference
Before starting, review the full set of IAM roles required by the shared VPC pattern.
Shared VPC Account Roles
These roles are created in the VPC Owner account and assumed by ROSA components from the Cluster Creator account.
1. Route 53 Role — <cluster>-route53-role
Allows ROSA to manage DNS records in the shared VPC’s private hosted zones.
Trust policy (final, after Step 9):
Permissions policy: AWS managed
ROSASharedVPCRoute53Policy
| Action | Scope |
|---|---|
route53:ChangeResourceRecordSets | Restricted to *.hypershift.local and *.openshiftapps.com patterns |
route53:GetHostedZone | All hosted zones |
route53:ListHostedZones | All |
route53:ListResourceRecordSets | All |
route53:ChangeTagsForResource | Hosted zones |
tag:GetResources | All |
Assumed by:
| Principal | Purpose |
|---|---|
| Installer Role | Initial DNS setup during cluster creation |
| ingress-operator | Ongoing DNS record management for app routes |
| control-plane-operator | DNS management for HCP internal communication |
2. VPC Endpoint Role — <cluster>-vpc-endpoint-role
Allows ROSA to create and manage PrivateLink VPC endpoints for the HCP control plane.
Trust policy (final, after Step 9):
Permissions policy: AWS managed
ROSASharedVPCEndpointPolicy
| Action | Scope |
|---|---|
ec2:CreateVpcEndpoint | With red-hat-managed tag condition |
ec2:ModifyVpcEndpoint, ec2:DeleteVpcEndpoints | With red-hat-managed tag condition |
ec2:CreateSecurityGroup, ec2:DeleteSecurityGroup | With red-hat-managed tag condition |
ec2:AuthorizeSecurityGroupIngress/Egress | With red-hat-managed tag condition |
ec2:CreateTags | Restricted to CreateVpcEndpoint and CreateSecurityGroup actions |
Assumed by:
| Principal | Purpose |
|---|---|
| Installer Role | Initial VPC endpoint creation |
| control-plane-operator | Ongoing VPC endpoint lifecycle management |
Cluster Account Roles (rosa CLI)
Account roles — created by rosa create account-roles --hosted-cp:
| Role | Purpose |
|---|---|
<PREFIX>-HCP-ROSA-Installer-Role | Cluster installation and initial setup |
<PREFIX>-HCP-ROSA-Support-Role | Red Hat SRE support access |
<PREFIX>-HCP-ROSA-Worker-Role | Worker node instance profile |
Operator roles — created by rosa create operator-roles --hosted-cp:
| Role | Namespace | Purpose |
|---|---|---|
<PREFIX>-kube-system-capa-controller-manager | kube-system | Cluster API AWS controller |
<PREFIX>-kube-system-control-plane-operator | kube-system | HCP control plane management |
<PREFIX>-kube-system-kms-provider | kube-system | KMS encryption for etcd |
<PREFIX>-kube-system-kube-controller-manager | kube-system | Kubernetes controller manager |
<PREFIX>-openshift-cloud-network-config-controller-cloud-credential | openshift-cloud-network-config-controller | Cloud network config |
<PREFIX>-openshift-cluster-csi-drivers-ebs-cloud-credentials | openshift-cluster-csi-drivers | EBS CSI driver |
<PREFIX>-openshift-image-registry-installer-cloud-credentials | openshift-image-registry | Image registry S3 backend |
<PREFIX>-openshift-ingress-operator-cloud-credentials | openshift-ingress-operator | Ingress DNS management |
When you pass
--route53-role-arnand--vpc-endpoint-role-arnto therosa create account-rolesandrosa create operator-rolescommands, the CLI automatically configures the operator roles withsts:AssumeRoleinline policies for the shared VPC roles.
KMS Key Policy
The customer-managed KMS key policy grants each ROSA operator only the minimum permissions required:
| Principal | KMS Actions |
|---|---|
| Account root | kms:* (administrative) |
| Installer Role | CreateGrant, DescribeKey, GenerateDataKeyWithoutPlaintext |
| Support Role | DescribeKey |
| Kube Controller Manager | DescribeKey |
| KMS Provider (etcd) | Encrypt, Decrypt, DescribeKey |
| CAPA Controller Manager | DescribeKey, GenerateDataKeyWithoutPlaintext, CreateGrant |
| EBS CSI Driver | Encrypt, Decrypt, ReEncrypt*, GenerateDataKey*, DescribeKey |
| EBS CSI Driver (grants) | CreateGrant, RevokeGrant, ListGrants (condition: kms:GrantIsForAWSResource) |
Route 53 Hosted Zone Naming
ROSA HCP validates that hosted zone names match specific patterns. Incorrect naming causes cluster creation to fail.
| Zone | Name Pattern | Example |
|---|---|---|
| HCP internal | <cluster_name>.hypershift.local | mycluster.hypershift.local |
| Ingress | rosa.<cluster_name>.<base_dns_domain> | rosa.mycluster.abcd.p3.openshiftapps.com |
Important: The
base_dns_domainmust be reserved underp3.openshiftapps.com(the HCP architecture parent) viarosa create dns-domain --hosted-cp. Classic ROSA domains (p1) or custom domains are not compatible.
Step-by-Step Deployment
Step 1: Set Environment Variables
Set these variables in your terminal. They are referenced throughout the tutorial.
Single-account testing: Set both account IDs to the same value. Where the tutorial says “switch to the VPC Owner account,” you can skip the profile switch.
If you have separate AWS CLI profiles for each account:
Throughout the tutorial, commands that run against the VPC Owner account use --profile $VPC_OWNER_PROFILE and commands against the Cluster Creator account use --profile $CLUSTER_CREATOR_PROFILE. Omit the --profile flag if you are using a single account.
Step 2: Create the VPC and Networking (VPC Owner Account)
Create the VPC with DNS support enabled:
Expected output:
Create an Internet Gateway:
Create three private subnets (one per Availability Zone):
Expected output:
Create a public subnet (for the NAT Gateway and optional bastion):
Create a NAT Gateway for outbound internet access from private subnets:
Create route tables and associate subnets:
Step 3: Create Shared VPC IAM Roles (VPC Owner Account)
Create the Route 53 role with the AWS managed ROSASharedVPCRoute53Policy. The initial trust policy uses the cluster account root — it will be tightened to specific role ARNs in Step 9.
Expected output:
Create the VPC Endpoint role with the AWS managed ROSASharedVPCEndpointPolicy:
Expected output:
Step 4: Create Route 53 Private Hosted Zones (VPC Owner Account)
ROSA HCP requires two private hosted zones with specific naming patterns. Create them now; the DNS domain from Step 5 is needed for the ingress zone name, so if you have not yet reserved a domain, skip this step and return after Step 5.
If you already know your
base_dns_domain, proceed here. Otherwise, complete Step 5 first, then return.
Create the HCP internal hosted zone (<cluster>.hypershift.local):
Expected output:
Create the Ingress hosted zone (rosa.<cluster>.<base_dns_domain>):
Expected output:
Step 5: Reserve an HCP DNS Domain (Cluster Creator Account)
Shared VPC HCP clusters require a base_dns_domain registered under the p3.openshiftapps.com parent:
Expected output:
Confirm and save the domain:
Expected output:
If you skipped Step 4, go back now and create the hosted zones using this domain.
Step 6: Create OIDC Config (Cluster Creator Account)
Expected output:
Save the OIDC Config ID — it is required for operator roles and cluster creation.
Step 7: Create Account Roles (Cluster Creator Account)
Pass the shared VPC role ARNs so the CLI configures the roles for cross-account access:
Expected output:
Retrieve the Installer Role ARN:
Verify:
Expected output:
Step 8: Create Operator Roles (Cluster Creator Account)
Expected output:
Verify:
Save the key operator role ARNs for later steps:
Step 9: Update Shared VPC Trust Policies (VPC Owner Account)
Now that the ROSA roles exist, tighten the trust policies on the shared VPC roles to only allow the specific roles that need access. This replaces the broad root trust from Step 3.
Update the Route 53 role trust policy:
Update the VPC Endpoint role trust policy:
IAM propagation: AWS IAM changes are eventually consistent and can take 5–15 seconds to propagate globally. Wait before proceeding to cluster creation.
Step 10: Create a Customer-Managed KMS Key (Cluster Creator Account) — Optional
If you want customer-managed encryption for etcd and EBS volumes, create a KMS key with a policy granting the ROSA operator roles access.
Retrieve the remaining operator role ARNs:
Create the KMS key policy:
Create the key:
Expected output:
Step 11: Create the ROSA HCP Cluster (Cluster Creator Account)
Assemble the rosa create cluster command with all the shared VPC parameters:
Without KMS: Omit the
--kms-key-arn,--etcd-encryption, and--etcd-encryption-kms-arnflags if you skipped Step 10.
Expected output:
Monitor the installation:
Or check the status periodically:
Expected states: waiting → installing → ready (takes 20–30 minutes).
When the cluster reaches ready:
Expected output:
Step 12: Access the Private Cluster
The cluster API is private and not reachable from the internet. Set up a bastion host in the shared VPC.
Launch a bastion instance
Connect using sshuttle (recommended)
sshuttle
creates a transparent VPN over SSH. All traffic to the VPC CIDR is routed through the bastion — no per-command proxy needed, and browser access works out of the box.
Use the absolute path to the SSH key (
${HOME}/.ssh/not~/.ssh/) becausesudoruns as root.
Alternative: SOCKS proxy
Step 13: Log In and Verify the Cluster
Create a temporary cluster admin:
Expected output:
Wait 1–2 minutes for the admin to propagate, then log in:
Verify the nodes:
Expected output:
Verify the cluster version:
Expected output:
Verify KMS encryption (if enabled):
Verify the shared VPC connectivity:
Cleanup
1. Delete the ROSA cluster
This takes 10–15 minutes. Wait for completion before proceeding.
2. Clean up rosa CLI resources
3. Delete the KMS key (if created)
4. Terminate the bastion
5. Delete Route 53 hosted zones (VPC Owner Account)
Hosted zones must be empty (only NS and SOA records) before deletion:
If deletion fails with
HostedZoneNotEmpty, list and delete non-NS/SOA records first:
6. Delete shared VPC IAM roles (VPC Owner Account)
7. Delete VPC resources (VPC Owner Account)
Resources must be deleted in reverse dependency order: