Deploying ARO HCP with Terraform
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.22. 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 OpenShift control plane as a fully managed service in a Microsoft-managed subscription, separate from your worker nodes. For product overview, comparison with classic ARO, and benefits, read Azure Red Hat OpenShift with hosted control planes now available in public preview (Microsoft).
This guide covers a public cluster deployment (clusters/public): public API and ingress. For private API or ingress, use
clusters/private
and the
private cluster steps
in the reference docs.
Looking for a simple Azure CLI example rather than a hardened production deployment? Follow Create an ARO with hosted control planes cluster (Azure CLI) on Microsoft Learn.
Public preview
ARO HCP is in public preview , not GA. APIs, regions, quotas, and supported features may change before GA.
Classic ARO (control plane in your subscription) remains fully supported and is the default GA path today: ARO Quickstart or Deploying ARO using Terraform .
Technical reference (Microsoft Learn): Introduction · Quickstart · Connect · Red Hat announcement
Terraform reference
validated-pattern-aro-hcp is a Terraform implementation maintained by Red Hat Cloud Experts for production-style deployments: least-privilege managed identities and RBAC, Entra external OIDC, optional OpenShift GitOps bootstrap, and Makefile wrappers for credentials and teardown. Reference docs: rh-mobb.github.io/validated-pattern-aro-hcp .
Microsoft’s CLI and Bicep quickstarts remain the product source of truth for ARO HCP behavior and limits. Use this repo when you want a Terraform path you can fork and adapt.
Guide overview
Work through these sections in order:
- Prerequisites : Azure subscription, clone the reference repo, install tooling, and confirm permissions.
-
Plan your deployment
: Choose cluster settings and edit
terraform.tfvarsbefore apply. Most values are permanent. - Deploy the cluster : Create a cluster profile and run Terraform.
-
Connect and configure
: After the cluster reaches
Succeeded, request credentials, configure Entra console login, and verify.
Architecture overview
You provision resources in your customer subscription and connect them to the hosted control plane in a Microsoft-managed subscription via a delegated VNet integration subnet. Product architecture: Introduction to Azure Red Hat OpenShift .
Conceptual deployment topology. Minimum footprint: two worker nodes.
Prerequisites
Meet Microsoft’s prerequisites first. Source: Prepare your environment .
Azure subscription
| Requirement | Notes |
|---|---|
| Azure CLI | Version 2.67.0 or later (az --version) |
| ARO HCP CLI extension | Required for az aro hcp commands (installed by make setup in the reference repo) |
| Contributor + User Access Administrator, or Owner | On the resource group or subscription where you create the cluster ( Permissions ) |
| Resource providers registered | Microsoft.RedHatOpenShift, Microsoft.Compute, Microsoft.Storage, Microsoft.Authorization (
Register resource providers
) |
| Compute quota | Microsoft documents at least 20 cores in your subscription ( Resource quota ). Verify quota for your chosen supported worker VM size in your region |
| Supported region |
Preview regions
: australiaeast, brazilsouth, canadacentral, centralindia, eastus2, switzerlandnorth, uksouth, westeurope |
Register providers (if needed):
Check quota (adjust the VM family for your node pool SKU):
Quota vs. reference defaults
Microsoft’s 20-core requirement is subscription quota, not the worker vCPU count in terraform.tfvars. The
default quickstart
uses two Standard_D8s_v3 workers; the reference defaults to two Standard_D4s_v6 workers. Pick a supported size and replica count that fit your workload and quota.
External authentication (plan ahead)
ARO HCP uses external OIDC authentication. Unlike classic ARO, the built-in OpenShift OAuth server is not available ( Authentication model ).
The reference repo creates the Entra app registration during Terraform apply when enable_external_auth = true (the default). The account running apply still needs Entra directory rights to create app registrations, not just Azure subscription RBAC. After the cluster is ready, apply the console OAuth secret in
Connect and configure
. See
External auth with Entra ID
if that step fails.
Get the reference repository
Clone the repo and install the az aro hcp CLI extension before planning or deploying:
Operator tooling
| Tool | Minimum | When you need it |
|---|---|---|
| Terraform | >= 1.9 | Deploy step |
jq |
any recent | Helper scripts in the reference repo |
oc
|
Match cluster version | After cluster create ( request admin credentials ) |
Red Hat pull secret (optional)
registry.redhat.io if you run the optional GitOps bootstrap later.- Browse to https://console.redhat.com/openshift/install/azure/aro-provisioned
- Download the pull secret (for example to
~/Downloads/pull-secret.txt). - Restrict permissions:
chmod 600 ~/Downloads/pull-secret.txt. Never commit this file.
Plan your deployment
Microsoft Learn organizes ARO HCP planning into three topics. Each maps to keys in clusters/<name>/terraform.tfvars. Most settings are permanent: changing them after create requires deleting and recreating the cluster.
Complete this section before you run make cluster.<name>.apply. Official Microsoft articles are the source of truth for trade-offs; the tables below show how those decisions appear in the Terraform reference.
Cluster profile
This guide uses
clusters/public
. Copy it to clusters/my-cluster (or your chosen name); each profile has its own terraform.tfvars and state under clusters/<name>/.
Other committed profiles in the repo include
clusters/private
and
clusters/aro-virt
. See the
reference docs
for those paths.
Full variable definitions:
terraform/variables.tf
.
Permanent cluster settings
Official guide: Choose your permanent cluster settings (preview).
| Official decision | terraform.tfvars key |
Default (reference) | Notes |
|---|---|---|---|
| Cluster region | location |
uksouth |
Must be a preview region |
| Cluster name | cluster_name |
(required) | Prefixes RG, VNet, identities, and subnets unless overridden |
| OpenShift version stream | cluster_version |
4.22 |
X.Y stream; plan fails if not enabled in location |
| Update channel | cluster_channel |
stable |
e.g. stable, fast |
| API server visibility | api_visibility |
Public |
This guide keeps Public (
other options
) |
| Default ingress visibility | ingress_visibility |
Public |
This guide keeps Public (
other options
) |
| etcd KMS Key Vault visibility | vault_visibility |
Public |
Public or Private for customer Key Vault |
| Internal image registry | cluster_image_registry_state |
Enabled |
Enabled or Disabled (create-time only) |
| Outbound connectivity | outbound_type |
LoadBalancer |
Load Balancer only |
| Red Hat pull secret | pull_secret_path |
../tmp/pull-secret.txt in examples |
Written to Key Vault; never commit the file |
| Entra OIDC | enable_external_auth |
true |
Terraform creates the Entra app at apply time; console secret is applied after cluster create |
| Extra OIDC redirect URIs | oidc_web_redirects |
RHOAI callback by default | Reference repo only |
Fixed in reference Terraform (not exposed as variables today):
| Official decision | Reference behavior |
|---|---|
| CNI plugin | OVNKubernetes only (
default quickstart
) |
| DNS base domain | Service-generated (dns = {}) |
| FIPS mode | Not exposed yet; use the official CLI/Bicep path if required |
Example:
Cluster network and node pools
Official guide: Plan your cluster network (preview).
| Official topic | terraform.tfvars key |
Default | Notes |
|---|---|---|---|
| Machine (VNet) CIDR | address_prefix |
10.0.0.0/16 |
Must cover all worker, integration, and optional pool subnets |
| Worker subnet | subnet_prefix |
10.0.0.0/24 |
Default node pool unless node_pools.<name>.subnet_id is set |
| VNet integration subnet | vnet_integration_subnet_prefix |
10.0.1.0/24 |
Minimum /29 (
subnet requirements
) |
| Service CIDR | service_cidr |
172.30.0.0/16 |
Must not overlap VNet or pod CIDR |
| Pod CIDR | pod_cidr |
10.128.0.0/14 |
Must not overlap VNet or service CIDR |
| Host prefix | host_prefix |
23 |
/23 per node from pod CIDR |
| Resource naming | vnet_name, subnet_name, etc. |
derived from cluster_name |
Override when integrating with existing names |
| Node pools | node_pools |
np-1: 2 × Standard_D4s_v6, zone 1 |
VM size, replicas, zones, autoscaling, taints, labels |
| Node pool patch | node_pool_version, node_pool_channel |
4.22.12, stable |
Align with control plane patch in the same channel |
The reference repo creates the NSG and rules from Required network security group traffic .
Example:
Managed identities and RBAC
Official guide: Required managed identities and role assignments (preview).
Microsoft documents 13 user-assigned managed identities and their role assignments. You do not declare them in terraform.tfvars; the reference modules/identities creates them during apply.
| Responsibility | Microsoft docs | Reference repo |
|---|---|---|
| Deployer RBAC | Contributor + User Access Administrator or Owner | Same; needed to create role assignments during apply |
| Managed identities | Create before cluster create | modules/identities in Terraform |
| External OIDC | Required for user authentication | enable_external_auth = true; console secret applied post-create |
| etcd customer-managed key | Key Vault, KMS key, KMS identity ( encryption strategy ) | modules/network; vault_visibility for Key Vault access |
To customize beyond the reference module, fork validated-pattern-aro-hcp or follow Create an ARO with hosted control planes cluster .
Deploy the cluster
From the cloned validated-pattern-aro-hcp directory:
1. Create a cluster profile
Copy the public example (see Cluster profile ):
2. Edit terraform.tfvars
Apply the decisions from
Plan your deployment
. At minimum, set location, cluster_name, and cluster_version.
Optional: list OpenShift versions enabled in your region before plan, and align cluster_version and node_pool_version in terraform.tfvars:
plan fails fast if cluster_version is not enabled in location.
If you use a pull secret:
Check for environment variables that override tfvars:
Unset or align any TF_VAR_* values before apply.
3. Initialize, plan, and apply
Wait until the cluster reaches provisioningState: Succeeded before continuing.
Connect and configure
Run these steps after the cluster is ready. Administrative credentials expire after
24 hours
; re-run kubeconfig when they expire.
1. Request admin credentials
This wraps az aro hcp cluster request-credential --admin and writes kubeconfig to .kube/config.
2. Configure Entra console login
This applies the console OAuth secret for the Entra app Terraform created during apply. If this step fails with Entra permission errors, see External auth with Entra ID .
3. Verify
The console URL from az aro hcp cluster show should return HTTP 200 after external-auth completes.
4. Optional GitOps bootstrap
Optional operators (OpenShift GitOps, Web Terminal, Compliance Operator, External Secrets):
See GitOps bootstrap in the reference repo.
Teardown
Do not run terraform destroy alone. The last node pool cannot be deleted independently (
OCPBUGS-86702
). Use the Makefile destroy target.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Cluster create permission error | Insufficient RBAC | Verify Contributor + User Access Administrator or Owner . See managed identities |
Console 503 / degraded console CO |
Console OAuth secret not applied | Run make cluster.<name>.external-auth after cluster is ready |
| Credential POST 404 | Cluster not ready | Wait for provisioningState: Succeeded |
| Admin kubeconfig expired | 24-hour TTL | make cluster.<name>.kubeconfig again |
| Last node pool delete 409 | OCPBUGS-86702 | make cluster.<name>.destroy only |
az ad app create insufficient privileges |
User app registration disabled in tenant | Application Developer or Cloud Application Administrator role |
Extended troubleshooting: reference README .
Related guides
Official documentation (Microsoft and Red Hat)
| Topic | Link |
|---|---|
| Architecture overview | Introduction to Azure Red Hat OpenShift |
| Standard vs hosted control planes | Compare architectures |
| Permanent cluster settings | Choose your permanent cluster settings |
| Network planning | Plan your cluster network |
| Managed identities and RBAC | Required managed identities and role assignments |
| Create a cluster (CLI/Bicep) | Create an ARO with hosted control planes cluster |
| Create a cluster (defaults quickstart) | Quickstart: default hosted cluster |
| Connect to a cluster | Connect to an ARO with hosted control planes cluster |
| Delete a cluster | Delete an ARO with hosted control planes cluster |
Red Hat Cloud Experts reference (Terraform)
| Topic | Link |
|---|---|
| Reference docs (full site) | rh-mobb.github.io/validated-pattern-aro-hcp |
| Private cluster profile | Quick start (private cluster) |
| Account prerequisites and RBAC matrix | Account prerequisites |
| External auth (Entra ID) | External auth guide |
| OpenShift Virtualization full stack | Virt stack |
| Classic ARO quickstart | ARO Quickstart |
| Classic ARO Terraform | Deploying ARO using Terraform |
| ROSA HCP Terraform (AWS) | Deploying a ROSA HCP cluster with Terraform |