DevOps help for Cloud Platform Engineers
  • Welcome!
  • Quick Start Guide
  • About Me
  • CV
  • Contribute
  • 🧠DevOps & SRE Foundations
    • DevOps Overview
      • Engineering Fundamentals
      • Implementing DevOps Strategy
      • DevOps Readiness Assessment
      • Lifecycle Management
      • The 12 Factor App
      • Design for Self Healing
      • Incident Management Best Practices (2025)
    • SRE Fundamentals
      • Toil Reduction
      • System Simplicity
      • Real-world Scenarios
        • AWS VM Log Monitoring API
    • Agile Development
      • Team Agreements
        • Definition of Done
        • Definition of Ready
        • Team Manifesto
        • Working Agreement
    • Industry Scenarios
      • Finance and Banking
      • Public Sector (UK/EU)
      • Energy Sector Edge Computing
  • DevOps Practices
    • Platform Engineering
    • FinOps
    • Observability
      • Modern Practices
  • 🚀Modern DevOps Practices
    • Infrastructure Testing
    • Modern Development
    • Database DevOps
  • 🛠️Infrastructure as Code (IaC)
    • Terraform
      • Cloud Integrations - Provider-specific implementations
        • Azure Scenarios
          • Azure Authetication
            • Service Principal
            • Service Principal in block
            • Service Principal in env
        • AWS Scenarios
          • AWS Authentication
        • GCP Scenarios
          • GCP Authentication
      • Testing and Validation
        • Unit Testing
        • Integration Testing
        • End-to-End Testing
        • Terratest Guide
      • Best Practices
        • State Management
        • Security
        • Code Organization
        • Performance
      • Tools & Utilities - Enhancing the Terraform workflow
        • Terraform Docs
        • TFLint
        • Checkov
        • Terrascan
      • CI/CD Integration - Automating infrastructure deployment
        • GitHub Actions
        • Azure Pipelines
        • GitLab CI
    • Bicep
      • Getting Started - First steps with Bicep [BEGINNER]
      • Template Specs
      • Best Practices - Guidelines for effective Bicep implementations
      • Modules - Building reusable components [INTERMEDIATE]
      • Examples - Sample implementations for common scenarios
      • Advanced Features
      • CI/CD Integration - Automating Bicep deployments
        • GitHub Actions
        • Azure Pipelines
  • 💰Cost Management & FinOps
    • Cloud Cost Optimization
  • 🐳Containers & Orchestration
    • Containerization Overview
      • Docker
        • Dockerfile Best Practices
        • Docker Compose
      • Kubernetes
        • CLI Tools - Essential command-line utilities
          • Kubectl
          • Kubens
          • Kubectx
        • Core Concepts
        • Components
        • Best Practices
          • Pod Security
          • Security Monitoring
          • Resource Limits
        • Advanced Features - Beyond the basics [ADVANCED]
          • Service Mesh
            • Istio
            • Linkerd
          • Ingress Controllers
            • NGINX
            • Traefik
            • Kong
            • Gloo Edge
            • Contour
        • Tips
          • Status in Pods
          • Resource handling
          • Pod Troubleshooting Commands
        • Enterprise Architecture
        • Health Management
        • Security & Compliance
        • Virtual Clusters
      • OpenShift
  • Service Mesh & Networking
    • Service Mesh Implementation
  • Architecture Patterns
    • Data Mesh
    • Multi-Cloud Networking
    • Disaster Recovery
    • Chaos Engineering
  • Edge Computing
    • Implementation Guide
      • Serverless Edge
      • IoT Edge Patterns
      • Real-Time Processing
      • Edge AI/ML
      • Security Hardening
      • Observability Patterns
      • Network Optimization
      • Storage Patterns
  • 🔄CI/CD & GitOps
    • CI/CD Overview
      • Continuous Integration
      • Continuous Delivery
        • Deployment Strategies
        • Secrets Management
        • Blue-Green Deployments
        • Deployment Metrics
        • Progressive Delivery
        • Release Management for DevOps/SRE (2025)
      • CI/CD Platforms - Tool selection and implementation
        • Azure DevOps
          • Pipelines
            • Stages
            • Jobs
            • Steps
            • Templates - Reusable pipeline components
            • Extends
            • Service Connections - External service authentication
            • Best Practices for 2025
            • Agents and Runners
            • Third-Party Integrations
            • Azure DevOps CLI
          • Boards & Work Items
        • GitHub Actions
        • GitLab
          • GitLab Runner
          • Real-life scenarios
          • Installation guides
          • Pros and Cons
          • Comparison with alternatives
      • GitOps
        • Modern GitOps Practices
        • GitOps Patterns for Multi-Cloud (2025)
        • Flux
          • Overview
          • Progressive Delivery
          • Use GitOps with Flux, GitHub and AKS
  • Source Control
    • Source Control Overview
      • Git Branching Strategies
      • Component Versioning
      • Kubernetes Manifest Versioning
      • GitLab
      • Creating a Fork
      • Naming Branches
      • Pull Requests
      • Integrating LLMs into Source Control Workflows
  • ☁️Cloud Platforms
    • Cloud Strategy
      • AWS to Azure
      • Azure to AWS
      • GCP to Azure
      • AWS to GCP
      • GCP to AWS
    • Azure
      • Best Practices
        • Azure Best Practices Overview
        • Azure Architecture Best Practices
        • Azure Naming Standards
        • Azure Tags
        • Azure Security Best Practices
      • Landing Zones
      • Services
        • Azure Active Directory (AAD)
        • Azure Monitor
        • Azure Key Vault
        • Azure Service Bus
        • Azure DNS
        • Azure App Service
        • Azure Batch
        • Azure Machine Learning
        • Azure OpenAI Service
        • Azure Cognitive Services
        • Azure Kubernetes Service (AKS)
        • Azure Databricks
        • Azure SQL Database
      • Monitoring
      • Administration Tools - Platform management interfaces
        • Azure PowerShell
        • Azure CLI
      • Tips & Tricks
    • AWS
      • Authentication
      • Best Practices
      • Tips & Tricks
      • Services
        • AWS IAM (Identity and Access Management)
        • Amazon CloudWatch
        • Amazon SNS (Simple Notification Service)
        • Amazon SQS (Simple Queue Service)
        • Amazon Route 53
        • AWS Elastic Beanstalk
        • AWS Batch
        • Amazon SageMaker
        • Amazon Bedrock
        • Amazon Comprehend
    • Google Cloud
      • Services
        • Cloud CDN
        • Cloud DNS
        • Cloud Load Balancing
        • Google Kubernetes Engine (GKE)
        • Cloud Run
        • Artifact Registry
        • Compute Engine
        • Cloud Functions
        • App Engine
        • Cloud Storage
        • Persistent Disk
        • Filestore
        • Cloud SQL
        • Cloud Spanner
        • Firestore
        • Bigtable
        • BigQuery
        • VPC (Virtual Private Cloud)
  • 🔐Security & Compliance
    • DevSecOps Overview
      • DevSecOps Pipeline Security
      • DevSecOps
        • Real-life Examples
        • Scanning & Protection - Automated security tooling
          • Dependency Scanning
          • Credential Scanning
          • Container Security Scanning
          • Static Code Analysis
            • Best Practices
            • Tool Integration Guide
            • Pipeline Configuration
        • CI/CD Security
        • Secrets Rotation
      • Supply Chain Security
        • SLSA Framework
        • Binary Authorization
        • Artifact Signing
      • Security Best Practices
        • Threat Modeling
        • Kubernetes Security
      • SecOps
      • Zero Trust Model
      • Cloud Compliance
        • ISO/IEC 27001:2022
        • ISO 22301:2019
        • PCI DSS
        • CSA STAR
      • Security Frameworks
      • SIEM and SOAR
  • Security Architecture
    • Zero Trust Implementation
      • Identity Management
      • Network Security
      • Access Control
  • 🔍Observability & Monitoring
    • Observability Fundamentals
      • Logging
      • Metrics
      • Tracing
      • Dashboards
      • SLOs and SLAs
      • Observability as Code
      • Pipeline Observability
  • 🧪Testing Strategies
    • Testing Overview
      • Modern Testing Approaches
      • End-to-End Testing
      • Unit Testing
      • Performance Testing
        • Load Testing
      • Fault Injection Testing
      • Integration Testing
      • Smoke Testing
  • 🤖AI Integration
    • AIops Overview
      • Workflow Automation
      • Predictive Analytics
      • Code Quality
  • 🧠AI & LLM Integration
    • Overview
      • Claude
        • Installation Guide
        • Project Guides
        • MCP Server Setup
        • LLM Comparison
      • Ollama
        • Installation Guide
        • Configuration
        • Models and Fine-tuning
        • DevOps Usage
        • Docker Setup
        • GPU Setup
        • Open WebUI
      • Copilot
        • Installation Guide
        • VS Code Integration
        • CLI Usage
      • Gemini
        • Installation Guides - Platform-specific setup
          • Linux Installation
          • WSL Installation
          • NixOS Installation
        • Gemini 2.5 Features
        • Roles and Agents
        • NotebookML Guide
        • Cloud Infrastructure Deployment
        • Summary
  • 💻Development Environment
    • DevOps Tools
      • Operating Systems - Development platforms
        • NixOS
          • Install NixOS: PC, Mac, WSL
          • Nix Language Deep Dive
          • Nix Language Fundamentals
            • Nix Functions and Techniques
            • Building Packages with Nix
            • NixOS Configuration Patterns
            • Flakes: The Future of Nix
          • NixOS Generators: Azure & QEMU
        • WSL2
          • Distributions
          • Terminal Setup
      • Editor Environments
      • CLI Tools
        • Azure CLI
        • PowerShell
        • Linux Commands
          • SSH - Secure Shell)
            • SSH Config
            • SSH Port Forwarding
        • Linux Fundametals
        • Cloud init
          • Cloud init examples
        • YAML Tools
          • How to create a k8s yaml file - How to create YAML config
          • YQ the tool
  • 📚Programming Languages
    • Python
    • Go
    • JavaScript/TypeScript
    • Java
    • Rust
  • Platform Engineering
    • Implementation Guide
  • FinOps
    • Implementation Guide
  • AIOps
    • LLMOps Guide
  • Should Learn
    • Should Learn
    • Linux
      • Commands
      • OS
      • Services
    • Terraform
    • Getting Started - Installation and initial setup [BEGINNER]
    • Cloud Integrations
    • Testing and Validation - Ensuring infrastructure quality
      • Unit Testing
      • Integration Testing
      • End-to-End Testing
      • Terratest Guide
    • Best Practices - Production-ready implementation strategies
      • State Management
      • Security
      • Code Organization
      • Performance
    • Tools & Utilities
    • CI/CD Integration
    • Bicep
    • Kubernetes
      • kubectl
    • Ansible
    • Puppet
    • Java
    • Rust
    • Azure CLI
  • 📖Documentation Best Practices
    • Documentation Strategy
      • Project Documentation
      • Release Notes
      • Static Sites
      • Documentation Templates
      • Real-World Examples
  • 📋Reference Materials
    • Glossary
    • Tool Comparison
    • Tool Decision Guides
    • Recommended Reading
    • Troubleshooting Guide
    • Development Setup
