Skip to main content

GCP

GCP Self-Hosted (Vanilla) K8s Cluster Provisioner

The Astro platform deploys a Kubernetes cluster on GCP instances on your behalf, allowing you to select the instance type, size, zone, region, and other configurations. This approach is beneficial when you require a cluster that is not managed by the cloud provider, providing you with full control over the cluster, including the control plane.

Prerequisites

To create a self-hosted cluster on GCP, ensure the following CLI tools are installed on your local machine:

  • GCP CLI for GCP cluster communication
  • kubectl (optional) for GCP cluster interaction
  • astroctl for cluster management

CLI Workflow

The astroctl cloud gcp selfHosted command group manages the full lifecycle of GCP self-hosted prerequisites. There are five subcommands:

CommandPurposeUsed By
setupCreate service account, roles, APIs, GCS bucket and auto-store credentials in vaultPlatform team
connectValidate existing credentials and store in vaultDeveloper
disconnectRevoke stored credentials from vault (keeps infrastructure)Platform team
validatePre-flight validation only (no storage)CI/CD, troubleshooting
cleanupRemove resources created by setup and purge vault credentialsPlatform team

Setup (Platform Team)

The platform team creates all GCP prerequisites and auto-stores credentials in the vault with a single command:

# Create service account, assign roles, enable APIs, and create GCS bucket
astroctl cloud gcp selfHosted setup --project-id <project-id> --region <region>

This interactive command will:

  1. Create a service account (astro-selfhosted@<project-id>.iam.gserviceaccount.com)
  2. Assign all 8 required IAM roles
  3. Enable all 5 required APIs
  4. Create a GCS bucket for cluster state
  5. Generate and save a service account key

If the service account already exists, you can add missing roles:

astroctl cloud gcp selfHosted setup --project-id <project-id> --region <region> \
--service-account existing-sa@<project-id>.iam.gserviceaccount.com

Connect (Developer / BYOC)

For existing credentials (Bring Your Own Credentials), validate and store them in the vault:

# Connect with auto-detected credentials (env vars or ADC)
astroctl cloud gcp selfHosted connect \
--project-id <project-id> \
--region <region> \
--bucket <bucket-name> \
--cluster-name <cluster-name>

# Connect with a credential file
astroctl cloud gcp selfHosted connect \
--project-id <project-id> \
--region <region> \
--credentials /path/to/key.json \
--bucket <bucket-name> \
--cluster-name <cluster-name>

On success, credentials are stored in the platform vault and the command outputs the provisioner block to paste into your cluster YAML:

provisioner:
type: selfHosted
selfHosted:
accountId: "<project-id>"
bucketName: "<bucket-name>"
credentials:
type: vault
Credential Resolution

The connect command auto-detects credentials in this order:

  1. Explicit --credentials flag (file path, raw JSON, or base64)
  2. GOOGLE_APPLICATION_CREDENTIALS environment variable
  3. GOOGLE_CREDENTIALS environment variable (raw JSON)
  4. Application Default Credentials (gcloud auth application-default login)

Validate

Run validations without generating output — useful for CI/CD pipelines or troubleshooting:

astroctl cloud gcp selfHosted validate \
--project-id <project-id> \
--credentials <path-to-key-file> \
--bucket <bucket-name>

The validate command checks:

  • Credentials are valid and project is accessible
  • All 5 required APIs are enabled
  • All 8 required IAM roles are assigned
  • GCS bucket is accessible

Disconnect

Revoke stored credentials from the vault without removing infrastructure — useful for credential rotation:

astroctl cloud gcp selfHosted disconnect --cluster-name <cluster-name>

After disconnecting, run connect with new credentials to re-store them in the vault.

Cleanup

When you no longer need the self-hosted prerequisites:

astroctl cloud gcp selfHosted cleanup --project-id <project-id>

This removes the service account, IAM role bindings, the state store bucket, and purges vault credentials.

Cleanup Impact

This is a destructive operation. Ensure no clusters depend on these resources before running cleanup.

Required IAM Roles

The setup command assigns these roles to the service account:

RoleDescription
Viewerroles/viewer
Storage Adminroles/storage.admin
Compute Adminroles/compute.admin
Kubernetes Engine Adminroles/container.admin
Service Account Userroles/iam.serviceAccountUser
Service Account Adminroles/iam.serviceAccountAdmin
Project IAM Adminroles/resourcemanager.projectIamAdmin
Artifact Registry Adminroles/artifactregistry.admin

Required APIs

The setup command enables these APIs:

