Install and operate

GCP HyperShift Setup & Operation

Complete guide for setting up and managing Sentinel HyperShift clusters on Google Cloud Platform.

WARNING: UNVERIFIED DRAFT. GCP HyperShift is tech preview upstream, requires a GKE Autopilot management cluster and Workload Identity (not service-account JSON keys). Steps, IAM roles, quotas, costs and links below were written before verification and must not be followed as-is. See "GCP Verification" in docs/_internal/superpowers/specs/2026-10-11-multicloud-hypershift-design.md.

Status: Not implemented (Phase 3 blocked)
Timeline: See Design Spec


Prerequisites#

Tools Required#

Tool Version Purpose
gcloud CLI Latest GCP resource management
kubectl 1.28+ Kubernetes cluster interaction
jq Latest JSON processing
Bash 3.2+ Script execution
Python 3.11+ E2E tests

macOS Installation#

# gcloud CLI
curl https://sdk.cloud.google.com | bash
exec -l $SHELL  # Restart shell

# Other tools
brew install kubectl jq python@3.11

Linux (Ubuntu/Debian)#

# gcloud CLI
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | \
  sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list

curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | \
  sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add -

sudo apt-get update
sudo apt-get install -y google-cloud-sdk kubectl jq python3.11

GCP Project Requirements#

  1. GCP Project with billing enabled
  2. Compute quota (default usually sufficient): - Compute Engine VMs: 10+ - vCPUs: 50+ - Persistent Disks: 50+ - In-use IP addresses: 10+ - Load balancers: 10+
  3. Cloud DNS zone (for cluster API endpoints)
  4. Service account (for HyperShift)

One-Time Setup (GCP Admin)#

These steps run once to prepare your GCP project. You need admin access only for this phase.

Step 1: Authenticate with gcloud#

# Login to GCP
gcloud auth login

# Set your project
export GCP_PROJECT_ID="my-project-id"
gcloud config set project $GCP_PROJECT_ID

# Verify
gcloud auth list
gcloud config get-value project

Step 2: Enable Required APIs#

# Enable necessary APIs
gcloud services enable \
  compute.googleapis.com \
  cloudresourcemanager.googleapis.com \
  iam.googleapis.com \
  dns.googleapis.com \
  container.googleapis.com \
  containerregistry.googleapis.com

Step 3: Create Cloud DNS Zone#

HyperShift needs a delegated DNS zone for cluster APIs:

# Create Cloud DNS zone
gcloud dns managed-zones create sentinel-hcp \
  --dns-name=sentinel-dev.example.com \
  --description="HyperShift clusters"

# Get nameservers
gcloud dns managed-zones describe sentinel-hcp --format='value(nameServers)'

# Output: [ns-123.googledomains.com., ns-456.googledomains.com., ...]

# Delegate from your domain registrar:
# Update your domain's nameservers to point to the above

Verify delegation (may take a few minutes):

dig ns sentinel-dev.example.com
# Should show Google nameservers

Step 4: Create Service Account#

HyperShift needs a service account with permissions to create resources:

# Create service account
gcloud iam service-accounts create sentinel-hcp \
  --display-name="Sentinel HyperShift Service Account"

# Get service account email
export SERVICE_ACCOUNT_EMAIL="sentinel-hcp@${GCP_PROJECT_ID}.iam.gserviceaccount.com"

# Grant required roles
gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \
  --member=serviceAccount:$SERVICE_ACCOUNT_EMAIL \
  --role=roles/compute.admin

gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \
  --member=serviceAccount:$SERVICE_ACCOUNT_EMAIL \
  --role=roles/dns.admin

gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \
  --member=serviceAccount:$SERVICE_ACCOUNT_EMAIL \
  --role=roles/iam.securityAdmin

gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \
  --member=serviceAccount:$SERVICE_ACCOUNT_EMAIL \
  --role=roles/resourcemanager.projectIamAdmin

Step 5: Create Service Account Key#

# Create key (JSON format)
gcloud iam service-accounts keys create \
  ~/gcp-sentinel-hcp-key.json \
  --iam-account=$SERVICE_ACCOUNT_EMAIL

