Terraform Lab 07 — Layer 4 vs. Layer 7 Load Balancing¶
Load Balancers act as intelligent traffic dispatchers. This lab covers the difference between Layer 4 (Transport / TCP/UDP) and Layer 7 (Application / HTTP/HTTPS) Load Balancing.
Lab contract¶
| Item | This lab |
|---|---|
| Execution model | Standalone focused scenario with a new working directory and state |
| Starts from | Only a GCP project ID; all backend infrastructure is created by this lab |
| Creates | VPC, subnet, firewall, two instance templates, two managed instance groups, and the complete Layer 7 load-balancing chain |
| Cost note | Global forwarding and backend resources may incur charges; destroy after verification |
| Next | Lab 08 — IPsec VPN & BGP |
Resource summary¶
| Terraform block | Count | Purpose |
|---|---|---|
google_compute_network / google_compute_subnetwork |
2 | Provides an isolated backend network |
google_compute_instance_template |
2 | Defines the web and API VM configurations |
google_compute_instance_group_manager |
2 | Creates one managed web VM and one managed API VM |
google_compute_health_check.http_health |
1 | Determines backend eligibility |
google_compute_backend_service |
2 | Separate web and API backend pools |
google_compute_url_map.l7_url_map |
1 | Sends /api/* to API and other paths to web |
google_compute_target_http_proxy.http_proxy |
1 | Terminates the HTTP frontend and uses the URL map |
google_compute_global_forwarding_rule.forwarding_rule |
1 | Creates the public TCP 80 entry point |
output.load_balancer_ip |
1 | Exposes the assigned frontend address for verification |
Comparison Matrix: Layer 4 vs. Layer 7¶
| Feature | Layer 4 (Network Load Balancer) | Layer 7 (Application Load Balancer) |
|---|---|---|
| OSI Layer | Layer 4 (TCP / UDP) | Layer 7 (HTTP / HTTPS / gRPC) |
| Inspection Capability | IP addresses and Port numbers only | URLs, HTTP headers, Cookies, Query parameters |
| Routing Capability | Distributes to a single backend pool | Content-based routing (/api → API pool, /images → Storage) |
| SSL/TLS Termination | Pass-through (Client connects directly to VM) | Offloads TLS certificates at the edge; talks HTTP internally |
| Performance | Extreme throughput, lowest latency | Rich traffic management, URL rewrites, and security |
Complete Terraform Configuration: L7 Cloud HTTP Load Balancer¶
terraform {
required_version = ">= 1.5.0"
required_providers {
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
}
}
provider "google" {
project = var.project_id
region = var.region
}
variable "project_id" {
description = "GCP project ID to deploy into"
type = string
}
variable "region" {
description = "GCP region for the load-balancer backends"
type = string
default = "us-central1"
}
resource "google_compute_network" "lb_vpc" {
name = "lb-vpc"
auto_create_subnetworks = false
}
resource "google_compute_subnetwork" "lb_subnet" {
name = "lb-backend-subnet"
ip_cidr_range = "10.20.0.0/24"
region = var.region
network = google_compute_network.lb_vpc.id
}
resource "google_compute_firewall" "allow_health_checks" {
name = "allow-lb-health-checks"
network = google_compute_network.lb_vpc.id
allow {
protocol = "tcp"
ports = ["80"]
}
source_ranges = ["35.191.0.0/16", "130.211.0.0/22"]
target_tags = ["lb-backend"]
}
resource "google_compute_instance_template" "web" {
name_prefix = "web-template-"
machine_type = "e2-micro"
tags = ["lb-backend"]
disk {
source_image = "debian-cloud/debian-12"
auto_delete = true
boot = true
}
network_interface {
subnetwork = google_compute_subnetwork.lb_subnet.id
}
metadata_startup_script = <<-EOF
#!/bin/bash
install -d /opt/web
echo "Web backend response" > /opt/web/index.html
echo "healthy" > /opt/web/health
python3 -m http.server 80 --directory /opt/web >/var/log/web-backend.log 2>&1 &
EOF
lifecycle {
create_before_destroy = true
}
}
resource "google_compute_instance_template" "api" {
name_prefix = "api-template-"
machine_type = "e2-micro"
tags = ["lb-backend"]
disk {
source_image = "debian-cloud/debian-12"
auto_delete = true
boot = true
}
network_interface {
subnetwork = google_compute_subnetwork.lb_subnet.id
}
metadata_startup_script = <<-EOF
#!/bin/bash
install -d /opt/api/api
echo "API backend response" > /opt/api/api/users
echo "healthy" > /opt/api/health
python3 -m http.server 80 --directory /opt/api >/var/log/api-backend.log 2>&1 &
EOF
lifecycle {
create_before_destroy = true
}
}
resource "google_compute_instance_group_manager" "web" {
name = "web-mig"
base_instance_name = "web"
zone = "${var.region}-a"
target_size = 1
version {
instance_template = google_compute_instance_template.web.id
}
named_port {
name = "http"
port = 80
}
}
resource "google_compute_instance_group_manager" "api" {
name = "api-mig"
base_instance_name = "api"
zone = "${var.region}-a"
target_size = 1
version {
instance_template = google_compute_instance_template.api.id
}
named_port {
name = "http-api"
port = 80
}
}
# 1. Health Check (Probes backend VMs on port 80)
resource "google_compute_health_check" "http_health" {
name = "app-http-health-check"
check_interval_sec = 5
timeout_sec = 3
healthy_threshold = 2
unhealthy_threshold = 3
http_health_check {
port = 80
request_path = "/health"
}
}
# 2. Backend Services (Groups of VMs serving specific traffic)
resource "google_compute_backend_service" "web_backend" {
name = "web-backend-service"
protocol = "HTTP"
port_name = "http"
load_balancing_scheme = "EXTERNAL_MANAGED"
health_checks = [google_compute_health_check.http_health.id]
backend {
group = google_compute_instance_group_manager.web.instance_group
}
}
resource "google_compute_backend_service" "api_backend" {
name = "api-backend-service"
protocol = "HTTP"
port_name = "http-api"
load_balancing_scheme = "EXTERNAL_MANAGED"
health_checks = [google_compute_health_check.http_health.id]
backend {
group = google_compute_instance_group_manager.api.instance_group
}
}
# 3. URL Map (The Layer 7 Routing Brain)
resource "google_compute_url_map" "l7_url_map" {
name = "prod-global-url-map"
default_service = google_compute_backend_service.web_backend.id
host_rule {
hosts = ["*"]
path_matcher = "allpaths"
}
path_matcher {
name = "allpaths"
default_service = google_compute_backend_service.web_backend.id
# Content-based routing: /api/* routes to dedicated API instances
path_rule {
paths = ["/api", "/api/*"]
service = google_compute_backend_service.api_backend.id
}
}
}
# 4. Target HTTP Proxy
resource "google_compute_target_http_proxy" "http_proxy" {
name = "prod-http-proxy"
url_map = google_compute_url_map.l7_url_map.id
}
# 5. Global Forwarding Rule (Public Entry Point with Anycast VIP)
resource "google_compute_global_forwarding_rule" "forwarding_rule" {
name = "http-global-entry"
target = google_compute_target_http_proxy.http_proxy.id
port_range = "80"
load_balancing_scheme = "EXTERNAL_MANAGED"
}
output "load_balancer_ip" {
description = "Global frontend IP assigned to the HTTP load balancer"
value = google_compute_global_forwarding_rule.forwarding_rule.ip_address
}
Apply and verify¶
Lab 07 creates its VPC, subnet, firewall rule, instance templates, and managed
instance groups. Only project_id is required; all resource names and backend
group links are derived inside Terraform.
cd docs/terraform/07-load-balancing-l4-l7
export PROJECT_ID="YOUR_PROJECT_ID"
gcloud services enable compute.googleapis.com \
--project="$PROJECT_ID"
terraform init
terraform fmt -check
terraform validate
terraform plan \
-input=false \
-var="project_id=$PROJECT_ID"
terraform apply \
-var="project_id=$PROJECT_ID"
Wait for both managed instances and load-balancer backends to become healthy, then test path-based routing:
# 1. Fetch the global virtual IP assigned to the load balancer.
VIP="$(terraform output -raw load_balancer_ip)"
# 2. Test the default web backend.
curl "http://$VIP/"
# Expected: Web backend response
# 3. Test the /api path routed to the API backend.
curl "http://$VIP/api/users"
# Expected: API backend response
Cleanup and next step¶
This destroys the complete standalone Lab 07 stack, including both managed instance groups and their VMs. Continue to Lab 08 — IPsec VPN & BGP.