Powered by GitBook
On this page
  • Key Features
  • Deploying Cloud CDN with Terraform
  • Basic Setup with Cloud Storage Backend
  • HTTPS Configuration with Custom Domain
  • Advanced Configuration with Load Balancer and Cloud Armor
  • Managing Cloud CDN with gcloud CLI
  • Setting up Cloud CDN with a Load Balancer
  • Setting up Cloud CDN with Compute Engine Backends
  • Managing Cache Invalidation
  • Real-World Example: Multi-Region Static Website with Cloud CDN
  • Architecture Overview
  • Terraform Implementation
  • Shell Script for Content Deployment
  • Best Practices
  • Common Issues and Troubleshooting
  • Cache Misses
  • SSL/TLS Issues
  • Performance Problems
  • Content Updates Not Appearing
  • Further Reading
Edit on GitHub
  1. Cloud Platforms
  2. Google Cloud
  3. Services

Cloud CDN

Deploying and managing Google Cloud CDN for content delivery

Google Cloud CDN (Content Delivery Network) uses Google's globally distributed edge points of presence to cache HTTP(S) content close to your users. By caching content at the edge, Cloud CDN accelerates content delivery, reduces serving costs, and helps alleviate the load on your backend servers.

Key Features

  • Global Edge Network: Leverage Google's global edge network spanning 100+ locations

  • Origin Support: Works with Cloud Storage buckets, Compute Engine instances, GKE services, or external origins

  • HTTP/2 and QUIC: Support for modern web protocols

  • SSL: Automatic SSL certificate management

  • Cache Control: Fine-grained cache control through standard HTTP headers

  • Cache Invalidation: API for fast content invalidation

  • Signed URLs/Cookies: Protected access to cached content

  • Metrics and Logging: Real-time monitoring and detailed logging

  • Media Optimization: Optimize delivery for video streaming and large files

  • Security Features: Integration with Cloud Armor for WAF and DDoS protection

