TerraformPilot

Terraform

Terraform on GCP: A Complete Beginner's Guide

A beginner-friendly Terraform GCP guide with provider setup, service accounts, GCS buckets, Compute Engine VMs, and networking. Step-by-step with code examples.

LLuca Berton1 min read

Quick Answer

#

Configure the google provider with your project ID and region, authenticate via gcloud auth application-default login (local) or a service account key (CI/CD), then terraform init && terraform plan && terraform apply.

Prerequisites

#
# Install Google Cloud CLI
curl https://sdk.cloud.google.com | bash
gcloud init
gcloud auth application-default login
 
# Install Terraform
# See: /articles/install-terraform-debian/
terraform version

Provider Configuration

#
terraform {
  required_version = ">= 1.5"
 
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.20"
    }
  }
}
 
provider "google" {
  project = var.project_id
  region  = var.region
}
 
variable "project_id" {
  type        = string
  description = "GCP project ID"
}
 
variable "region" {
  type    = string
  default = "us-central1"
}

Authentication Methods

#

Local Development

#
gcloud auth application-default login
# Terraform uses ADC (Application Default Credentials) automatically

Service Account (CI/CD)

#
# Create service account
gcloud iam service-accounts create terraform \
  --display-name "Terraform"
 
# Grant permissions
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member "serviceAccount:terraform@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role "roles/editor"
 
# Create and download key
gcloud iam service-accounts keys create key.json \
  --iam-account terraform@${PROJECT_ID}.iam.gserviceaccount.com
 
export GOOGLE_APPLICATION_CREDENTIALS="key.json"

Your First GCP Resources

#

GCS Bucket

#
resource "google_storage_bucket" "data" {
  name          = "${var.project_id}-data"
  location      = "US"
  force_destroy = false
 
  uniform_bucket_level_access = true
 
  versioning {
    enabled = true
  }
 
  lifecycle_rule {
    condition {
      age = 90
    }
    action {
      type          = "SetStorageClass"
      storage_class = "NEARLINE"
    }
  }
}

VPC Network

#
resource "google_compute_network" "main" {
  name                    = "main-vpc"
  auto_create_subnetworks = false
}
 
resource "google_compute_subnetwork" "app" {
  name          = "app-subnet"
  ip_cidr_range = "10.0.1.0/24"
  region        = var.region
  network       = google_compute_network.main.id
 
  secondary_ip_range {
    range_name    = "pods"
    ip_cidr_range = "10.1.0.0/16"
  }
}

Compute Engine VM

#
resource "google_compute_instance" "web" {
  name         = "web-server"
  machine_type = "e2-medium"
  zone         = "${var.region}-a"
 
  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-12"
      size  = 20
    }
  }
 
  network_interface {
    subnetwork = google_compute_subnetwork.app.id
    access_config {} # Adds external IP
  }
 
  metadata_startup_script = <<-EOF
    #!/bin/bash
    apt-get update
    apt-get install -y nginx
    systemctl enable nginx
  EOF
 
  tags = ["http-server"]
}
 
resource "google_compute_firewall" "http" {
  name    = "allow-http"
  network = google_compute_network.main.name
 
  allow {
    protocol = "tcp"
    ports    = ["80", "443"]
  }
 
  source_ranges = ["0.0.0.0/0"]
  target_tags   = ["http-server"]
}

Remote State with GCS

#
terraform {
  backend "gcs" {
    bucket = "myproject-terraform-state"
    prefix = "prod"
  }
}

Enable Required APIs

#
resource "google_project_service" "apis" {
  for_each = toset([
    "compute.googleapis.com",
    "storage.googleapis.com",
    "container.googleapis.com",
    "iam.googleapis.com",
  ])
  service            = each.value
  disable_on_destroy = false
}

GCP vs AWS Terraform Comparison

#
ConceptAWSGCP
NetworkingVPC + SubnetsVPC Network + Subnetwork
ComputeEC2Compute Engine
StorageS3Cloud Storage (GCS)
KubernetesEKSGKE
IdentityIAM RolesService Accounts
Providerhashicorp/awshashicorp/google

Common Mistakes

#
MistakeFix
API not enabledAdd google_project_service resources
Wrong projectCheck gcloud config get-value project
Quota exceededRequest quota increase in Console
Bucket name takenGCS names are globally unique — add project ID prefix
#

Conclusion

#

Terraform on GCP follows the same init → plan → apply workflow as other clouds. Authenticate via gcloud locally or service accounts in CI/CD, enable required APIs, and use GCS for remote state. The google provider covers Compute Engine, GKE, Cloud SQL, Cloud Storage, and 200+ other GCP services.

#Terraform#Google Cloud#DevOps#Infrastructure as Code#Beginner

Share this article