# Keep this file secure (git-ignored)
ls -la ~/gcp-sentinel-hcp-key.json

# Base64 encode it (for GitHub Actions)
cat ~/gcp-sentinel-hcp-key.json | base64 -w0

Step 6: Login to Management Cluster#

You need cluster-admin access to the existing HyperShift management cluster:

# Get management cluster kubeconfig (from whoever set it up)
export KUBECONFIG=~/.kube/hypershift_mgmt

# Verify access
kubectl cluster-info
kubectl get ns | grep hypershift

Step 7: Create Scoped Credentials#

This creates GCP IAM bindings for HyperShift:

# Run the credential setup script
./.github/scripts/hypershift/cloud/gcp/setup-credentials.sh

# This:
# 1. Creates service account bindings
# 2. Creates GCP IAM roles for hosted control planes
# 3. Creates OpenShift service account
# 4. Outputs: .env.sentinel-hypershift-gcp

Output: .env.sentinel-hypershift-gcp (git-ignored)

# Contents:
export CLOUD_PLATFORM=gcp
export GCP_PROJECT_ID=my-project-id
export GCP_REGION=us-central1
export GCP_SERVICE_ACCOUNT_JSON=$(cat ~/gcp-sentinel-hcp-key.json | base64 -w0)
export HYPERSHIFT_MGMT_KUBECONFIG=~/.kube/hypershift_mgmt
export PULL_SECRET=$(cat ~/.docker/config.json)
export BASE_DOMAIN=sentinel-dev.example.com
export MANAGED_BY_TAG=sentinel-hypershift-custom
export GCP_HCP_ROLE_NAME=sentinel-hypershift-custom-hcp-role

Step 8: Verify Setup#

# Load the new GCP credentials
source .env.sentinel-hypershift-gcp

# Run preflight check
./.github/scripts/hypershift/cloud/gcp/preflight-check.sh

# Output should show:
# ✓ GCP credentials valid
# ✓ Management cluster accessible
# ✓ Cloud DNS zone exists
# ✓ Quotas sufficient
# ✓ Pull secret present

✅ One-time setup complete! You now have GCP credentials for daily development.


Daily Usage (Scoped Credentials)#

After one-time setup, use these credentials for all cluster operations.

Quick Start#

# 1. Load your GCP credentials
source .env.sentinel-hypershift-gcp

# 2. Create a cluster
./.github/scripts/hypershift/create-cluster.sh

# Wait 15-20 minutes...
# ✓ Cluster created on GCP
# ✓ Kubeconfig saved to ~/.clusters/hcp/<cluster-name>/

# 3. Use the cluster
export KUBECONFIG=~/.clusters/hcp/sentinel-hypershift-custom-gcp-<suffix>/auth/kubeconfig
kubectl get nodes

# 4. Run tests
uv run pytest sentinel/tests/e2e/ -v

# 5. Cleanup
./.github/scripts/hypershift/destroy-cluster.sh <suffix>

Cluster Naming#

Clusters are named: sentinel-hypershift-custom-gcp-${SUFFIX}

Suffix options:

# Default: Your username (automatically sanitized)
./.github/scripts/hypershift/create-cluster.sh
# → sentinel-hypershift-custom-gcp-ladas

# Custom suffix
./.github/scripts/hypershift/create-cluster.sh pr529
# → sentinel-hypershift-custom-gcp-pr529

# Random suffix
CLUSTER_SUFFIX="" ./.github/scripts/hypershift/create-cluster.sh
# → sentinel-hypershift-custom-gcp-abc123

Accessing the Cluster#

# List available kubeconfigs
ls ~/.clusters/hcp/

# Set kubeconfig for your cluster
export KUBECONFIG=~/.clusters/hcp/sentinel-hypershift-custom-gcp-pr529/auth/kubeconfig

# Verify access
kubectl cluster-info
kubectl get nodes
kubectl get pods -A

Destroying Clusters#

# Destroy specific cluster
./.github/scripts/hypershift/destroy-cluster.sh pr529