Deploying Cloud CDN with Terraform

Basic Setup with Cloud Storage Backend

# Create a storage bucket to serve as the CDN origin
resource "google_storage_bucket" "cdn_bucket" {
  name          = "my-cdn-content-bucket"
  location      = "US"
  storage_class = "STANDARD"
  
  # Enable website serving
  website {
    main_page_suffix = "index.html"
    not_found_page   = "404.html"
  }
  
  # Enforce uniform bucket-level access
  uniform_bucket_level_access = true
  
  # Make objects publicly readable
  force_destroy = true
}

# Upload sample content
resource "google_storage_bucket_object" "sample_content" {
  name        = "index.html"
  bucket      = google_storage_bucket.cdn_bucket.name
  content     = "<html><body>Hello from Cloud CDN!</body></html>"
  content_type = "text/html"
}

# Grant public read access to objects
resource "google_storage_bucket_iam_member" "public_read" {
  bucket = google_storage_bucket.cdn_bucket.name
  role   = "roles/storage.objectViewer"
  member = "allUsers"
}

# Create a compute backend service for the CDN
resource "google_compute_backend_bucket" "cdn_backend" {
  name        = "cdn-backend-bucket"
  description = "Backend bucket for serving content via CDN"
  bucket_name = google_storage_bucket.cdn_bucket.name
  
  # Enable CDN
  enable_cdn = true
  
  # Configure caching behavior
  cdn_policy {
    cache_mode        = "CACHE_ALL_STATIC"
    client_ttl        = 3600  # 1 hour
    default_ttl       = 3600  # 1 hour
    max_ttl           = 86400 # 24 hours
    negative_caching  = true
    
    # Cache static content types automatically
    cache_key_policy {
      include_host         = true
      include_protocol     = true
      include_query_string = false
    }
  }
}

# Create a URL map to route requests to the backend
resource "google_compute_url_map" "cdn_url_map" {
  name            = "cdn-url-map"
  description     = "URL map for CDN"
  default_service = google_compute_backend_bucket.cdn_backend.id
}

# Create an HTTP target proxy
resource "google_compute_target_http_proxy" "cdn_http_proxy" {
  name    = "cdn-http-proxy"
  url_map = google_compute_url_map.cdn_url_map.id
}

# Create a global forwarding rule (the entrypoint for the CDN)
resource "google_compute_global_forwarding_rule" "cdn_forwarding_rule" {
  name       = "cdn-forwarding-rule"
  target     = google_compute_target_http_proxy.cdn_http_proxy.id
  port_range = "80"
  ip_protocol = "TCP"
}

# Output the CDN URL
output "cdn_url" {
  value = "http://${google_compute_global_forwarding_rule.cdn_forwarding_rule.ip_address}"
}

