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:
| Command | Purpose | Used By |
|---|---|---|
setup | Create service account, roles, APIs, GCS bucket and auto-store credentials in vault | Platform team |
connect | Validate existing credentials and store in vault | Developer |
disconnect | Revoke stored credentials from vault (keeps infrastructure) | Platform team |
validate | Pre-flight validation only (no storage) | CI/CD, troubleshooting |
cleanup | Remove resources created by setup and purge vault credentials | Platform 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:
- Create a service account (
astro-selfhosted@<project-id>.iam.gserviceaccount.com) - Assign all 8 required IAM roles
- Enable all 5 required APIs
- Create a GCS bucket for cluster state
- 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
The connect command auto-detects credentials in this order:
- Explicit
--credentialsflag (file path, raw JSON, or base64) GOOGLE_APPLICATION_CREDENTIALSenvironment variableGOOGLE_CREDENTIALSenvironment variable (raw JSON)- 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.
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:
| Role | Description |
|---|---|
| Viewer | roles/viewer |
| Storage Admin | roles/storage.admin |
| Compute Admin | roles/compute.admin |
| Kubernetes Engine Admin | roles/container.admin |
| Service Account User | roles/iam.serviceAccountUser |
| Service Account Admin | roles/iam.serviceAccountAdmin |
| Project IAM Admin | roles/resourcemanager.projectIamAdmin |
| Artifact Registry Admin | roles/artifactregistry.admin |
Required APIs
The setup command enables these APIs:
| API Name | API ID |
|---|---|
| Compute Engine | compute.googleapis.com |
| Kubernetes Engine | container.googleapis.com |
| Cloud Resource Manager | cloudresourcemanager.googleapis.com |
| Container Registry | containerregistry.googleapis.com |
| Artifact Registry | artifactregistry.googleapis.com |
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
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
accountId | string | Yes | - | GCP project ID where the cluster will be created |
bucketName | string | Yes | - | GCS bucket name for storing cluster configuration. Must be in the same region as the cluster. |
credentials | object | Yes | - | 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
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
networkId | string | No | - | VPC network name for BYOVPC. If not provided, platform creates a new VPC |
Cluster Configuration Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
kubernetesVersion | string | No | Platform default | Kubernetes version. Must be full semantic version (e.g., 1.30.14) |
Field Validation Rules
| Field | Validation |
|---|---|
accountId | Must be a valid GCP project ID (lowercase, hyphens allowed) |
bucketName | Must be a valid GCS bucket name |
networkId | Must be 1-63 lowercase letters, digits, or hyphens |
kubernetesVersion | Must be full semantic version format: 1.30.14 (major.minor.patch) |
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)
Option 1: Platform Vault (recommended)
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
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
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.
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:
- Preflight Check - Validates upgrade paths and checks for issues
- Readiness Report - Generates comprehensive upgrade analysis with risk score
- Pre-Upgrade Checklist - Interactive checklist with verification commands
- Configuration - Select target version and rolling update settings
- 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
- Control plane nodes are upgraded first (one at a time for HA)
- etcd cluster is upgraded
- Worker nodes are upgraded using rolling replacement
- Progress is tracked and reported in real-time
- 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
- 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
When changing machine types, nodes are replaced using a rolling strategy. Ensure your maxSurge and maxUnavailable settings allow for the desired replacement behavior.