35 min to read
AWS CDN Complete Implementation Guide - Kubernetes + CloudFront for API and Static File Optimization
Building scalable CDN solutions with External-DNS, ALB, S3, and CloudFront for global content delivery

Overview
Content Delivery Networks (CDN) have evolved from optional infrastructure to mission-critical components in modern web applications.
For organizations operating global services or handling high-volume traffic, a well-architected CDN strategy is essential for maintaining user experience and server stability.
This comprehensive guide demonstrates how to build a complete CDN solution using Kubernetes and AWS CloudFront, optimizing both API server responses and static file delivery.
We’ll cover automated DNS management with External-DNS, dual distribution patterns (ALB + CloudFront and S3 + CloudFront), and enterprise-grade security configurations.
Architecture Overview
Our CDN implementation follows a hybrid architecture pattern that addresses different content delivery requirements through specialized distribution strategies.
Dual Distribution Strategy
API Server CDN (ALB + CloudFront): Dynamic content with intelligent caching based on endpoint characteristics
Static File CDN (S3 + CloudFront): Long-term cached static assets with optimized compression and security
Component Architecture
API Server CDN Flow
- Kubernetes Cluster: Application runtime environment with horizontal pod autoscaling
- External-DNS: Automated Route53 record management for service discovery
- Application Load Balancer: Origin server with health checks and SSL termination
- CloudFront Distribution: Global edge caching with path-based cache behaviors
Static File CDN Flow
- S3 Bucket: Secure storage with versioning and lifecycle policies
- Origin Access Control: Zero-trust security model for S3 access
- CloudFront Distribution: Global distribution with file-type optimized caching
- Route53 Integration: DNS alias records for custom domain routing
Step 1: External-DNS Configuration
External-DNS serves as the automation backbone for DNS management, automatically creating and updating Route53 records based on Kubernetes resource annotations.
# external-dns-values.yaml
image:
repository: registry.k8s.io/external-dns/external-dns
pullPolicy: IfNotPresent
serviceAccount:
create: true
annotations:
# IRSA (IAM Role for Service Account) configuration
eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/external-dns-role
# Deploy to system-dedicated nodegroup for stability
nodeSelector:
eks.amazonaws.com/nodegroup: system-nodegroup
# Security hardening - principle of least privilege
podSecurityContext:
runAsNonRoot: true
fsGroup: 65534
securityContext:
privileged: false
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
capabilities:
drop: ["ALL"]
rbac:
create: true
# Resource optimization
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 256Mi
# Logging and monitoring configuration
logLevel: info
logFormat: text
interval: 5m
# Resource types to monitor
sources:
- service
- ingress
# DNS record management policy
policy: upsert-only # Safe record management
registry: txt
txtOwnerId: "enterprise-external-dns"
txtPrefix: "external-dns-"
# Domain filtering for security
domainFilters:
- enterprise.example.com
# AWS Route53 provider configuration
provider:
name: aws
extraArgs:
- --aws-zone-type=public
- --aws-prefer-cname
- --annotation-filter=external-dns.alpha.kubernetes.io/hostname
Step 2: ACM Certificate Generation for CloudFront
CloudFront requires certificates specifically issued in the us-east-1 region. We’ll use Terraform to provision certificates with proper validation.
# acm-certificates.tf
module "cloudfront_certificate" {
source = "../../../modules/acm/v6.1.0"
providers = {
aws = aws.us_east_1 # CloudFront certificates must be in us-east-1
}
domain_name = var.root_domain
zone_id = aws_route53_zone.main_zone.zone_id
validation_method = "DNS"
subject_alternative_names = [
"*.enterprise.example.com",
"enterprise.example.com"
]
wait_for_validation = true
tags = {
Environment = var.environment
Project = var.project
Terraform = var.terraform
Purpose = "CloudFront-SSL"
Name = "cloudfront-acm-certificate"
}
depends_on = [aws_route53_zone.main_zone]
}
Step 3: API Origin Server Setup
Creating dedicated origin domains separates CDN traffic from direct access, enabling better traffic analysis and security controls.
# api-ingress-values.yaml
ingress:
enabled: true
className: "alb"
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
# Shared ALB group for cost optimization
alb.ingress.kubernetes.io/group.name: enterprise-shared-alb
alb.ingress.kubernetes.io/group.order: "10"
# Origin-specific domain configuration
external-dns.alpha.kubernetes.io/hostname: origin-api.enterprise.example.com
# Explicit ALB naming
alb.ingress.kubernetes.io/load-balancer-name: enterprise-shared-alb-loadbalancer
# SSL configuration (ALB - service region certificate)
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:eu-central-1:123456789012:certificate/cert-id
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS": 443}]' # HTTPS only
# ALB optimization for CDN
alb.ingress.kubernetes.io/target-group-attributes: |
deregistration_delay.timeout_seconds=30,
stickiness.enabled=false
# Purpose identification through tagging
alb.ingress.kubernetes.io/tags: "Purpose=CDN-Origin,Environment=production"
hosts:
- host: origin-api.enterprise.example.com
paths:
- path: /
pathType: Prefix
Step 4: API CloudFront Distribution Configuration
The API distribution requires sophisticated caching strategies that account for different endpoint characteristics and data sensitivity levels.
# cloudfront-api.tf
module "api_cdn" {
source = "terraform-aws-modules/cloudfront/aws"
aliases = ["api.enterprise.example.com"]
comment = "Enterprise API CloudFront Distribution"
enabled = true
is_ipv6_enabled = true
price_class = "PriceClass_100" # North America, Europe focused
retain_on_delete = false
wait_for_deployment = false
# ALB Origin configuration
origin = {
alb_api_origin = {
domain_name = "origin-api.enterprise.example.com"
custom_origin_config = {
http_port = 443
https_port = 443
origin_protocol_policy = "https-only"
origin_ssl_protocols = ["TLSv1.2"]
origin_read_timeout = 60
origin_keepalive_timeout = 5
}
# Origin Shield for improved cache hit ratio
origin_shield = {
enabled = true
origin_shield_region = "eu-central-1" # Match service region
}
}
}
# Default cache behavior - general API responses
default_cache_behavior = {
target_origin_id = "alb_api_origin"
viewer_protocol_policy = "redirect-to-https"
allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
cached_methods = ["GET", "HEAD", "OPTIONS"]
compress = true
use_forwarded_values = true
query_string = true
headers = ["Host", "Origin", "Referer", "CloudFront-Forwarded-Proto"]
cookies_forward = "none"
min_ttl = 0
default_ttl = 3600 # 1 hour default cache
max_ttl = 86400 # Maximum 24 hours
}
# Endpoint-specific cache control
ordered_cache_behavior = [
# Health checks - short cache for rapid failure detection
{
path_pattern = "/health"
target_origin_id = "alb_api_origin"
viewer_protocol_policy = "redirect-to-https"
allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD"]
compress = true
use_forwarded_values = true
query_string = false
headers = ["Host"]
cookies_forward = "none"
min_ttl = 0
default_ttl = 30 # 30 seconds
max_ttl = 300 # Maximum 5 minutes
},
# Static configuration data - medium cache duration
{
path_pattern = "/api/configs/*"
target_origin_id = "alb_api_origin"
viewer_protocol_policy = "redirect-to-https"
allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD"]
compress = true
use_forwarded_values = true
query_string = true
headers = ["Host", "Authorization", "Content-Type"]
cookies_forward = "all"
min_ttl = 0
default_ttl = 1800 # 30 minutes
max_ttl = 3600 # 1 hour
},
# Product listings - considering change frequency
{
path_pattern = "/api/products/list"
target_origin_id = "alb_api_origin"
viewer_protocol_policy = "redirect-to-https"
allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD"]
compress = true
use_forwarded_values = true
query_string = true
headers = ["Host", "Authorization"]
cookies_forward = "all"
min_ttl = 0
default_ttl = 900 # 15 minutes
max_ttl = 1800 # 30 minutes
},
# Authentication endpoints - cache completely disabled
{
path_pattern = "/auth/*"
target_origin_id = "alb_api_origin"
viewer_protocol_policy = "redirect-to-https"
allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
cached_methods = ["GET", "HEAD"]
compress = true
use_forwarded_values = true
query_string = true
headers = ["*"] # Forward all headers
cookies_forward = "all"
min_ttl = 0
default_ttl = 0 # No caching
max_ttl = 0
},
# User-specific data - cache disabled
{
path_pattern = "/api/users/*"
target_origin_id = "alb_api_origin"
viewer_protocol_policy = "redirect-to-https"
allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
cached_methods = ["GET", "HEAD"]
compress = true
use_forwarded_values = true
query_string = true
headers = ["*"]
cookies_forward = "all"
min_ttl = 0
default_ttl = 0
max_ttl = 0
}
]
# SSL certificate configuration
viewer_certificate = {
acm_certificate_arn = module.cloudfront_certificate.acm_certificate_arn
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1.2_2021"
}
# Geographic restrictions
geo_restriction = {
restriction_type = "none"
}
# SPA support through error page handling
custom_error_response = [
{
error_code = 404
response_code = 200
response_page_path = "/index.html"
}
]
tags = {
Environment = var.environment
Project = var.project
Terraform = var.terraform
Name = "enterprise-api-cdn"
Purpose = "API-Distribution"
}
depends_on = [module.cloudfront_certificate]
}
Step 5: Route53 DNS Configuration
Comprehensive DNS setup supporting both IPv4 and IPv6 for maximum global accessibility.
# route53.tf
resource "aws_route53_zone" "main_zone" {
name = var.domain_name
tags = {
Environment = var.environment
Project = var.project
Terraform = var.terraform
Name = "main-route53-zone"
}
}
# API CDN A record (IPv4)
resource "aws_route53_record" "api_cdn" {
zone_id = aws_route53_zone.main_zone.zone_id
name = "api.enterprise.example.com"
type = "A"
alias {
name = module.api_cdn.cloudfront_distribution_domain_name
zone_id = module.api_cdn.cloudfront_distribution_hosted_zone_id
evaluate_target_health = false
}
depends_on = [
aws_route53_zone.main_zone,
module.api_cdn
]
}
# API CDN AAAA record (IPv6)
resource "aws_route53_record" "api_cdn_ipv6" {
zone_id = aws_route53_zone.main_zone.zone_id
name = "api.enterprise.example.com"
type = "AAAA"
alias {
name = module.api_cdn.cloudfront_distribution_domain_name
zone_id = module.api_cdn.cloudfront_distribution_hosted_zone_id
evaluate_target_health = false
}
depends_on = [
aws_route53_zone.main_zone,
module.api_cdn
]
}
# Static files CDN A record (IPv4)
resource "aws_route53_record" "static_files_cdn" {
zone_id = aws_route53_zone.main_zone.zone_id
name = "cdn.enterprise.example.com"
type = "A"
alias {
name = module.static_files_cdn.cloudfront_distribution_domain_name
zone_id = module.static_files_cdn.cloudfront_distribution_hosted_zone_id
evaluate_target_health = false
}
depends_on = [
aws_route53_zone.main_zone,
module.static_files_cdn
]
}
# Static files CDN AAAA record (IPv6)
resource "aws_route53_record" "static_files_cdn_ipv6" {
zone_id = aws_route53_zone.main_zone.zone_id
name = "cdn.enterprise.example.com"
type = "AAAA"
alias {
name = module.static_files_cdn.cloudfront_distribution_domain_name
zone_id = module.static_files_cdn.cloudfront_distribution_hosted_zone_id
evaluate_target_health = false
}
depends_on = [
aws_route53_zone.main_zone,
module.static_files_cdn
]
}
IPv6 Support Benefits
| Benefit | Technical Advantage | Business Impact |
|---|---|---|
| Address Space | Unlimited addressing vs IPv4 exhaustion | Future-proof infrastructure design |
| Performance | No NAT overhead, direct routing | Lower latency for mobile users |
| Global Reach | High adoption in APAC regions | Better user experience in key markets |
| Mobile Networks | LTE/5G prefer IPv6 | Optimized mobile application performance |
Step 6: S3 Static File Storage Configuration
Implementing zero-trust security model with Origin Access Control for maximum protection.
# s3-static-files.tf
module "static_files_bucket" {
source = "terraform-aws-modules/s3-bucket/aws"
bucket = var.static_files_bucket_name
# Private bucket with complete isolation
control_object_ownership = true
object_ownership = "ObjectWriter"
# Block all public access (security hardening)
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
# Server-side encryption configuration
server_side_encryption_configuration = {
rule = {
apply_server_side_encryption_by_default = {
sse_algorithm = "AES256"
}
}
}
# Versioning for file recovery and change tracking
versioning = {
enabled = true
}
# Lifecycle management for cost optimization
lifecycle_configuration = {
rule = [
{
id = "delete_old_versions"
status = "Enabled"
noncurrent_version_expiration = {
noncurrent_days = 30
}
abort_incomplete_multipart_upload = {
days_after_initiation = 7
}
}
]
}
tags = {
Environment = var.environment
Project = var.project
Terraform = var.terraform
Name = var.static_files_bucket_name
Purpose = "Static-File-Storage"
}
depends_on = [aws_route53_zone.main_zone]
}
# S3 bucket policy - CloudFront-only access (security enhancement)
resource "aws_s3_bucket_policy" "static_files" {
bucket = module.static_files_bucket.s3_bucket_id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "AllowCloudFrontServicePrincipal"
Effect = "Allow"
Principal = {
Service = "cloudfront.amazonaws.com"
}
Action = "s3:GetObject"
Resource = "${module.static_files_bucket.s3_bucket_arn}/*"
Condition = {
StringEquals = {
"AWS:SourceArn" = module.static_files_cdn.cloudfront_distribution_arn
}
}
}
]
})
depends_on = [
module.static_files_bucket,
module.static_files_cdn
]
}
Step 7: S3-based CloudFront Distribution
Optimized distribution configuration for static file delivery with file-type specific caching strategies.
# cloudfront-s3.tf
module "static_files_cdn" {
source = "terraform-aws-modules/cloudfront/aws"
aliases = ["cdn.enterprise.example.com"]
comment = "Enterprise Static Files CDN Distribution"
enabled = true
is_ipv6_enabled = true
price_class = "PriceClass_100"
retain_on_delete = false
wait_for_deployment = false
# Origin Access Control setup (modern approach, replaces OAI)
create_origin_access_control = true
origin_access_control = {
s3_oac = {
description = "CloudFront access to S3 static files"
origin_type = "s3"
signing_behavior = "always"
signing_protocol = "sigv4"
}
}
# S3 Origin configuration
origin = {
s3_static_files = {
domain_name = module.static_files_bucket.s3_bucket_bucket_regional_domain_name
origin_access_control = "s3_oac"
}
}
# Default cache behavior - long cache for static files
default_cache_behavior = {
target_origin_id = "s3_static_files"
viewer_protocol_policy = "redirect-to-https"
allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD"]
compress = true
# S3 doesn't require cookies or query strings
use_forwarded_values = true
query_string = false
cookies_forward = "none"
# Long TTL for static files
min_ttl = 0
default_ttl = 86400 # 24 hours
max_ttl = 31536000 # 1 year
}
# File-type specific cache control
ordered_cache_behavior = [
# Image files - very long cache (low change frequency)
{
path_pattern = "*.{jpg,jpeg,png,gif,webp,svg,ico}"
target_origin_id = "s3_static_files"
viewer_protocol_policy = "https-only"
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
compress = true
use_forwarded_values = true
query_string = false
cookies_forward = "none"
min_ttl = 0
default_ttl = 2592000 # 30 days
max_ttl = 31536000 # 1 year
},
# CSS/JS files - long cache (compression optimization)
{
path_pattern = "*.{css,js}"
target_origin_id = "s3_static_files"
viewer_protocol_policy = "https-only"
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
compress = true
use_forwarded_values = true
query_string = false
cookies_forward = "none"
min_ttl = 0
default_ttl = 604800 # 7 days
max_ttl = 2592000 # 30 days
},
# Download files - long cache + CORS headers
{
path_pattern = "/downloads/*"
target_origin_id = "s3_static_files"
viewer_protocol_policy = "https-only"
allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD"]
compress = true
use_forwarded_values = true
query_string = true
headers = ["Origin", "Access-Control-Request-Headers", "Access-Control-Request-Method"]
cookies_forward = "none"
min_ttl = 0
default_ttl = 86400 # 1 day
max_ttl = 31536000 # 1 year
},
# Document files - medium cache (compression disabled)
{
path_pattern = "*.{pdf,doc,docx,xls,xlsx,ppt,pptx,zip,rar}"
target_origin_id = "s3_static_files"
viewer_protocol_policy = "https-only"
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
compress = false # Pre-compressed files don't need additional compression
use_forwarded_values = true
query_string = false
cookies_forward = "none"
min_ttl = 0
default_ttl = 604800 # 7 days
max_ttl = 2592000 # 30 days
}
]
# SSL certificate configuration
viewer_certificate = {
acm_certificate_arn = module.cloudfront_certificate.acm_certificate_arn
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1.2_2021"
}
# No geographic restrictions
geo_restriction = {
restriction_type = "none"
}
# Default index file
default_root_object = "index.html"
# Error page configuration
custom_error_response = [
{
error_code = 403
response_code = 404
response_page_path = "/errors/404.html"
},
{
error_code = 404
response_code = 404
response_page_path = "/errors/404.html"
}
]
tags = {
Environment = var.environment
Project = var.project
Terraform = var.terraform
Name = "enterprise-static-files-cdn"
Purpose = "Static-File-Distribution"
}
depends_on = [
module.static_files_bucket,
module.cloudfront_certificate
]
}
Step 8: Advanced Security and Optimization
CloudFront Functions for Security Headers
# cloudfront-functions.tf
resource "aws_cloudfront_function" "security_headers" {
name = "add-security-headers"
runtime = "cloudfront-js-1.0"
comment = "Add security headers to all responses"
publish = true
code = <<-EOT
function handler(event) {
var response = event.response;
var headers = response.headers;
// Security headers implementation
headers['strict-transport-security'] = {
value: 'max-age=31536000; includeSubdomains; preload'
};
headers['content-security-policy'] = {
value: "default-src 'self'; img-src 'self' data: https:; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'"
};
headers['x-frame-options'] = {value: 'DENY'};
headers['x-content-type-options'] = {value: 'nosniff'};
headers['referrer-policy'] = {value: 'strict-origin-when-cross-origin'};
headers['permissions-policy'] = {
value: 'geolocation=(), camera=(), microphone=()'
};
return response;
}
EOT
}
CI/CD IAM Role Configuration
# iam-deployment.tf
resource "aws_iam_role" "cicd_deployment_role" {
name = "enterprise-cicd-deployment-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "codebuild.amazonaws.com" # CodeBuild or required service
}
}
]
})
tags = {
Environment = var.environment
Purpose = "CI-CD-Deployment"
}
}
resource "aws_iam_role_policy" "s3_deployment_policy" {
name = "s3-deployment-policy"
role = aws_iam_role.cicd_deployment_role.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject",
"s3:DeleteObject",
"s3:ListBucket"
]
Resource = [
module.static_files_bucket.s3_bucket_arn,
"${module.static_files_bucket.s3_bucket_arn}/*"
]
},
{
Effect = "Allow"
Action = [
"cloudfront:CreateInvalidation",
"cloudfront:GetInvalidation",
"cloudfront:ListInvalidations"
]
Resource = [
module.static_files_cdn.cloudfront_distribution_arn,
module.api_cdn.cloudfront_distribution_arn
]
}
]
})
}
Step 9: WAF Integration for Enhanced Security
# waf-protection.tf
resource "aws_wafv2_web_acl" "cdn_protection" {
name = "enterprise-cdn-protection"
scope = "CLOUDFRONT"
default_action {
allow {}
}
rule {
name = "AWSManagedRulesCommonRuleSet"
priority = 1
override_action {
none {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesCommonRuleSet"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "CommonRuleSetMetric"
sampled_requests_enabled = true
}
}
rule {
name = "AWSManagedRulesKnownBadInputsRuleSet"
priority = 2
override_action {
none {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesKnownBadInputsRuleSet"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "KnownBadInputsMetric"
sampled_requests_enabled = true
}
}
rule {
name = "RateLimitRule"
priority = 3
action {
block {}
}
statement {
rate_based_statement {
limit = 2000
aggregate_key_type = "IP"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "RateLimitMetric"
sampled_requests_enabled = true
}
}
tags = {
Environment = var.environment
Name = "enterprise-cdn-waf"
}
}
Step 10: Monitoring and Alerting Configuration
# monitoring.tf
resource "aws_cloudwatch_metric_alarm" "high_4xx_error_rate" {
alarm_name = "cloudfront-high-4xx-error-rate"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = "2"
metric_name = "4xxErrorRate"
namespace = "AWS/CloudFront"
period = "300"
statistic = "Average"
threshold = "5.0"
alarm_description = "CloudFront 4xx error rate exceeds threshold"
alarm_actions = [aws_sns_topic.alerts.arn]
dimensions = {
DistributionId = module.api_cdn.cloudfront_distribution_id
}
tags = {
Environment = var.environment
Purpose = "CDN-Monitoring"
}
}
resource "aws_cloudwatch_metric_alarm" "high_5xx_error_rate" {
alarm_name = "cloudfront-high-5xx-error-rate"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = "2"
metric_name = "5xxErrorRate"
namespace = "AWS/CloudFront"
period = "300"
statistic = "Average"
threshold = "2.0"
alarm_description = "CloudFront 5xx error rate exceeds threshold"
alarm_actions = [aws_sns_topic.alerts.arn]
dimensions = {
DistributionId = module.api_cdn.cloudfront_distribution_id
}
tags = {
Environment = var.environment
Purpose = "CDN-Monitoring"
}
}
resource "aws_cloudwatch_metric_alarm" "low_cache_hit_rate" {
alarm_name = "cloudfront-low-cache-hit-rate"
comparison_operator = "LessThanThreshold"
evaluation_periods = "3"
metric_name = "CacheHitRate"
namespace = "AWS/CloudFront"
period = "900"
statistic = "Average"
threshold = "80.0"
alarm_description = "CloudFront cache hit rate is below optimal threshold"
alarm_actions = [aws_sns_topic.alerts.arn]
dimensions = {
DistributionId = module.static_files_cdn.cloudfront_distribution_id
}
tags = {
Environment = var.environment
Purpose = "CDN-Performance"
}
}
resource "aws_sns_topic" "alerts" {
name = "enterprise-cdn-alerts"
tags = {
Environment = var.environment
Purpose = "CDN-Alerting"
}
}
Step 11: Deployment and Validation
Comprehensive Validation Script
Operational Considerations
Cache Strategy Optimization
| Content Type | Cache Duration | Reasoning | Monitoring Focus |
|---|---|---|---|
| Authentication APIs | No cache (0s) | Security and real-time validation | Response time, error rates |
| User-specific Data | No cache (0s) | Privacy and data freshness | Origin load, personalization accuracy |
| Configuration Data | Medium (30min-1hr) | Balance between freshness and performance | Cache hit rate, update propagation |
| Product Listings | Short (15-30min) | Inventory changes require quick updates | Business impact of stale data |
| Health Checks | Very short (30s-5min) | Rapid failure detection | Monitoring system responsiveness |
| Static Images | Very long (30+ days) | Rarely change, bandwidth savings | Storage costs vs performance |
| CSS/JS Files | Long (7-30 days) | Version-controlled deployments | Cache invalidation effectiveness |
| Download Files | Long (1 day-1 year) | Large files, expensive to transfer | Bandwidth costs, user experience |
Performance Optimization Strategies
# Advanced cache policy configuration
resource "aws_cloudfront_cache_policy" "optimized_api" {
name = "enterprise-optimized-api-cache-policy"
comment = "Optimized cache policy for API responses"
default_ttl = 3600
max_ttl = 86400
min_ttl = 0
parameters_in_cache_key_and_forwarded_to_origin {
query_strings_config {
query_string_behavior = "whitelist"
query_strings {
items = ["page", "limit", "sort", "filter"] # Only necessary query parameters
}
}
headers_config {
header_behavior = "whitelist"
headers {
items = ["Authorization", "Content-Type", "Accept-Language"] # Essential headers only
}
}
cookies_config {
cookie_behavior = "none" # APIs typically don't need cookies
}
enable_accept_encoding_gzip = true
enable_accept_encoding_brotli = true
}
}
# Response headers policy for performance
resource "aws_cloudfront_response_headers_policy" "performance_security" {
name = "enterprise-performance-security-headers"
comment = "Performance and security headers for CDN"
cors_config {
access_control_allow_credentials = false
access_control_allow_headers {
items = ["Authorization", "Content-Type", "X-Requested-With"]
}
access_control_allow_methods {
items = ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
}
access_control_allow_origins {
items = ["https://enterprise.example.com", "https://*.enterprise.example.com"]
}
access_control_max_age_sec = 86400
origin_override = false
}
security_headers_config {
strict_transport_security {
access_control_max_age_sec = 31536000
include_subdomains = true
preload = true
override = false
}
content_type_options {
override = false
}
frame_options {
frame_option = "DENY"
override = false
}
referrer_policy {
referrer_policy = "strict-origin-when-cross-origin"
override = false
}
}
custom_headers_config {
items {
header = "X-CDN-Cache-Status"
value = "Enterprise-CDN"
override = false
}
}
}
Cost Optimization Techniques
Disaster Recovery and Incident Response
Security Best Practices
Advanced WAF Rules
# Geo-blocking for security
resource "aws_wafv2_web_acl" "enhanced_protection" {
name = "enterprise-enhanced-cdn-protection"
scope = "CLOUDFRONT"
default_action {
allow {}
}
# Geographic restrictions
rule {
name = "GeoBlocking"
priority = 1
action {
block {}
}
statement {
geo_match_statement {
country_codes = ["CN", "RU", "KP"] # Block specific countries
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "GeoBlockingMetric"
sampled_requests_enabled = true
}
}
# IP reputation blocking
rule {
name = "AWSManagedRulesAmazonIpReputationList"
priority = 2
override_action {
none {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesAmazonIpReputationList"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "IpReputationMetric"
sampled_requests_enabled = true
}
}
# SQL injection protection
rule {
name = "AWSManagedRulesSQLiRuleSet"
priority = 3
override_action {
none {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesSQLiRuleSet"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "SQLiProtectionMetric"
sampled_requests_enabled = true
}
}
}
Conclusion
This comprehensive CDN implementation guide demonstrates how to build enterprise-grade content delivery infrastructure using Kubernetes and AWS CloudFront. The dual distribution strategy addresses both dynamic API content and static file delivery requirements through specialized optimization approaches.
Key architectural achievements include:
- Intelligent Caching Strategy: Content-aware TTL configurations that balance performance with data freshness requirements
- Zero-Trust Security Model: Origin Access Control (OAC) implementation ensuring S3 buckets remain completely private while enabling CloudFront access
- Cost-Effective Operations: Strategic use of Price Classes, Origin Shield, and compression to optimize global delivery costs
- Proactive Monitoring: Comprehensive CloudWatch metrics and alerting for maintaining optimal performance
The modern OAC approach represents a significant security improvement over legacy OAI methods, providing more granular access control and better integration with AWS IAM policies. Additionally, the IPv6 support ensures future-proof connectivity for mobile and international users.
Operational excellence is achieved through:
- Automated DNS management via External-DNS
- File-type specific cache optimizations
- Emergency response procedures for rapid incident resolution
- Advanced WAF integration for comprehensive threat protection
For production deployments, continuous performance monitoring and cache hit rate analysis are essential for optimization. Regular security reviews and adoption of new AWS features will ensure the CDN infrastructure remains efficient and secure as business requirements evolve.
The implementation provides a solid foundation for scaling global applications while maintaining security, performance, and cost efficiency across diverse content delivery scenarios.
Comments