HTTPS Configuration with Custom Domain

# Create a storage bucket as the CDN origin
resource "google_storage_bucket" "https_cdn_bucket" {
  name          = "my-secure-cdn-bucket"
  location      = "US"
  storage_class = "STANDARD"
  
  uniform_bucket_level_access = true
  force_destroy = true
}

# Reserve a static external IP address
resource "google_compute_global_address" "cdn_ip" {
  name = "cdn-static-ip"
}

# Create a managed SSL certificate
resource "google_compute_managed_ssl_certificate" "cdn_certificate" {
  name = "cdn-managed-certificate"

  managed {
    domains = ["cdn.example.com"]
  }
}

# Create a compute backend service for the CDN
resource "google_compute_backend_bucket" "https_cdn_backend" {
  name        = "https-cdn-backend-bucket"
  bucket_name = google_storage_bucket.https_cdn_bucket.name
  enable_cdn  = true
  
  cdn_policy {
    cache_mode        = "CACHE_ALL_STATIC"
    client_ttl        = 3600
    default_ttl       = 3600
    max_ttl           = 86400
    serve_while_stale = 86400  # Serve stale content for up to 24 hours while revalidating
    signed_url_cache_max_age_sec = 7200
  }
}

# Create a URL map
resource "google_compute_url_map" "https_cdn_url_map" {
  name            = "https-cdn-url-map"
  default_service = google_compute_backend_bucket.https_cdn_backend.id
}

# Create an HTTPS target proxy with the SSL certificate
resource "google_compute_target_https_proxy" "https_cdn_proxy" {
  name             = "https-cdn-proxy"
  url_map          = google_compute_url_map.https_cdn_url_map.id
  ssl_certificates = [google_compute_managed_ssl_certificate.cdn_certificate.id]
}

# Create a global forwarding rule (the entrypoint for the CDN)
resource "google_compute_global_forwarding_rule" "https_cdn_forwarding_rule" {
  name       = "https-cdn-forwarding-rule"
  target     = google_compute_target_https_proxy.https_cdn_proxy.id
  port_range = "443"
  ip_address = google_compute_global_address.cdn_ip.address
  ip_protocol = "TCP"
}

# Output the CDN domain and IP
output "cdn_ip" {
  value = google_compute_global_address.cdn_ip.address
}

output "cdn_url" {
  value = "https://cdn.example.com"
}

output "dns_record_value" {
  value = "Add an A record for cdn.example.com pointing to ${google_compute_global_address.cdn_ip.address}"
}

Advanced Configuration with Load Balancer and Cloud Armor

# Create a VPC network
resource "google_compute_network" "cdn_network" {
  name                    = "cdn-network"
  auto_create_subnetworks = false
}

# Create a subnet
resource "google_compute_subnetwork" "cdn_subnet" {
  name          = "cdn-subnet"
  ip_cidr_range = "10.0.0.0/24"
  region        = "us-central1"
  network       = google_compute_network.cdn_network.id
}

# Create a firewall rule to allow HTTP/HTTPS traffic
resource "google_compute_firewall" "cdn_firewall" {
  name    = "cdn-firewall-allow-http-https"
  network = google_compute_network.cdn_network.id

  allow {
    protocol = "tcp"
    ports    = ["80", "443", "8080"]
  }

  source_ranges = ["0.0.0.0/0"]
  target_tags   = ["web-server"]
}

# Create an instance template for the origin servers
resource "google_compute_instance_template" "origin_template" {
  name_prefix  = "origin-template-"
  machine_type = "e2-medium"
  
  tags = ["web-server"]

  disk {
    source_image = "debian-cloud/debian-11"
    auto_delete  = true
    boot         = true
    disk_size_gb = 20
  }

  network_interface {
    network    = google_compute_network.cdn_network.id
    subnetwork = google_compute_subnetwork.cdn_subnet.id
    access_config {
      // Ephemeral public IP
    }
  }

  metadata_startup_script = <<-EOT
    #!/bin/bash
    apt-get update
    apt-get install -y apache2
    cat <<EOF > /var/www/html/index.html
    <html><body>
      <h1>Hello from Google Cloud CDN!</h1>
      <p>Server: $(hostname)</p>
      <p>Time: $(date)</p>
    </body></html>
    EOF
  EOT

  lifecycle {
    create_before_destroy = true
  }
}

# Create an instance group manager
resource "google_compute_instance_group_manager" "origin_group" {
  name               = "origin-group-manager"
  base_instance_name = "origin"
  zone               = "us-central1-a"
  target_size        = 2
  
  version {
    instance_template = google_compute_instance_template.origin_template.id
  }

  auto_healing_policies {
    health_check      = google_compute_health_check.http_health_check.id
    initial_delay_sec = 300
  }
}

# Create a health check
resource "google_compute_health_check" "http_health_check" {
  name               = "http-health-check"
  check_interval_sec = 5
  timeout_sec        = 5
  
  http_health_check {
    port         = 80
    request_path = "/health-check"
  }
}