API NameAPI ID
Compute Enginecompute.googleapis.com
Kubernetes Enginecontainer.googleapis.com
Cloud Resource Managercloudresourcemanager.googleapis.com
Container Registrycontainerregistry.googleapis.com
Artifact Registryartifactregistry.googleapis.com
GCP Permissions

The Astro platform requires permissions to create and manage GCP resources for provisioning Kubernetes clusters. The service account credentials will be stored in encrypted format to prevent unauthorized access.

Complete Field Reference

The selfHosted type represents the spec for the GCP self-hosted provisioner. This is the authoritative reference for all available fields.

Core Fields

FieldTypeRequiredDefaultDescription
accountIdstringYes-GCP project ID where the cluster will be created
bucketNamestringYes-GCS bucket name for storing cluster configuration. Must be in the same region as the cluster.
credentialsobjectYes-GCP credentials. Use type: vault (recommended for self-hosted) or type: static for inline credentials. The vault type is only supported for the selfHosted provisioner.

Networking Fields

FieldTypeRequiredDefaultDescription
networkIdstringNo-VPC network name for BYOVPC. If not provided, platform creates a new VPC

Cluster Configuration Fields

FieldTypeRequiredDefaultDescription
kubernetesVersionstringNoPlatform defaultKubernetes version. Must be full semantic version (e.g., 1.30.14)

Field Validation Rules

FieldValidation
accountIdMust be a valid GCP project ID (lowercase, hyphens allowed)
bucketNameMust be a valid GCS bucket name
networkIdMust be 1-63 lowercase letters, digits, or hyphens
kubernetesVersionMust be full semantic version format: 1.30.14 (major.minor.patch)
Version Format

Self-hosted clusters require the full semantic version format (e.g., 1.30.14). The major.minor format (e.g., 1.30) is not supported for self-hosted clusters.

The credentials will be used to authenticate the astro platform and other tools when managing your GCP resources.

BYOA (Bring Your Own Account)

Run setup or connect to store credentials in the platform vault, then reference them with type: vault — no sensitive data in your YAML:

provider: gcp
region: us-west2
provisioner:
type: selfHosted
selfHosted:
accountId: <project-id>
bucketName: <bucket-name> # this bucket should be created in the same region as the cluster
credentials:
type: vault
How vault works

The setup command automatically stores credentials in the vault after creating GCP prerequisites. For existing credentials, run connect to store them manually. The platform retrieves credentials from the vault at provision time — no secrets in YAML files.

Option 2: Credentials in YAML (explicit)

If you cannot use the vault, you can still provide credentials inline:

provider: gcp
region: us-west2
provisioner:
type: selfHosted
selfHosted:
accountId: <project-id>
bucketName: <bucket-name> # this bucket should be created in the same region as the cluster
credentials:
type: static
data:
GOOGLE_APPLICATION_CREDENTIALS: <path-to-key-file> # path to the JSON key file
Security

Avoid committing credentials to version control. Prefer type: vault (Option 1) or ensure your YAML files are in .gitignore.

Bring Your Own VPC (BYOVPC)

Add the networkId field to your cluster YAML to use an existing VPC:

provider: gcp
region: us-west2
provisioner:
type: selfHosted
selfHosted:
accountId: "<project-id>"
networkId: "<vpc-network-name>"
bucketName: "<bucket-name>"
credentials:
type: vault

Requirements for the VPC:

  • Must be in the same region as the cluster
  • Must have internet access configured

KubeConfig

With simple command like below, you can set the context to the cluster and have the access to the cluster. You need to make sure to install the kubectl CLI as required. The kubeconfig will be valid for 1 hour by default and you need to generate the kubeconfig again with the new duration.

astroctl infra k8s generate-kubeconfig <cluster-name> --duration <duration>

and you can set the context to the cluster with the following command:

astroctl infra k8s set-context <cluster-name>

The cluster uses the client authentication type mutual TLS authentication to authenticate the kubeconfig. The platform lets you to configure the duration for the kubeconfig to be valid. Only the platform admin or admin of the organization can export the kubeconfig.

Cluster Updates

Self-hosted GCP clusters support updates to Kubernetes version and node group configurations. You can use either the Console UI or the CLI.

Version Format

Self-hosted clusters require the full semantic version format (e.g., 1.30.14). The major.minor format (e.g., 1.30) is not supported.

Option 1: Console (Upgrade Wizard)