# Or by full name
./.github/scripts/hypershift/destroy-cluster.sh sentinel-hypershift-custom-gcp-pr529

Important: Always destroy test clusters to avoid GCP costs!


Configuration#

Cluster Parameters#

Control cluster characteristics via environment variables:

# Number of worker nodes (default: 2)
export REPLICAS=3
./.github/scripts/hypershift/create-cluster.sh

# Machine type (default: n1-standard-4)
export MACHINE_TYPE=n1-standard-8
./.github/scripts/hypershift/create-cluster.sh

# OpenShift version (default: 4.20.11)
export OCP_VERSION=4.19.12
./.github/scripts/hypershift/create-cluster.sh

# Autoscaling (default: min=2, max=5)
export AUTOSCALE_MIN=1
export AUTOSCALE_MAX=10
./.github/scripts/hypershift/create-cluster.sh

# Disable autoscaling
export AUTOSCALE_MIN=""
export AUTOSCALE_MAX=""
./.github/scripts/hypershift/create-cluster.sh

GCP Region#

# Create cluster in different region
export GCP_REGION=europe-west1
./.github/scripts/hypershift/create-cluster.sh

Supported regions: Any GCP region in your project


CI/CD Integration#

GitHub Actions Matrix#

Both AWS and GCP run simultaneously:

strategy:
  matrix:
    cloud: [aws, gcp]
  max-parallel: 2

Each cloud gets its own secrets and creates clusters independently.

Secrets Configuration#

  1. Go to Repository Settings → Secrets and variables → Actions
  2. Add these secrets (same names as .env file): - GCP_PROJECT_ID - GCP_REGION - GCP_SERVICE_ACCOUNT_JSON (base64) - HYPERSHIFT_MGMT_KUBECONFIG (base64) - PULL_SECRET (JSON) - BASE_DOMAIN - MANAGED_BY_TAG - GCP_HCP_ROLE_NAME

  3. Create Environments for e2e-aws and e2e-gcp with separate secret sets

Trigger E2E Tests#

# Automatic: Push to main or open PR
# Manual: GitHub Actions → e2e-hypershift → Run workflow

# Or via gh CLI
gh workflow run e2e-hypershift.yaml -f cluster_name=pr529

Troubleshooting#

Cluster Creation Fails#

Error: "ERROR: Quota exceeded"

Solution:

# Check your quotas
gcloud compute project-info describe --project=$GCP_PROJECT_ID | grep QUOTA

# View quota details
gcloud compute project-info describe --project=$GCP_PROJECT_ID \
  --format="value(commonInstanceMetadata.items.compute-max-cpu-instances)" \
  --format="value(quota.*)"

# Request quota increase in GCP Console
# IAM & Admin → Quotas → select resource → Edit Quotas → Request increase

Error: "ERROR: Cannot connect to management cluster"

Solution:

# Verify kubeconfig is set
echo $KUBECONFIG

# Verify it points to valid file
ls -la $KUBECONFIG

# Verify you can connect
kubectl cluster-info

Cluster Won't Delete#

Error: "ERROR: Timeout waiting for cluster deletion"

Solution:

# Check if control plane namespace is stuck
kubectl get ns clusters-sentinel-hypershift-custom-gcp-<suffix>

# Force delete if stuck
kubectl delete ns clusters-sentinel-hypershift-custom-gcp-<suffix> --grace-period=0 --force

# Check for orphaned GCP resources
./.github/scripts/hypershift/cloud/gcp/find-orphaned-resources.sh

# Manually delete via GCP Console if necessary
gcloud compute instances list --filter='labels.kubernetes_io_cluster_sentinel-hypershift-custom-gcp_*=owned'

Access Denied Errors#

Error: "Permission denied: 'compute.instances.create'"

Solution:

# Verify service account has permissions
gcloud projects get-iam-policy $GCP_PROJECT_ID \
  --flatten="bindings[].members" \
  --format='table(bindings.role)' \
  --filter="bindings.members:sentinel-hcp@*"