# Create a Cloud Armor security policy
resource "google_compute_security_policy" "cdn_security_policy" {
  name = "cdn-security-policy"
  
  # Block countries you don't do business with
  rule {
    action   = "deny(403)"
    priority = 1000
    match {
      expr {
        expression = "origin.region_code == 'ZZ'"  # Replace ZZ with actual country code
      }
    }
    description = "Block specific countries"
  }
  
  # Block known bad IPs
  rule {
    action   = "deny(403)"
    priority = 2000
    match {
      expr {
        expression = "evaluatePreconfiguredExpr('sql-injection')"
      }
    }
    description = "Block SQL injection attempts"
  }
  
  # Default rule - allow all other traffic
  rule {
    action   = "allow"
    priority = 2147483647
    match {
      versioned_expr = "SRC_IPS_V1"
      config {
        src_ip_ranges = ["*"]
      }
    }
    description = "Default rule"
  }
}

# Create a backend service
resource "google_compute_backend_service" "cdn_backend_service" {
  name                            = "cdn-backend-service"
  protocol                        = "HTTP"
  port_name                       = "http"
  timeout_sec                     = 10
  enable_cdn                      = true
  connection_draining_timeout_sec = 300
  health_checks                   = [google_compute_health_check.http_health_check.id]
  security_policy                 = google_compute_security_policy.cdn_security_policy.id
  
  backend {
    group = google_compute_instance_group_manager.origin_group.instance_group
  }
  
  cdn_policy {
    cache_mode                   = "USE_ORIGIN_HEADERS"
    default_ttl                  = 3600
    max_ttl                      = 86400
    client_ttl                   = 600
    negative_caching             = true
    cache_key_policy {
      include_host         = true
      include_protocol     = true
      include_query_string = true
    }
    signed_url_cache_max_age_sec = 7200
  }
  
  custom_response_headers = [
    "X-Cache-Status: {cdn_cache_status}",
    "X-Cache-ID: {cdn_cache_id}",
    "Strict-Transport-Security: max-age=31536000; includeSubDomains; preload"
  ]
}

# Create a URL map
resource "google_compute_url_map" "cdn_url_map" {
  name            = "cdn-url-map"
  default_service = google_compute_backend_service.cdn_backend_service.id
  
  # Path matcher for specific routes
  host_rule {
    hosts        = ["cdn.example.com"]
    path_matcher = "path-matcher"
  }
  
  path_matcher {
    name            = "path-matcher"
    default_service = google_compute_backend_service.cdn_backend_service.id
    
    path_rule {
      paths   = ["/images/*"]
      service = google_compute_backend_bucket.images_backend.id
    }
    
    path_rule {
      paths   = ["/api/*"]
      service = google_compute_backend_service.api_backend_service.id
    }
  }
}

# Create a backend bucket for static images
resource "google_storage_bucket" "images_bucket" {
  name     = "cdn-images-bucket"
  location = "US"
}

resource "google_compute_backend_bucket" "images_backend" {
  name        = "images-backend"
  bucket_name = google_storage_bucket.images_bucket.name
  enable_cdn  = true
  
  cdn_policy {
    cache_mode = "CACHE_ALL_STATIC"
    default_ttl = 86400  # 24 hours
    max_ttl     = 604800 # 7 days
  }
}

# Create a backend service for API calls (no caching)
resource "google_compute_backend_service" "api_backend_service" {
  name        = "api-backend-service"
  protocol    = "HTTP"
  port_name   = "http"
  timeout_sec = 30
  enable_cdn  = false  # No caching for API calls
  
  backend {
    group = google_compute_instance_group_manager.origin_group.instance_group
  }
  
  health_checks = [google_compute_health_check.http_health_check.id]
}

# Create SSL certificate
resource "google_compute_managed_ssl_certificate" "cdn_certificate" {
  name = "cdn-managed-certificate"

  managed {
    domains = ["cdn.example.com"]
  }
}

# Create HTTPS target proxy
resource "google_compute_target_https_proxy" "cdn_https_proxy" {
  name             = "cdn-https-proxy"
  url_map          = google_compute_url_map.cdn_url_map.id
  ssl_certificates = [google_compute_managed_ssl_certificate.cdn_certificate.id]
}

# Create global forwarding rule for HTTPS
resource "google_compute_global_forwarding_rule" "cdn_https_forwarding_rule" {
  name       = "cdn-https-forwarding-rule"
  target     = google_compute_target_https_proxy.cdn_https_proxy.id
  port_range = "443"
  ip_protocol = "TCP"
}

# Create HTTP target proxy for redirect
resource "google_compute_target_http_proxy" "cdn_http_proxy" {
  name    = "cdn-http-proxy"
  url_map = google_compute_url_map.http_redirect.id
}

# Create HTTP to HTTPS redirect URL map
resource "google_compute_url_map" "http_redirect" {
  name = "http-redirect"
  
  default_url_redirect {
    https_redirect         = true
    redirect_response_code = "MOVED_PERMANENTLY_DEFAULT"
    strip_query            = false
  }
}

# Create global forwarding rule for HTTP (redirects to HTTPS)
resource "google_compute_global_forwarding_rule" "cdn_http_forwarding_rule" {
  name       = "cdn-http-forwarding-rule"
  target     = google_compute_target_http_proxy.cdn_http_proxy.id
  port_range = "80"
  ip_protocol = "TCP"
}

Managing Cloud CDN with gcloud CLI

Setting up Cloud CDN with a Load Balancer

# Create a GCS bucket as origin
gsutil mb -l us-central1 gs://my-cdn-bucket

