GCP for DevOps — Terraform GCP Basics
Terraform GCP Basics
Terraform uses the Google provider (hashicorp/google) to create and manage GCP resources declaratively.
Install Terraform
# macOS
$ brew install terraform
# Verify
$ terraform version
Terraform v1.7.0
Authentication Methods
| Method | Use Case | Command |
|---|---|---|
| Application Default Credentials (ADC) | Local development | gcloud auth application-default login |
| Service Account Key | CI/CD pipelines | GOOGLE_APPLICATION_CREDENTIALS=key.json |
| Workload Identity Federation | GitHub Actions, GitLab CI | OIDC token exchange |
# ADC — simplest for local dev
$ gcloud auth application-default login
# Service Account (CI/CD)
$ export GOOGLE_APPLICATION_CREDENTIALS="/path/to/sa-key.json"
First Terraform Configuration
# main.tf
terraform {
required_version = ">= 1.5"
required_providers {
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
}
}
provider "google" {
project = "my-project-id"
region = "us-central1"
zone = "us-central1-a"
}
# Create a VPC
resource "google_compute_network" "vpc" {
name = "my-vpc"
auto_create_subnetworks = false
}
# Create a subnet
resource "google_compute_subnetwork" "subnet" {
name = "my-subnet"
ip_cidr_range = "10.0.1.0/24"
region = "us-central1"
network = google_compute_network.vpc.id
}
# Create a VM
resource "google_compute_instance" "vm" {
name = "my-vm"
machine_type = "e2-micro"
zone = "us-central1-a"
boot_disk {
initialize_params {
image = "debian-cloud/debian-12"
size = 20
}
}
network_interface {
subnetwork = google_compute_subnetwork.subnet.id
access_config {} # Ephemeral public IP
}
tags = ["http-server"]
}
Terraform Workflow
# Initialize (download providers)
$ terraform init
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/google versions matching "~> 5.0"...
- Installing hashicorp/google v5.20.0...
Terraform has been successfully initialized!
# Preview changes
$ terraform plan
Plan: 3 to add, 0 to change, 0 to destroy.
# Apply changes
$ terraform apply
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
# View current state
$ terraform show
# Destroy all resources
$ terraform destroy
Variables
# variables.tf
variable "project_id" {
description = "GCP project ID"
type = string
}
variable "region" {
description = "GCP region"
type = string
default = "us-central1"
}
variable "environment" {
description = "Environment name"
type = string
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}
# terraform.tfvars
project_id = "my-project-id"
region = "us-central1"
environment = "dev"
Outputs
# outputs.tf
output "vm_ip" {
description = "External IP of the VM"
value = google_compute_instance.vm.network_interface[0].access_config[0].nat_ip
}
output "vpc_id" {
description = "VPC network ID"
value = google_compute_network.vpc.id
}
$ terraform output vm_ip
"34.123.45.67"
Data Sources
Read existing resources without managing them.
# Look up the default compute service account
data "google_compute_default_service_account" "default" {}
# Look up a project
data "google_project" "current" {}
# Use data source values
output "project_number" {
value = data.google_project.current.number
}
Common Mistakes
| Mistake | Why It’s Wrong | Fix |
|---|---|---|
| Hardcoding project ID in provider | Can’t reuse across projects | Use variables |
| No version constraints | Breaking changes on provider update | Pin with ~> 5.0 |
| Using SA keys in production | Security risk, rotation burden | Use Workload Identity Federation |
No .gitignore for Terraform |
State and secrets committed | Ignore .terraform/, *.tfstate* |
Running apply without plan |
Unexpected changes | Always review plan output |
Quick Reference
| Command | Description |
|---|---|
terraform init |
Initialize and download providers |
terraform plan |
Preview changes |
terraform apply |
Apply changes |
terraform destroy |
Destroy all resources |
terraform output |
Show output values |
terraform fmt |
Format HCL files |
terraform validate |
Validate configuration |
Next → Google Provider