# Should show: roles/compute.admin, roles/dns.admin, roles/iam.securityAdmin

# If missing, re-run setup-credentials.sh

DNS Issues#

Error: "Could not resolve .sentinel-dev.example.com"

Solution:

# Verify BASE_DOMAIN is correct
echo $BASE_DOMAIN

# Verify Cloud DNS zone exists
gcloud dns managed-zones list | grep sentinel

# Check created DNS records
gcloud dns record-sets list --zone=sentinel-hcp

# Verify nameserver delegation (may take propagation time)
dig ns sentinel-dev.example.com

Cost Management#

Monitoring Costs#

# GCP Console → Billing → Cost Management
# Filter by label: sentinel.io/managed-by = sentinel-hypershift-custom

# Or via gcloud CLI
gcloud billing accounts list
gcloud billing accounts describe <account-id> --format=json

Cost Breakdown#

Per cluster (typical): - Compute Engine: $25-45/month - Cloud Load Balancer: $15/month - VPC/Network: $5/month - Cloud DNS: <$1/month - Total: ~$45-65/month

Cost Optimization#

  1. Destroy unused clusters (biggest cost driver)
  2. Use smaller machines for non-critical tests (n1-standard-2 instead of n1-standard-4)
  3. Reduce node count (1 node instead of 2 if possible)
  4. Schedule tests to run only during business hours
  5. Use sustained use discounts (longer-running clusters)

Debugging#

Cluster Status#

# Check if cluster is ready
kubectl get hostedcluster -n clusters

# Check control plane pod status
kubectl get pods -n clusters-<cluster-name>

# View cluster events
kubectl describe hostedcluster -n clusters <cluster-name>

Logs#

# HyperShift operator logs
kubectl logs -n hypershift-system deployment/hypershift-operator -f

# Control plane pod logs
kubectl logs -n clusters-<cluster-name> <pod-name>

# GCP resource creation logs
gcloud logging read --limit=50 --format=json | jq '.[] | select(.resource.type=="gce_instance")'

GCP Resources#

# View all Compute Engine instances with sentinel labels
gcloud compute instances list \
  --filter='labels.sentinel_io_managed_by=sentinel-hypershift-custom'

# View all Cloud DNS records
gcloud dns record-sets list --zone=sentinel-hcp

# View all network resources
gcloud compute networks list --filter='name~sentinel-hypershift'

# View firewall rules
gcloud compute firewall-rules list --filter='labels.sentinel_io_managed_by=sentinel-hypershift-custom'

Advanced: Custom VPC Configuration#

By default, HyperShift creates a new VPC for each cluster. To use existing VPC:

# Edit GCP Terraform to use existing VPC
# File: .github/scripts/hypershift/cloud/gcp/terraform/variables.tf

# Set network and subnet
export NETWORK="projects/<project>/global/networks/existing-vpc"
export SUBNET="projects/<project>/regions/<region>/subnetworks/existing-subnet"

./.github/scripts/hypershift/create-cluster.sh

Frequently Asked Questions#

Q: How long does cluster creation take?
A: 15-20 minutes typically. Monitor in CI logs or management cluster.

Q: Can I access the cluster while tests run?
A: Yes, kubeconfig is created immediately. Tests run concurrently.

Q: What happens to cluster after E2E tests?
A: It's automatically destroyed to save costs (unless you set skip_destroy=true).

Q: Can I use a different GCP region?
A: Yes, set GCP_REGION before creation.

Q: How much does a test cluster cost?
A: ~$2-3 per day (if running continuously). Always destroy when done.

Q: Can I modify a running cluster?
A: Yes, you have full kubectl access. Changes persist during test run.

Q: What if service account key expires?
A: Create a new key: gcloud iam service-accounts keys create ...



Support#

  • HyperShift Docs: https://hypershift-docs.readthedocs.io/
  • GCP HyperShift: https://hypershift-docs.readthedocs.io/en/latest/how-to/gcp/
  • GCP Docs: https://cloud.google.com/docs
  • OpenShift Docs: https://docs.openshift.com/

Edit this page on GitHub