# Make bucket publicly readable
gsutil iam ch allUsers:objectViewer gs://my-cdn-bucket

# Upload content to the bucket
echo "<html><body>Hello from Cloud CDN</body></html>" > index.html
gsutil cp index.html gs://my-cdn-bucket/

# Create a backend bucket with Cloud CDN enabled
gcloud compute backend-buckets create my-cdn-backend \
  --gcs-bucket-name=my-cdn-bucket \
  --enable-cdn

# Create a URL map to route requests to the backend
gcloud compute url-maps create my-cdn-url-map \
  --default-backend-bucket=my-cdn-backend

# Create an HTTP target proxy
gcloud compute target-http-proxies create my-http-proxy \
  --url-map=my-cdn-url-map

# Create a global forwarding rule (frontend)
gcloud compute forwarding-rules create my-http-forwarding-rule \
  --global \
  --target-http-proxy=my-http-proxy \
  --ports=80

Setting up Cloud CDN with Compute Engine Backends

# Create a health check
gcloud compute health-checks create http http-basic-check \
  --port=80 \
  --request-path=/health.html

# Create an instance template
gcloud compute instance-templates create web-template \
  --machine-type=e2-medium \
  --image-family=debian-11 \
  --image-project=debian-cloud \
  --tags=http-server \
  --metadata=startup-script='#! /bin/bash
    apt-get update
    apt-get install -y apache2
    cat > /var/www/html/index.html << EOF
    <html><body>
      <h1>Hello from Google Cloud CDN!</h1>
      <p>Time: $(date)</p>
    </body></html>
    cat > /var/www/html/health.html << EOF
    OK
    EOF'

# Create an instance group
gcloud compute instance-groups managed create web-group \
  --zone=us-central1-a \
  --size=2 \
  --template=web-template \
  --health-check=http-basic-check \
  --initial-delay=300

# Create a backend service with Cloud CDN enabled
gcloud compute backend-services create web-backend-service \
  --protocol=HTTP \
  --port-name=http \
  --health-checks=http-basic-check \
  --enable-cdn \
  --global

# Add the instance group to the backend service
gcloud compute backend-services add-backend web-backend-service \
  --instance-group=web-group \
  --instance-group-zone=us-central1-a \
  --global

# Create a URL map
gcloud compute url-maps create web-url-map \
  --default-service=web-backend-service

# Create an HTTP target proxy
gcloud compute target-http-proxies create web-http-proxy \
  --url-map=web-url-map

# Create a forwarding rule
gcloud compute forwarding-rules create web-forwarding-rule \
  --global \
  --target-http-proxy=web-http-proxy \
  --ports=80

Managing Cache Invalidation

# Invalidate a specific file
gcloud compute url-maps invalidate-cdn-cache my-cdn-url-map \
  --path="/images/logo.png"

# Invalidate a directory and all its contents
gcloud compute url-maps invalidate-cdn-cache my-cdn-url-map \
  --path="/css/*"

# Invalidate all content
gcloud compute url-maps invalidate-cdn-cache my-cdn-url-map \
  --path="/*"

# Invalidate with host
gcloud compute url-maps invalidate-cdn-cache my-cdn-url-map \
  --path="/js/app.js" \
  --host="cdn.example.com"

Real-World Example: Multi-Region Static Website with Cloud CDN

This example demonstrates a complete setup for a multi-region, high-performance static website using Cloud Storage, Cloud CDN, and Cloud Load Balancing:

Architecture Overview

  1. Cloud Storage buckets in multiple regions for origin content

  2. Cloud Load Balancer for global routing

  3. Cloud CDN for edge caching

  4. Cloud Armor for security

  5. Custom domain with SSL

Terraform Implementation

provider "google" {
  project = var.project_id
  region  = "us-central1"
}

# Variables
variable "project_id" {
  description = "The GCP project ID"
  type        = string
}

variable "domain_name" {
  description = "The domain name for the website"
  type        = string
  default     = "example.com"
}

# Create regional buckets for redundancy
resource "google_storage_bucket" "primary_bucket" {
  name          = "${var.project_id}-website-us"
  location      = "US"
  storage_class = "STANDARD"
  
  uniform_bucket_level_access = true
  website {
    main_page_suffix = "index.html"
    not_found_page   = "404.html"
  }
  
  cors {
    origin          = ["https://${var.domain_name}"]
    method          = ["GET", "HEAD", "OPTIONS"]
    response_header = ["Content-Type", "Cache-Control"]
    max_age_seconds = 3600
  }
}

resource "google_storage_bucket" "backup_bucket" {
  name          = "${var.project_id}-website-eu"
  location      = "EU"
  storage_class = "STANDARD"
  
  uniform_bucket_level_access = true
  website {
    main_page_suffix = "index.html"
    not_found_page   = "404.html"
  }
  
  cors {
    origin          = ["https://${var.domain_name}"]
    method          = ["GET", "HEAD", "OPTIONS"]
    response_header = ["Content-Type", "Cache-Control"]
    max_age_seconds = 3600
  }
}

# Create IAM policies for the buckets
resource "google_storage_bucket_iam_member" "primary_bucket_viewer" {
  bucket = google_storage_bucket.primary_bucket.name
  role   = "roles/storage.objectViewer"
  member = "allUsers"
}

resource "google_storage_bucket_iam_member" "backup_bucket_viewer" {
  bucket = google_storage_bucket.backup_bucket.name
  role   = "roles/storage.objectViewer"
  member = "allUsers"
}

# Create backend buckets for Cloud CDN
resource "google_compute_backend_bucket" "primary_backend" {
  name        = "primary-website-backend"
  description = "Primary website backend bucket"
  bucket_name = google_storage_bucket.primary_bucket.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
    
    cache_key_policy {
      include_host         = true
      include_protocol     = true
      include_query_string = false
    }
  }
}

resource "google_compute_backend_bucket" "backup_backend" {
  name        = "backup-website-backend"
  description = "Backup website backend bucket"
  bucket_name = google_storage_bucket.backup_bucket.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
  }
}

# Create health check for failover
resource "google_compute_health_check" "website_health_check" {
  name               = "website-health-check"
  check_interval_sec = 5
  timeout_sec        = 5
  
  http_health_check {
    port         = 80
    request_path = "/health.html"
  }
}

# Create a Cloud Armor security policy
resource "google_compute_security_policy" "website_security_policy" {
  name = "website-security-policy"
  
  # Rate limiting rule - 100 requests per minute per IP
  rule {
    action   = "throttle"
    priority = 1000
    match {
      versioned_expr = "SRC_IPS_V1"
      config {
        src_ip_ranges = ["*"]
      }
    }
    description = "Rate limiting"
    
    rate_limit_options {
      conform_action = "allow"
      exceed_action  = "deny(429)"
      enforce_on_key = "IP"
      rate_limit_threshold {
        count        = 100
        interval_sec = 60
      }
    }
  }
  
  # Block common web attacks
  rule {
    action   = "deny(403)"
    priority = 2000
    match {
      expr {
        expression = "evaluatePreconfiguredExpr('xss-stable')"
      }
    }
    description = "Block XSS attacks"
  }
  
  rule {
    action   = "deny(403)"
    priority = 2100
    match {
      expr {
        expression = "evaluatePreconfiguredExpr('sql-injection-stable')"
      }
    }
    description = "Block SQL injection attacks"
  }
  
  # Default rule
  rule {
    action   = "allow"
    priority = 2147483647
    match {
      versioned_expr = "SRC_IPS_V1"
      config {
        src_ip_ranges = ["*"]
      }
    }
    description = "Default allow rule"
  }
}

# Create URL map for failover routing
resource "google_compute_url_map" "website_url_map" {
  name            = "website-url-map"
  description     = "URL map for website with failover"
  default_service = google_compute_backend_bucket.primary_backend.id
  
  # Health check based failover
  path_matcher {
    name            = "failover"
    default_service = google_compute_backend_bucket.primary_backend.id
    
    route_rules {
      priority = 1
      service  = google_compute_backend_bucket.primary_backend.id
      
      # If primary is unhealthy, route to backup
      route_action {
        weighted_backend_services {
          backend_service = google_compute_backend_bucket.primary_backend.id
          weight          = 100
        }
        
        fault_injection_policy {
          abort {
            http_status = 502
            percentage  = 100
          }
        }
        
        request_mirror_policy {
          backend_service = google_compute_backend_bucket.backup_backend.id
        }
      }
    }
    
    route_rules {
      priority = 2
      service  = google_compute_backend_bucket.backup_backend.id
    }
  }
}

# Reserve a global IP address
resource "google_compute_global_address" "website_ip" {
  name = "website-global-ip"
}

# Create a managed SSL certificate
resource "google_compute_managed_ssl_certificate" "website_cert" {
  name = "website-ssl-cert"
  
  managed {
    domains = [var.domain_name, "www.${var.domain_name}"]
  }
}

# Create a HTTPS target proxy
resource "google_compute_target_https_proxy" "website_https_proxy" {
  name             = "website-https-proxy"
  url_map          = google_compute_url_map.website_url_map.id
  ssl_certificates = [google_compute_managed_ssl_certificate.website_cert.id]
}

# Create an HTTP target proxy for redirects
resource "google_compute_target_http_proxy" "website_http_proxy" {
  name    = "website-http-proxy"
  url_map = google_compute_url_map.http_redirect.id
}

# Create a URL map for HTTP to HTTPS redirect
resource "google_compute_url_map" "http_redirect" {
  name = "http-redirect"
  
  default_url_redirect {
    https_redirect         = true
    redirect_response_code = "MOVED_PERMANENTLY_DEFAULT"
    strip_query            = false
  }
}

# Create global forwarding rules
resource "google_compute_global_forwarding_rule" "website_https_rule" {
  name       = "website-https-forwarding-rule"
  target     = google_compute_target_https_proxy.website_https_proxy.id
  port_range = "443"
  ip_address = google_compute_global_address.website_ip.address
}

resource "google_compute_global_forwarding_rule" "website_http_rule" {
  name       = "website-http-forwarding-rule"
  target     = google_compute_target_http_proxy.website_http_proxy.id
  port_range = "80"
  ip_address = google_compute_global_address.website_ip.address
}

# Create DNS records
resource "google_dns_managed_zone" "website_zone" {
  name     = "website-zone"
  dns_name = "${var.domain_name}."
}

resource "google_dns_record_set" "website_record" {
  name         = "${var.domain_name}."
  type         = "A"
  ttl          = 300
  managed_zone = google_dns_managed_zone.website_zone.name
  rrdatas      = [google_compute_global_address.website_ip.address]
}

