Use when defining infrastructure as code, creating Terraform/Pulumi configurations, managing cloud resources declaratively, or version-controlling infrastructure - focuses on IaC tools and infrastructure automation
☐ Select appropriate tool for your cloud provider ☐ Install and configure tool locally ☐ Set up authentication with cloud provider
Tool selection:
For this guide, we'll focus on Terraform (most popular).
☐ Create project directory ☐ Create main configuration file ☐ Initialize Terraform ☐ Configure backend for state storage
Project structure:
infrastructure/
├── main.tf # Main resources
├── variables.tf # Input variables
├── outputs.tf # Output values
├── terraform.tfvars # Variable values (don't commit secrets)
├── backend.tf # State backend config
└── versions.tf # Provider versions
Initialize project:
mkdir infrastructure
cd infrastructure
# Create backend.tf for remote state
cat > backend.tf << 'EOF'
terraform {
backend "gcs" {
bucket = "my-terraform-state"
prefix = "prod"
}
}
EOF
# Initialize
terraform init
☐ Define provider configuration ☐ Create resource definitions ☐ Use variables for configuration ☐ Add outputs for important values
Example: Cloud Run service with database (GCP)
# versions.tf
terraform {
required_version = ">= 1.0"
required_providers {
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
}
}
# main.tf
provider "google" {
project = var.project_id
region = var.region
}
# Cloud Run service
resource "google_cloud_run_service" "app" {
name = var.service_name
location = var.region
template {
spec {
containers {
image = var.container_image
env {
name = "DATABASE_URL"
value = "postgresql://${google_sql_database_instance.db.connection_name}"
}
env {
name = "API_KEY"
value_from {
secret_key_ref {
name = google_secret_manager_secret_version.api_key.name
key = "latest"
}
}
}
resources {
limits = {
cpu = "1000m"
memory = "512Mi"
}
}
}
}
metadata {
annotations = {
"autoscaling.knative.dev/maxScale" = "10"
"autoscaling.knative.dev/minScale" = "1"
}
}
}
traffic {
percent = 100
latest_revision = true
}
}
# Cloud SQL database
resource "google_sql_database_instance" "db" {
name = "${var.service_name}-db"
database_version = "POSTGRES_15"
region = var.region
settings {
tier = "db-f1-micro"
backup_configuration {
enabled = true
start_time = "03:00"
}
}
deletion_protection = true
}
resource "google_sql_database" "database" {
name = var.database_name
instance = google_sql_database_instance.db.name
}
# Secret Manager
resource "google_secret_manager_secret" "api_key" {
secret_id = "${var.service_name}-api-key"
replication {
automatic = true
}
}
# Allow public access to Cloud Run
resource "google_cloud_run_service_iam_member" "public" {
service = google_cloud_run_service.app.name
location = google_cloud_run_service.app.location
role = "roles/run.invoker"
member = "allUsers"
}
variables.tf:
variable "project_id" {
description = "GCP project ID"
type = string
}
variable "region" {
description = "GCP region"
type = string
default = "us-central1"
}
variable "service_name" {
description = "Name of the Cloud Run service"
type = string
}
variable "container_image" {
description = "Container image to deploy"
type = string
}
variable "database_name" {
description = "PostgreSQL database name"
type = string
default = "myapp"
}
outputs.tf:
output "service_url" {
description = "URL of the deployed Cloud Run service"
value = google_cloud_run_service.app.status[0].url
}
output "database_connection" {
description = "Database connection name"
value = google_sql_database_instance.db.connection_name
sensitive = true
}
terraform.tfvars:
project_id = "my-gcp-project"
region = "us-central1"
service_name = "myapp"
container_image = "gcr.io/my-gcp-project/myapp:latest"
☐ Run terraform plan to preview changes ☐ Review plan output carefully ☐ Apply changes to provision infrastructure ☐ Verify resources created successfully
Terraform workflow:
# Format code
terraform fmt
# Validate configuration
terraform validate
# Plan changes (dry run)
terraform plan -out=tfplan
# Review plan output carefully!
# Look for:
# - Resources being created (+)
# - Resources being modified (~)
# - Resources being destroyed (-)
# Apply changes
terraform apply tfplan
# View outputs
terraform output
# View specific output
terraform output service_url
☐ Use remote state backend (GCS, S3, Terraform Cloud) ☐ Enable state locking ☐ Never commit state files to git ☐ Back up state regularly
Configure remote backend (GCS):
terraform {
backend "gcs" {
bucket = "my-terraform-state"
prefix = "prod/terraform.tfstate"
}
}
State commands:
# List resources in state
terraform state list
# Show specific resource
terraform state show google_cloud_run_service.app
# Move resource in state (refactoring)
terraform state mv old_name new_name
# Remove resource from state (careful!)
terraform state rm google_cloud_run_service.app
# Pull remote state
terraform state pull
# Import existing resource
terraform import google_cloud_run_service.app projects/PROJECT/locations/REGION/services/SERVICE
☐ Create modules for common patterns ☐ Use modules from Terraform Registry ☐ Version modules for stability
Create module:
modules/
└── cloud-run-app/
├── main.tf
├── variables.tf
└── outputs.tf
modules/cloud-run-app/main.tf:
resource "google_cloud_run_service" "app" {
name = var.name
location = var.region
template {
spec {
containers {
image = var.image
}
}
}
}
Use module:
module "frontend" {
source = "./modules/cloud-run-app"
name = "frontend"
region = "us-central1"
image = "gcr.io/project/frontend:latest"
}
module "backend" {
source = "./modules/cloud-run-app"
name = "backend"
region = "us-central1"
image = "gcr.io/project/backend:latest"
}
☐ Create separate state files per environment ☐ Use workspaces or separate directories ☐ Parametrize environment-specific values
Option 1: Workspaces
# Create workspaces
terraform workspace new dev
terraform workspace new staging
terraform workspace new prod
# Select workspace
terraform workspace select prod
# Apply (uses prod workspace state)
terraform apply
Option 2: Separate directories
infrastructure/
├── modules/
│ └── app/
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ │ ├── main.tf
│ │ └── terraform.tfvars
│ └── prod/
│ ├── main.tf
│ └── terraform.tfvars
☐ Add terraform plan to pull requests ☐ Require approval before apply ☐ Automate apply on main branch merge
GitHub Actions workflow: