GCP deployment with Terraform
End state: Observal running in your GCP project on Cloud Run, backed by Cloud SQL Postgres, Memorystore Redis, and a GCE instance for ClickHouse — with a Global HTTPS Load Balancer, managed SSL certificate, Secret Manager for credentials, and GCS for backups.
For the overall deployment strategy and comparison with AWS, see Production deployment. If you want a simpler single-VM setup, see Single-node deployment.
What gets provisioned
A single terraform apply creates:
VPC with a private subnet, Cloud NAT, and a Serverless VPC Access Connector
Cloud Run v2 services:
api,web,workerwith autoscaling (min/max instance counts)Cloud Run v2 job:
init(one-shot migrations + seeds)Cloud SQL Postgres (Open-source distribution): optional HA, encrypted, automated backups
Memorystore Redis: BASIC or STANDARD_HA tier
GCE instance (data host): ClickHouse on a persistent disk, with optional Prometheus and Grafana, accessible via IAP SSH tunnel
Global HTTPS Load Balancer with managed SSL certificate (when domain is supplied)
Cloud DNS A record pointing to the load balancer
Secret Manager: generated DB / ClickHouse / SECRET_KEY passwords, plus connection URLs injected into Cloud Run services
GCS backups bucket: versioned, lifecycle to Nearline → delete
Artifact Registry: for storing container images (optional)
Prerequisites
GCP project with billing enabled
Resources cost money
gcloud CLI authenticated
gcloud auth application-default login
Terraform ≥ 1.5
brew install terraform
(Optional) Cloud DNS managed zone
Required for HTTPS on a custom domain
Enable required APIs:
Quickstart
Configuration
All inputs live in terraform.tfvars.
Minimal (no custom domain)
The install comes up on the Cloud Run default URL (e.g. https://observal-prod-api-xxxxx-uc.a.run.app).
Recommended (HTTPS on your domain)
Terraform provisions a Global HTTPS Load Balancer with a Google-managed SSL certificate and creates the DNS A record.
Sizing
For high-throughput installs, bump data_machine_type to e2-standard-4, db_tier to db-custom-4-16384, and redis_tier to STANDARD_HA.
ClickHouse Cloud
The GCE data host is skipped entirely.
Operating the install
Shell into the data host
No public SSH. Access is through IAP (Identity-Aware Proxy) — authenticated, audited, no SSH keys to manage.
View logs
Cloud Run logs go to Cloud Logging automatically:
Or use the Cloud Console: Logging → Logs Explorer, filter by resource.type="cloud_run_revision".
Re-run migrations
Read a generated secret
Upgrade to a new release
Cloud Run handles the rolling deploy. Zero downtime.
Resize the data disk
Destroy
Cloud SQL deletion protection is enabled on prod. Disable manually before destroy if you mean it.
Cost estimate (us-central1, on-demand)
Cloud Run api
1 vCPU / 1 GB, min 1 instance
$25
Cloud Run web
1 vCPU / 512 MB, min 1 instance
$15
Cloud Run worker
1 vCPU / 1 GB, min 1 instance
$25
Cloud SQL Postgres
db-g1-small (shared)
$25
Memorystore Redis
1 GB BASIC
$35
GCE data host
e2-standard-2
$50
Global HTTPS LB
—
$18
Persistent Disk 100 GB
—
$4
GCS backups
~1 GB
$0.02
Total
~$200
Cloud Run scales to zero when idle (if min_instances = 0), which can significantly reduce costs for low-traffic deployments.
Production hardening checklist
Troubleshooting
Cloud Run service stuck in Revision is not ready. Check revision logs in Cloud Logging. Common causes: Secret Manager permissions missing, VPC connector not ready, or image pull failure.
Init job fails.
Usually: Cloud SQL not yet reachable (transient on first apply), or missing secret access.
502 from the load balancer. The managed SSL certificate takes 10–30 minutes to provision. Check: Network Services → Load Balancing → (your LB) → Backend services → Health.
Cloud SQL connection refused from Cloud Run. The VPC Access Connector must be in the same region as Cloud Run. Verify connector_cidr doesn't overlap with your VPC subnet.
For application-level issues, see Troubleshooting.
Next
Production deployment — overview of both clouds
Configuration — environment variables
Upgrades — upgrade and rollback procedures
Backup and restore — restore procedures
Last updated
Was this helpful?