resource "google_dns_record_set" "www_record" {
  name         = "www.${var.domain_name}."
  type         = "A"
  ttl          = 300
  managed_zone = google_dns_managed_zone.website_zone.name
  rrdatas      = [google_compute_global_address.website_ip.address]
}

# Output important information
output "website_ip" {
  value = google_compute_global_address.website_ip.address
}

output "website_url" {
  value = "https://${var.domain_name}"
}

output "bucket_urls" {
  value = {
    primary = google_storage_bucket.primary_bucket.url
    backup  = google_storage_bucket.backup_bucket.url
  }
}

output "cdn_update_command" {
  value = "To invalidate cache: gcloud compute url-maps invalidate-cdn-cache website-url-map --path='/*'"
}

Shell Script for Content Deployment

#!/bin/bash
# deploy_website.sh - Deploy website content to multi-region setup

# Configuration
PROJECT_ID="my-project-id"
PRIMARY_BUCKET="gs://${PROJECT_ID}-website-us"
BACKUP_BUCKET="gs://${PROJECT_ID}-website-eu"
WEBSITE_DIR="./website"

# Check if gsutil is installed
if ! command -v gsutil &> /dev/null; then
    echo "gsutil could not be found. Please install the Google Cloud SDK."
    exit 1
fi

# Validate website directory exists
if [ ! -d "$WEBSITE_DIR" ]; then
    echo "Website directory $WEBSITE_DIR not found."
    exit 1
fi

# Sync website content to primary bucket
echo "Deploying to primary bucket..."
gsutil -m rsync -r -d "$WEBSITE_DIR" "$PRIMARY_BUCKET"

# Set correct content types for web assets
echo "Setting content types..."
gsutil -m setmeta -r \
  -h "Cache-Control:public, max-age=3600" \
  "${PRIMARY_BUCKET}/**/*.html"

gsutil -m setmeta -r \
  -h "Cache-Control:public, max-age=86400" \
  "${PRIMARY_BUCKET}/**/*.css" \
  "${PRIMARY_BUCKET}/**/*.js"

gsutil -m setmeta -r \
  -h "Cache-Control:public, max-age=604800" \
  "${PRIMARY_BUCKET}/**/*.jpg" \
  "${PRIMARY_BUCKET}/**/*.png" \
  "${PRIMARY_BUCKET}/**/*.gif" \
  "${PRIMARY_BUCKET}/**/*.ico" \
  "${PRIMARY_BUCKET}/**/*.webp"

# Create health check file
echo "OK" > /tmp/health.html
gsutil cp /tmp/health.html "${PRIMARY_BUCKET}/health.html"

# Sync to backup bucket for failover
echo "Syncing to backup bucket..."
gsutil -m rsync -r -d "$PRIMARY_BUCKET" "$BACKUP_BUCKET"

# Invalidate CDN cache
echo "Invalidating CDN cache..."
gcloud compute url-maps invalidate-cdn-cache website-url-map --path="/*"

echo "Deployment completed successfully!"

Best Practices

  1. Content Optimization

    • Use appropriate caching headers (Cache-Control, Expires)

    • Enable gzip/Brotli compression for text-based content

    • Optimize images and use modern formats (WebP)

    • Implement HTTP/2 for better performance

  2. Cache Control Strategy

    • Set longer TTLs for static content (images, JS, CSS)

    • Use shorter TTLs for frequently changing content

    • Implement versioned URLs for cache-busting

    • Consider negative caching for 404/5xx errors

  3. Security

    • Use HTTPS with modern TLS versions

    • Implement Cloud Armor security policies

    • Use signed URLs/cookies for private content

    • Apply proper CORS settings for web applications

  4. Performance Monitoring

    • Monitor cache hit ratios

    • Track origin load and bandwidth savings

    • Set up alerts for latency or error rate increases

    • Use Cloud Monitoring dashboards for CDN metrics

  5. Operations

    • Plan cache invalidation strategies

    • Implement CI/CD for content updates

    • Configure multi-region origins for redundancy

    • Use canary deployments for high-traffic sites

Common Issues and Troubleshooting

Cache Misses

  • Verify the cache policy is correctly configured

  • Check the Cache-Control headers from the origin

  • Ensure query strings are handled correctly in cache key

  • Monitor for cache sharding (many unique URLs)

  • Check if client caching headers differ from server headers

SSL/TLS Issues

  • Verify SSL certificate is valid and not expired

  • Check SSL certificate covers all domains being served

  • Ensure OCSP stapling is enabled

  • Verify TLS version compatibility with clients

  • Check for mixed content warnings

Performance Problems

  • Monitor latency by region and edge location

  • Check for origin server performance issues

  • Verify content compression is working

  • Analyze cache hit ratios

  • Optimize critical rendering path

Content Updates Not Appearing

  • Check cache invalidation status

  • Verify cache TTL settings

  • Use versioned URLs for static assets

  • Check for stale-while-revalidate issues

  • Monitor origin server reachability

Further Reading

PreviousServicesNextCloud DNS

Last updated 4 days ago

☁️
Cloud CDN Documentation
Cloud CDN Best Practices
Terraform Google Cloud CDN Resources
Cache Invalidation API
Setting Up Cloud CDN with Cloud Storage