Terraform GCP Resource Types
Introduction
Terraform, an Infrastructure as Code (IaC) tool, allows you to define cloud resources using a declarative configuration language. When working with Google Cloud Platform (GCP), Terraform provides a wide range of resource types that correspond to GCP services. Understanding these resource types is crucial for effectively managing your cloud infrastructure.
In this guide, we'll explore common GCP resource types that you can manage with Terraform, how to define them in your configuration files, and practical examples to help you get started.
The Structure of GCP Resource Types in Terraform
In Terraform, GCP resources follow a common naming convention:
resource "google_[service]_[resource]" "name" {
// resource configuration
}
Where:
google_
is the provider prefix[service]
is the GCP service (like compute, storage, container)[resource]
is the specific resource typename
is your chosen identifier for this resource within your Terraform code
Common GCP Resource Types
Let's explore some of the most commonly used GCP resource types with examples.
Compute Resources
Virtual Machines (Compute Engine)
resource "google_compute_instance" "web_server" {
name = "web-server"
machine_type = "e2-medium"
zone = "us-central1-a"
boot_disk {
initialize_params {
image = "debian-cloud/debian-11"
}
}
network_interface {
network = "default"
access_config {
// Ephemeral public IP
}
}
metadata_startup_script = "echo 'Hello, World!' > /var/www/html/index.html"
tags = ["web", "http-server"]
}
This creates a Compute Engine VM instance with a Debian image, attaches it to the default network, and runs a simple startup script.
Instance Groups
resource "google_compute_instance_template" "web_template" {
name = "web-template"
machine_type = "e2-medium"
disk {
source_image = "debian-cloud/debian-11"
auto_delete = true
boot = true
}
network_interface {
network = "default"
access_config {
// Ephemeral IP
}
}
metadata_startup_script = "apt-get update && apt-get install -y nginx"
}
resource "google_compute_instance_group_manager" "web_igm" {
name = "web-igm"
base_instance_name = "web"
zone = "us-central1-a"
target_size = 2
version {
instance_template = google_compute_instance_template.web_template.id
}
}
This example creates an instance template and an instance group manager that maintains two identical VMs based on the template.
Storage Resources
Cloud Storage Bucket
resource "google_storage_bucket" "static_website" {
name = "my-static-website-bucket"
location = "US"
force_destroy = true
website {
main_page_suffix = "index.html"
not_found_page = "404.html"
}
uniform_bucket_level_access = true
}
resource "google_storage_bucket_object" "index_page" {
name = "index.html"
bucket = google_storage_bucket.static_website.name
content = <<EOF
<!DOCTYPE html>
<html>
<head>
<title>Hello World</title>
</head>
<body>
<h1>Hello from Terraform!</h1>
</body>
</html>
EOF
}
This creates a Cloud Storage bucket configured to host a static website and uploads an index.html file to it.
Networking Resources
VPC Network and Subnets
resource "google_compute_network" "vpc_network" {
name = "terraform-network"
auto_create_subnetworks = false
}
resource "google_compute_subnetwork" "subnet" {
name = "terraform-subnet"
ip_cidr_range = "10.0.1.0/24"
region = "us-central1"
network = google_compute_network.vpc_network.id
}
This example creates a custom VPC network without automatic subnet creation and then defines a specific subnet within the network.
Firewall Rules
resource "google_compute_firewall" "allow_http" {
name = "allow-http"
network = google_compute_network.vpc_network.name
allow {
protocol = "tcp"
ports = ["80"]
}
source_ranges = ["0.0.0.0/0"]
target_tags = ["http-server"]
}
This creates a firewall rule allowing HTTP traffic (port 80) from any source to instances with the "http-server" tag.
Database Resources
Cloud SQL Instance
resource "google_sql_database_instance" "postgres" {
name = "postgres-instance"
database_version = "POSTGRES_13"
region = "us-central1"
settings {
tier = "db-f1-micro"
backup_configuration {
enabled = true
start_time = "04:00"
}
}
deletion_protection = false # Set to true for production
}
resource "google_sql_database" "database" {
name = "my-database"
instance = google_sql_database_instance.postgres.name
}
resource "google_sql_user" "user" {
name = "my-user"
instance = google_sql_database_instance.postgres.name
password = "changeme" # Use secrets management in production
}
This creates a PostgreSQL Cloud SQL instance with a database and user. Note that in production environments, you should use Terraform's secrets management or external secrets providers for sensitive data like passwords.
Kubernetes Resources
Google Kubernetes Engine (GKE) Cluster
resource "google_container_cluster" "primary" {
name = "my-gke-cluster"
location = "us-central1"
# We can't create a cluster with no node pool defined, but we want to only use
# separately managed node pools. So we create the smallest possible default
# node pool and immediately delete it.
remove_default_node_pool = true
initial_node_count = 1
}
resource "google_container_node_pool" "primary_preemptible_nodes" {
name = "my-node-pool"
location = "us-central1"
cluster = google_container_cluster.primary.name
node_count = 1
node_config {
preemptible = true
machine_type = "e2-medium"
# Google recommends custom service accounts that have cloud-platform scope and permissions granted via IAM Roles.
oauth_scopes = [
"https://www.googleapis.com/auth/cloud-platform"
]
}
}
This creates a GKE cluster with a custom node pool using preemptible VMs.
Identity and Access Management (IAM)
Service Account and Role Binding
resource "google_service_account" "app_service_account" {
account_id = "app-service-account"
display_name = "Application Service Account"
}
resource "google_project_iam_binding" "storage_objectViewer" {
project = "your-project-id"
role = "roles/storage.objectViewer"
members = [
"serviceAccount:${google_service_account.app_service_account.email}",
]
}
This creates a service account and grants it the Storage Object Viewer role at the project level.
Organizing Your Terraform GCP Resources
As your infrastructure grows, organizing your Terraform code becomes important. Here's a recommended structure for GCP projects:
project/
├── main.tf # Main configuration file
├── variables.tf # Input variables definition
├── outputs.tf # Output values
├── providers.tf # Provider configuration
├── modules/ # Reusable modules
│ ├── networking/
│ ├── compute/
│ └── storage/
└── environments/ # Environment-specific configurations
├── dev/
├── stage/
└── prod/
Practical Example: Building a Three-Tier Web Application
Let's combine several resource types to create a simplified three-tier web application:
# Network configuration
resource "google_compute_network" "vpc" {
name = "app-network"
auto_create_subnetworks = false
}
resource "google_compute_subnetwork" "web_subnet" {
name = "web-subnet"
ip_cidr_range = "10.0.1.0/24"
region = "us-central1"
network = google_compute_network.vpc.id
}
resource "google_compute_subnetwork" "app_subnet" {
name = "app-subnet"
ip_cidr_range = "10.0.2.0/24"
region = "us-central1"
network = google_compute_network.vpc.id
}
resource "google_compute_subnetwork" "db_subnet" {
name = "db-subnet"
ip_cidr_range = "10.0.3.0/24"
region = "us-central1"
network = google_compute_network.vpc.id
}
# Web tier - Compute instance template and managed instance group
resource "google_compute_instance_template" "web_template" {
name_prefix = "web-template-"
machine_type = "e2-medium"
disk {
source_image = "debian-cloud/debian-11"
auto_delete = true
boot = true
}
network_interface {
subnetwork = google_compute_subnetwork.web_subnet.id
access_config {
// Ephemeral IP
}
}
metadata_startup_script = "apt-get update && apt-get install -y nginx"
lifecycle {
create_before_destroy = true
}
}
resource "google_compute_instance_group_manager" "web_igm" {
name = "web-igm"
base_instance_name = "web"
zone = "us-central1-a"
target_size = 2
version {
instance_template = google_compute_instance_template.web_template.id
}
}
# App tier - GKE cluster
resource "google_container_cluster" "app_cluster" {
name = "app-cluster"
location = "us-central1"
network = google_compute_network.vpc.name
subnetwork = google_compute_subnetwork.app_subnet.name
# Private cluster configuration
private_cluster_config {
enable_private_nodes = true
enable_private_endpoint = false
master_ipv4_cidr_block = "172.16.0.0/28"
}
ip_allocation_policy {
cluster_ipv4_cidr_block = "10.16.0.0/16"
services_ipv4_cidr_block = "10.12.0.0/16"
}
remove_default_node_pool = true
initial_node_count = 1
}
resource "google_container_node_pool" "app_nodes" {
name = "app-node-pool"
location = "us-central1"
cluster = google_container_cluster.app_cluster.name
node_count = 3
node_config {
machine_type = "e2-standard-2"
oauth_scopes = [
"https://www.googleapis.com/auth/cloud-platform"
]
}
}
# Database tier - Cloud SQL
resource "google_sql_database_instance" "database" {
name = "app-database"
database_version = "POSTGRES_13"
region = "us-central1"
depends_on = [google_compute_network.vpc]
settings {
tier = "db-g1-small"
ip_configuration {
ipv4_enabled = false
private_network = google_compute_network.vpc.id
}
}
deletion_protection = false # Set to true for production
}
resource "google_sql_database" "app_db" {
name = "app-database"
instance = google_sql_database_instance.database.name
}
This example combines multiple GCP resource types to create a three-tier architecture:
- Web tier: Load-balanced VM instances running Nginx
- Application tier: GKE cluster for containerized applications
- Database tier: Private Cloud SQL instance
Best Practices for GCP Resources in Terraform
- Use Variables for Reusable Configurations
variable "region" {
description = "GCP region to deploy resources"
default = "us-central1"
}
variable "project_id" {
description = "GCP project ID"
}
// Use variables in resources
resource "google_compute_instance" "instance" {
zone = "${var.region}-a"
// other configuration
}
- Leverage Data Sources for External Information
data "google_compute_image" "debian" {
family = "debian-11"
project = "debian-cloud"
}
resource "google_compute_instance" "instance" {
// ...
boot_disk {
initialize_params {
image = data.google_compute_image.debian.self_link
}
}
}
- Use Modules for Reusable Components
module "vpc" {
source = "./modules/vpc"
project = var.project_id
region = var.region
}
module "gke" {
source = "./modules/gke"
project = var.project_id
region = var.region
network_name = module.vpc.network_name
}
Resource Types Visualization
Here's a diagram showing the relationship between common GCP resource types:
Summary
Terraform provides a
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)