name: aws-cloudfront-cdn description: 使用CloudFront进行全球内容分发,包括缓存、安全头部、WAF集成和源配置。用于低延迟内容交付。
AWS CloudFront CDN
概览
Amazon CloudFront是一个快速、全球分布的内容分发网络(CDN)。在世界各地的边缘位置缓存内容,以减少延迟、提高性能,并提供高可用性以及DDoS保护。
使用场景
- 静态网站托管和资源
- API加速和动态内容
- 视频和媒体流
- 移动应用内容
- 大文件下载
- 实时数据分发
- DDoS保护源
- 源隔离和安全
实施示例
1. 使用AWS CLI的CloudFront分发
# 为S3源创建分发
aws cloudfront create-distribution \
--distribution-config '{
"CallerReference": "myapp-'$(date +%s)'",
"Enabled": true,
"Comment": "我的应用分发",
"Origins": {
"Quantity": 1,
"Items": [{
"Id": "myS3Origin",
"DomainName": "mybucket.s3.us-east-1.amazonaws.com",
"S3OriginConfig": {
"OriginAccessIdentity": "origin-access-identity/cloudfront/ABCDEFG1234567"
}
}]
},
"DefaultCacheBehavior": {
"AllowedMethods": {
"Quantity": 3,
"Items": ["GET", "HEAD", "OPTIONS"]
},
"ViewerProtocolPolicy": "redirect-to-https",
"TargetOriginId": "myS3Origin",
"ForwardedValues": {
"QueryString": false,
"Cookies": {"Forward": "none"},
"Headers": {"Quantity": 0}
},
"TrustedSigners": {
"Enabled": false,
"Quantity": 0
},
"MinTTL": 0,
"DefaultTTL": 86400,
"MaxTTL": 31536000,
"Compress": true
},
"CacheBehaviors": [
{
"PathPattern": "/api/*",
"AllowedMethods": {
"Quantity": 7,
"Items": ["GET", "HEAD", "OPTIONS", "PUT", "POST", "PATCH", "DELETE"]
},
"ViewerProtocolPolicy": "https-only",
"TargetOriginId": "myS3Origin",
"ForwardedValues": {
"QueryString": true,
"Cookies": {"Forward": "all"},
"Headers": {"Quantity": 0}
},
"MinTTL": 0,
"DefaultTTL": 0,
"MaxTTL": 31536000
}
],
"WebACLId": "arn:aws:wafv2:us-east-1:123456789012:global/webacl/test/a1234567"
}'
# 列出分发
aws cloudfront list-distributions
# 获取分发配置
aws cloudfront get-distribution-config \
--id E123EXAMPLE123
# 使缓存失效
aws cloudfront create-invalidation \
--distribution-id E123EXAMPLE123 \
--paths "/*"
2. Terraform CloudFront配置
# cloudfront.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
# 源访问身份
resource "aws_cloudfront_origin_access_identity" "s3" {
comment = "OAI for S3 bucket"
}
# CloudFront源的S3桶
resource "aws_s3_bucket" "static" {
bucket = "myapp-static-${data.aws_caller_identity.current.account_id}"
}
resource "aws_s3_bucket_versioning" "static" {
bucket = aws_s3_bucket.static.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_public_access_block" "static" {
bucket = aws_s3_bucket.static.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
# S3桶策略用于CloudFront
resource "aws_s3_bucket_policy" "static" {
bucket = aws_s3_bucket.static.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Sid = "AllowCloudFrontAccess"
Effect = "Allow"
Principal = {
AWS = aws_cloudfront_origin_access_identity.s3.iam_arn
}
Action = "s3:GetObject"
Resource = "${aws_s3_bucket.static.arn}/*"
}]
})
}
# WAF Web ACL
resource "aws_wafv2_web_acl" "cloudfront" {
scope = "CLOUDFRONT"
name = "cloudfront-waf"
default_action {
allow {}
}
rule {
name = "RateLimitRule"
priority = 1
action {
block {}
}
statement {
rate_based_statement {
limit = 2000
aggregate_key_type = "IP"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "RateLimitRule"
sampled_requests_enabled = true
}
}
rule {
name = "AWSManagedRulesCommonRuleSet"
priority = 2
action {
block {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesCommonRuleSet"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "AWSManagedRulesCommonRuleSet"
sampled_requests_enabled = true
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "cloudfront-waf"
sampled_requests_enabled = true
}
}
# CloudFront分发
resource "aws_cloudfront_distribution" "s3" {
enabled = true
is_ipv6_enabled = true
default_root_object = "index.html"
comment = "CDN for static assets"
origin {
domain_name = aws_s3_bucket.static.bucket_regional_domain_name
origin_id = "S3Origin"
s3_origin_config {
origin_access_identity = aws_cloudfront_origin_access_identity.s3.cloudfront_access_identity_path
}
}
default_cache_behavior {
allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "S3Origin"
forwarded_values {
query_string = false
cookies {
forward = "none"
}
headers = ["Origin", "Accept-Charset"]
}
viewer_protocol_policy = "redirect-to-https"
min_ttl = 0
default_ttl = 86400
max_ttl = 31536000
compress = true
}
cache_behavior {
path_pattern = "/api/*"
allowed_methods = ["GET", "HEAD", "OPTIONS", "PUT", "POST", "PATCH", "DELETE"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "S3Origin"
forwarded_values {
query_string = true
cookies {
forward = "all"
}
headers = ["Authorization", "Host", "User-Agent"]
}
viewer_protocol_policy = "https-only"
min_ttl = 0
default_ttl = 0
max_ttl = 31536000
}
restrictions {
geo_restriction {
restriction_type = "none"
}
}
viewer_certificate {
cloudfront_default_certificate = true
}
web_acl_id = aws_wafv2_web_acl.cloudfront.arn
tags = {
Name = "cdn-distribution"
}
}
# CloudFront缓存策略用于静态资产
resource "aws_cloudfront_cache_policy" "static" {
name = "static-cache-policy"
comment = "Cache policy for static assets"
default_ttl = 86400
max_ttl = 31536000
min_ttl = 0
parameters_in_cache_key_and_forwarded_to_origin {
query_strings_config {
query_string_behavior = "none"
}
headers_config {
header_behavior = "none"
}
cookies_config {
cookie_behavior = "none"
}
enable_accept_encoding_gzip = true
enable_accept_encoding_brotli = true
}
}
# 源请求策略
resource "aws_cloudfront_origin_request_policy" "api" {
name = "api-origin-request-policy"
comment = "Forward headers for API requests"
headers_config {
header_behavior = "allViewer"
}
query_strings_config {
query_string_behavior = "all"
}
cookies_config {
cookie_behavior = "all"
}
}
# 使缓存失效
resource "aws_cloudfront_invalidation" "s3" {
distribution_id = aws_cloudfront_distribution.s3.id
paths = ["/*"]
depends_on = [aws_cloudfront_distribution.s3]
}
# CloudWatch报警
resource "aws_cloudwatch_metric_alarm" "cloudfront_errors" {
alarm_name = "cloudfront-high-error-rate"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 2
metric_name = "4xxErrorRate"
namespace = "AWS/CloudFront"
period = 300
statistic = "Average"
threshold = 5
alarm_description = "Alert when error rate exceeds 5%"
dimensions = {
DistributionId = aws_cloudfront_distribution.s3.id
}
}
data "aws_caller_identity" "current" {}
output "cloudfront_domain" {
value = aws_cloudfront_distribution.s3.domain_name
description = "CloudFront domain name"
}
output "cloudfront_id" {
value = aws_cloudfront_distribution.s3.id
description = "CloudFront distribution ID"
}
3. 自定义头部和安全配置
# 添加自定义安全头部
aws cloudfront create-response-headers-policy \
--response-headers-policy-config '{
"Name": "SecurityHeadersPolicy",
"SecurityHeadersConfig": {
"StrictTransportSecurity": {
"Enabled": true,
"AccessControlMaxAgeSec": 63072000,
"IncludeSubdomains": true,
"Preload": true
},
"ContentTypeOptions": {
"Enabled": true
},
"XSSProtection": {
"Enabled": true,
"ModeBlock": true
},
"ReferrerPolicy": {
"Enabled": true,
"ReferrerPolicy": "strict-origin-when-cross-origin"
},
"FrameOptions": {
"Enabled": true,
"FrameOption": "DENY"
}
}
}'
最佳实践
✅ DO
- 对S3使用源访问身份(OAI)
- 仅对观众启用HTTPS
- 在CloudFront压缩内容
- 设置适当的缓存TTL
- 谨慎使用缓存失效
- 启用WAF保护
- 监控CloudWatch指标
- 为冗余使用多个源
❌ DON’T
- 不要使S3桶公开
- 不要缓存敏感数据
- 生产中不要使用HTTP
- 忽略缓存头部
- 创建过多的失效
- 跳过WAF保护
监控
- CloudWatch指标(请求、字节、错误)
- CloudWatch报警用于错误和延迟
- WAF指标和阻止的请求
- 缓存命中率/未命中率
- 源延迟指标