The Console provides a guided 5-step upgrade wizard:

  1. Preflight Check - Validates upgrade paths and checks for issues
  2. Readiness Report - Generates comprehensive upgrade analysis with risk score
  3. Pre-Upgrade Checklist - Interactive checklist with verification commands
  4. Configuration - Select target version and rolling update settings
  5. Confirmation - Review summary and confirm by typing cluster name

To access: Go to Clusters → Select cluster → Click Upgrade button

The wizard shows:

  • Visual version timeline (current → next → locked future versions)
  • Node group scaling controls (min/max nodes)
  • Control plane configuration (self-hosted only)
  • Rolling update settings (maxSurge, maxUnavailable)
  • Impact summary before execution

Option 2: CLI Commands

Version Discovery

# List available versions for this cluster
astroctl infra k8s upgrade <cluster-name> --list-versions

# Check self-hosted versions
astroctl cloud gcp k8s-versions --self-hosted
astroctl cloud gcp k8s-versions --self-hosted --show-upgrade-paths

Kubernetes Version Upgrade

# Dry-run validation first
astroctl infra k8s upgrade <cluster-name> 1.30.14 --dry-run

# Generate readiness report
astroctl infra k8s upgrade <cluster-name> 1.30.14 --generate-report

# Execute upgrade
astroctl infra k8s upgrade <cluster-name> 1.30.14

# Skip confirmation (for automation)
astroctl infra k8s upgrade <cluster-name> 1.30.14 --yes

Scaling Node Groups

# List node groups
astroctl infra k8s scale <cluster-name> --list

# Scale a node group
astroctl infra k8s scale <cluster-name> <nodegroup-name> --min 3 --max 10

# Preview changes
astroctl infra k8s scale <cluster-name> <nodegroup-name> --min 5 --max 20 --dry-run

Advanced Updates (YAML)

# Show YAML examples for your cluster
astroctl infra k8s update <cluster-name> --example

# Apply update
astroctl infra k8s update <cluster-name> -f update.yaml

# Dry-run validation
astroctl infra k8s update <cluster-name> -f update.yaml --dry-run

# Skip confirmation
astroctl infra k8s update <cluster-name> -f update.yaml --auto-approve

Monitor Progress

# Stream real-time progress
astroctl infra k8s progress stream <cluster-name>

# Get current status
astroctl infra k8s progress get <cluster-name>

# View operation history
astroctl infra k8s progress history <cluster-name>

Update File Reference

apiVersion: platform.astropulse.io/v1
kind: K8sClusterUpdate
spec:
# Kubernetes version (full semver required)
kubernetesVersion: "1.30.14"

# Rolling update configuration
updateConfig:
maxSurge: "1" # Nodes added during update (number or %)
maxUnavailable: "1" # Nodes down during update (number or %)
dryRun: false # Validate without applying
generateReport: false # Generate readiness report

# Worker node groups
nodeGroups:
- name: "worker-ng-0"
minNode: 2
maxNode: 6
machineTypes: ["n2-standard-4"]
instanceType: "ondemand" # or "spot"
labels:
workload: "general"

# Control plane configuration (self-hosted only)
selfHosted:
controlPlane:
name: "control-plane"
minNode: 3
maxNode: 3
machineTypes: ["n2-standard-2"]

Upgrade Process

  1. Control plane nodes are upgraded first (one at a time for HA)
  2. etcd cluster is upgraded
  3. Worker nodes are upgraded using rolling replacement
  4. Progress is tracked and reported in real-time
Upgrade Considerations
  • Self-hosted clusters only support upgrades to sequential minor versions (cannot skip versions)
  • Ensure you have recent etcd backups before upgrading
  • Always test upgrades in a non-production environment first

Rollback

Self-hosted clusters support full rollback including control plane downgrade — unlike managed providers (EKS/GKE/AKS) which only downgrade node pools.

# List valid rollback versions
astroctl infra k8s rollback <cluster-name> --list-versions

# Dry-run validation
astroctl infra k8s rollback <cluster-name> <target-version> --dry-run

# Execute rollback
astroctl infra k8s rollback <cluster-name> <target-version>

# Skip confirmation (automation)
astroctl infra k8s rollback <cluster-name> <target-version> --yes
Rollback Impact
  • Control plane + worker nodes are all downgraded via rolling update
  • Workloads will be drained and migrated to new nodes
  • Ensure workloads are compatible with the older Kubernetes version
  • This is a destructive operation for existing nodes
Zero-Downtime Updates

When changing machine types, nodes are replaced using a rolling strategy. Ensure your maxSurge and maxUnavailable settings allow for the desired replacement behavior.