Skip to content

Create a GCP Hosted Cluster

This guide walks through creating a GCP hosted cluster using the infrastructure and IAM resources created in the previous steps.

Prerequisites

Create Hosted Cluster

hypershift create cluster gcp \
  --name=<cluster-name> \
  --namespace=<namespace> \
  --release-image=<release-image> \
  --pull-secret=<path-to-pull-secret> \
  --project=<hosted-cluster-project-id> \
  --region=<region> \
  --network=<vpc-name> \
  --subnet=<subnet-name> \
  --private-service-connect-subnet=<psc-subnet> \
  --endpoint-access=PublicAndPrivate \
  --workload-identity-project-number=<project-number> \
  --workload-identity-pool-id=<pool-id> \
  --workload-identity-provider-id=<provider-id> \
  --control-plane-service-account=<controlplane-sa-email> \
  --node-pool-service-account=<nodepool-sa-email> \
  --cloud-controller-service-account=<cloud-controller-sa-email> \
  --storage-service-account=<storage-sa-email> \
  --image-registry-service-account=<image-registry-sa-email> \
  --network-service-account=<network-sa-email> \
  --service-account-signing-key-path=<path-to-sa-signer.key> \
  --oidc-issuer-url=<oidc-issuer-url> \
  --base-domain=<your-dns-domain> \
  --external-dns-domain=<your-dns-domain> \
  --node-pool-replicas=2 \
  --feature-set=TechPreviewNoUpgrade \
  --annotations=hypershift.openshift.io/pod-security-admission-label-override=baseline

Pod Security Admission Override Required

GKE clusters enforce pod security policies that block some HyperShift control plane components from starting without the baseline override.

CAPG Image Override Required for 4.22.x/4.23.x only (GCP-841)

The CAPG image in these releases crashes due to a removed ClusterResourceSet feature gate. Add the CAPG image annotation:

--annotations="hypershift.openshift.io/pod-security-admission-label-override=baseline,hypershift.openshift.io/capi-provider-gcp-image=<capg-image>"

Get the CAPG image from the release payload:

oc adm release info <release-image> --image-for=cluster-api-provider-gcp

Flags

Flag Required Description
--name Yes Name for the hosted cluster
--namespace Yes Namespace for the HostedCluster resource
--release-image Yes OpenShift release image
--pull-secret Yes Path to pull secret file
--project Yes Hosted cluster GCP project ID
--region Yes GCP region
--network Yes VPC network name (from create infra gcp output)
--subnet Yes Subnet for worker nodes (from create infra gcp output: subnetName)
--private-service-connect-subnet Yes Subnet for PSC endpoints (same as --subnet)
--endpoint-access Yes Private or PublicAndPrivate
--workload-identity-project-number Yes GCP project number (from create iam gcp output)
--workload-identity-pool-id Yes WIF pool ID (from create iam gcp output)
--workload-identity-provider-id Yes WIF provider ID (from create iam gcp output)
--control-plane-service-account Yes Control Plane Operator SA email
--node-pool-service-account Yes NodePool CAPG SA email
--cloud-controller-service-account Yes Cloud Controller Manager SA email
--storage-service-account Yes GCP PD CSI Driver SA email
--image-registry-service-account Yes Image Registry Operator SA email
--network-service-account Yes Cloud Network Config Controller SA email
--service-account-signing-key-path Yes Path to RSA private key for OIDC token signing
--oidc-issuer-url Yes OIDC issuer URL
--node-pool-replicas Yes Number of worker nodes (default: 0)
--base-domain Yes Base DNS domain for the hosted cluster
--external-dns-domain Yes DNS domain for ExternalDNS-managed hostnames (API server, OAuth)
--feature-set Yes Must be TechPreviewNoUpgrade for GCP platform
--machine-type No GCP machine type (default: n2-standard-4)
--zone No GCP zone for nodes (default: {region}-a)
--boot-image No Override RHCOS boot image from release payload

Monitor Cluster Creation

Watch the hosted cluster status:

oc get hostedcluster -n <namespace> <cluster-name> -w

Wait for the Available condition to be True:

oc wait --for=condition=Available hostedcluster/<cluster-name> -n <namespace> --timeout=30m

Access the Hosted Cluster

Retrieve the kubeconfig:

oc get secret <cluster-name>-admin-kubeconfig -n <namespace> -o jsonpath='{.data.kubeconfig}' | base64 -d > hosted-kubeconfig

Verify access:

KUBECONFIG=hosted-kubeconfig oc get nodes
KUBECONFIG=hosted-kubeconfig oc get clusterversion

Image Registry

GCP hosted clusters automatically configure the OpenShift image registry using Workload Identity Federation (WIF). The --image-registry-service-account flag passed at cluster creation supplies the GCP service account (GSA) that the registry operator uses to access GCS.

The flow is:

  1. The HyperShift control plane generates a WIF credential for the image-registry GSA and writes it to the installer-cloud-credentials secret in the openshift-image-registry namespace.
  2. The cluster image registry operator reads the credential and creates a GCS bucket in the hosted cluster project.
  3. The registry becomes available at image-registry.openshift-image-registry.svc:5000.

Verify Registry Status

KUBECONFIG=hosted-kubeconfig oc get clusteroperator image-registry

The AVAILABLE column should be True within a few minutes of nodes joining.

Inspect the GCS bucket chosen by the registry operator:

KUBECONFIG=hosted-kubeconfig oc get configs.imageregistry.operator.openshift.io cluster \
  -o jsonpath='{.spec.storage}'

Disable the Image Registry

Add --capabilities-disabled=ImageRegistry to the hypershift create cluster gcp command to skip deploying the registry operator and suppress GCS bucket creation.

To disable the registry on a running cluster, patch the HostedCluster resource:

oc patch hostedcluster <cluster-name> -n <namespace> \
  --type=merge \
  --patch='{"spec":{"capabilities":{"disabled":["ImageRegistry"]}}}'

For advanced scenarios (custom bucket, pre-existing bucket, troubleshooting WIF auth), see Configure Image Registry on GCP.

Destroy Hosted Cluster

hypershift destroy cluster gcp \
  --name=<cluster-name> \
  --namespace=<namespace>

After the cluster is destroyed, clean up the infrastructure and IAM resources:

hypershift destroy infra gcp \
  --infra-id=<infra-id> \
  --project-id=<hosted-cluster-project-id> \
  --region=<region>

hypershift destroy iam gcp \
  --infra-id=<infra-id> \
  --project-id=<hosted-cluster-project-id>

Troubleshooting

Check Hosted Control Plane Pods

oc get pods -n <namespace>-<cluster-name>

Check HostedCluster Conditions

oc get hostedcluster -n <namespace> <cluster-name> -o jsonpath='{range .status.conditions[*]}{.type}={.status} {.message}{"\n"}{end}'

Check NodePool Status

oc get nodepool -n <namespace> -o yaml

Common Issues

  • WIF validation fails — Ensure all service account emails match the output from create iam gcp
  • PSC endpoint not available — Verify the operator has WIF credentials and the PSC subnet exists
  • Nodes not joining — Check that the boot image is available and the hosted cluster project has compute API enabled
  • Image registry operator not available — Confirm the installer-cloud-credentials secret exists in openshift-image-registry and the WIF credential references the correct pool/provider; see Configure Image Registry on GCP for details
  • GCS bucket creation fails (403) — The image-registry GSA is missing roles/storage.admin; grant it with gcloud projects add-iam-policy-binding or re-run hypershift create iam gcp