Use the following examples to deploy sample backends with Cloud CDN enabled.
If you are new to using Terraform for Google Cloud, see Get started with Terraform.
Using a Cloud Storage bucket
The following sample configures Cloud CDN with a public Cloud Storage bucket. The sample also includes load balancing and caching configurations. The configurations can be modified, as required.
For details about each section of the sample, see Set up a backend bucket.
# Cloud Storage bucket
resource "random_id" "bucket_prefix" {
byte_length = 8
}
resource "google_storage_bucket" "default" {
name = "${random_id.bucket_prefix.hex}-my-bucket"
location = "us-east1"
uniform_bucket_level_access = true
storage_class = "STANDARD"
// delete bucket and contents on destroy.
force_destroy = true
// Assign specialty files
website {
main_page_suffix = "index.html"
not_found_page = "404.html"
}
}
# make bucket public
resource "google_storage_bucket_iam_member" "default" {
bucket = google_storage_bucket.default.name
role = "roles/storage.objectViewer"
member = "allUsers"
}
resource "google_storage_bucket_object" "index_page" {
name = "index-page"
bucket = google_storage_bucket.default.name
content = <<-EOT
<html><body>
<h1>Congratulations on setting up Google Cloud CDN with Storage backend!</h1>
</body></html>
EOT
}
resource "google_storage_bucket_object" "error_page" {
name = "404-page"
bucket = google_storage_bucket.default.name
content = <<-EOT
<html><body>
<h1>404 Error: Object you are looking for is no longer available!</h1>
</body></html>
EOT
}
# image object for testing, try to access http://<your_lb_ip_address>/test.jpg
resource "google_storage_bucket_object" "test_image" {
name = "test-object"
# Uncomment and add valid path to an object.
# source = "/path/to/an/object"
# content_type = "image/jpeg"
# Delete after uncommenting above source and content_type attributes
content = "Data as string to be uploaded"
content_type = "text/plain"
bucket = google_storage_bucket.default.name
}
# reserve IP address
resource "google_compute_global_address" "default" {
name = "example-ip"
}
# forwarding rule
resource "google_compute_global_forwarding_rule" "default" {
name = "http-lb-forwarding-rule"
ip_protocol = "TCP"
load_balancing_scheme = "EXTERNAL"
port_range = "80"
target = google_compute_target_http_proxy.default.id
ip_address = google_compute_global_address.default.id
}
# http proxy
resource "google_compute_target_http_proxy" "default" {
name = "http-lb-proxy"
url_map = google_compute_url_map.default.id
}
# url map
resource "google_compute_url_map" "default" {
name = "http-lb"
default_service = google_compute_backend_bucket.default.id
}
# backend bucket with CDN policy with default ttl settings
resource "google_compute_backend_bucket" "default" {
name = "cat-backend-bucket"
description = "Contains beautiful images"
bucket_name = google_storage_bucket.default.name
enable_cdn = true
cdn_policy {
cache_mode = "CACHE_ALL_STATIC"
client_ttl = 3600
default_ttl = 3600
max_ttl = 86400
negative_caching = true
serve_while_stale = 86400
}
}
Using MIG and custom headers
You can use Terraform resources to bring up an external HTTP load balancer with a Cloud CDN backend service and custom request and response headers.
For information about the load balancer setup, see the primary setup guide.
# VPC
resource "google_compute_network" "default" {
name = "l7-xlb-network"
provider = google-beta
auto_create_subnetworks = false
}
# backend subnet
resource "google_compute_subnetwork" "default" {
name = "l7-xlb-subnet"
provider = google-beta
ip_cidr_range = "10.0.1.0/24"
region = "us-central1"
network = google_compute_network.default.id
}
# reserved IP address
resource "google_compute_global_address" "default" {
provider = google-beta
name = "l7-xlb-static-ip"
}
# forwarding rule
resource "google_compute_global_forwarding_rule" "default" {
name = "l7-xlb-forwarding-rule"
provider = google-beta
ip_protocol = "TCP"
load_balancing_scheme = "EXTERNAL"
port_range = "80"
target = google_compute_target_http_proxy.default.id
ip_address = google_compute_global_address.default.id
}
# http proxy
resource "google_compute_target_http_proxy" "default" {
name = "l7-xlb-target-http-proxy"
provider = google-beta
url_map = google_compute_url_map.default.id
}
# url map
resource "google_compute_url_map" "default" {
name = "l7-xlb-url-map"
provider = google-beta
default_service = google_compute_backend_service.default.id
}
# backend service with custom request and response headers
resource "google_compute_backend_service" "default" {
name = "l7-xlb-backend-service"
provider = google-beta
protocol = "HTTP"
port_name = "my-port"
load_balancing_scheme = "EXTERNAL"
timeout_sec = 10
enable_cdn = true
custom_request_headers = ["X-Client-Geo-Location: {client_region_subdivision}, {client_city}"]
custom_response_headers = ["X-Cache-Hit: {cdn_cache_status}"]
health_checks = [google_compute_health_check.default.id]
backend {
group = google_compute_instance_group_manager.default.instance_group
balancing_mode = "UTILIZATION"
capacity_scaler = 1.0
}
}
# instance template
resource "google_compute_instance_template" "default" {
name = "l7-xlb-mig-template"
provider = google-beta
machine_type = "e2-small"
tags = ["allow-health-check"]
network_interface {
network = google_compute_network.default.id
subnetwork = google_compute_subnetwork.default.id
access_config {
# add external ip to fetch packages
}
}
disk {
source_image = "debian-cloud/debian-12"
auto_delete = true
boot = true
}
# install nginx and serve a simple web page
metadata = {
startup-script = <<-EOF1
#! /bin/bash
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y nginx-light jq
NAME=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/hostname")
IP=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip")
METADATA=$(curl -f -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?recursive=True" | jq 'del(.["startup-script"])')
cat <<EOF > /var/www/html/index.html
<pre>
Name: $NAME
IP: $IP
Metadata: $METADATA
</pre>
EOF
EOF1
}
lifecycle {
create_before_destroy = true
}
}
# health check
resource "google_compute_health_check" "default" {
name = "l7-xlb-hc"
provider = google-beta
http_health_check {
port_specification = "USE_SERVING_PORT"
}
}
# MIG
resource "google_compute_instance_group_manager" "default" {
name = "l7-xlb-mig1"
provider = google-beta
zone = "us-central1-c"
named_port {
name = "http"
port = 8080
}
version {
instance_template = google_compute_instance_template.default.id
name = "primary"
}
base_instance_name = "vm"
target_size = 2
}
# allow access from health check ranges
resource "google_compute_firewall" "default" {
name = "l7-xlb-fw-allow-hc"
provider = google-beta
direction = "INGRESS"
network = google_compute_network.default.id
source_ranges = ["130.211.0.0/22", "35.191.0.0/16"]
allow {
protocol = "tcp"
}
target_tags = ["allow-health-check"]
}