跳到主要内容

AWS-S3-CloudFront-ALB实战

1. 架构

用户

Route 53 (DNS)

CloudFront (CDN)

├── S3 (静态文件)
└── ALB → EC2 / ECS / Lambda (动态)

2. S3 静态托管

2.1 创建 bucket

aws s3 mb s3://my-frontend --region us-east-1

# 关闭公开访问限制(如果要公开)
aws s3api delete-public-access-block --bucket my-frontend

2.2 上传 + 缓存头

# JS / CSS 长缓存
aws s3 sync ./dist/assets s3://my-frontend/assets/ \
--cache-control "public, max-age=31536000, immutable"

# HTML 不缓存
aws s3 cp ./dist/index.html s3://my-frontend/index.html \
--cache-control "no-cache"

# 全量同步并删除多余
aws s3 sync ./dist s3://my-frontend/ --delete

2.3 Bucket Policy(CloudFront OAC 访问)

{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": { "Service": "cloudfront.amazonaws.com" },
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-frontend/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::123456789:distribution/E123ABC"
}
}
}]
}

S3 不直接公开 → CloudFront 通过 OAC(Origin Access Control)访问 → 用户只能通过 CloudFront。

3. CloudFront

3.1 Distribution 配置

控制台 → CloudFront → Create distribution:

  • Origin:S3 bucket 选刚才的
  • Origin access:Origin access control(OAC)
  • Viewer protocol policy:Redirect HTTP to HTTPS
  • Allowed HTTP methods:GET, HEAD, OPTIONS
  • Cache policy:CachingOptimized(自动)
  • Compress:Yes
  • Price class:100(仅北美 + 欧洲,便宜)

3.2 缓存行为

按路径定不同策略:

/api/* → Origin: ALB cache-policy: CachingDisabled
/_next/* → Origin: S3 cache-policy: CachingOptimized
/* (default) → Origin: S3 cache-policy: CachingOptimized

3.3 自定义错误页

SPA fallback:

  • HTTP error code: 403 / 404
  • Response page path: /index.html
  • HTTP response code: 200

3.4 失效(Invalidation)

aws cloudfront create-invalidation \
--distribution-id E123ABC \
--paths "/index.html" "/"

每月前 1000 路径免费,超出收费。

3.5 自定义域名

CloudFront → Alternate domain names → 加 app.example.com。 关联 ACM 证书(必须 us-east-1 region 的证书)。 Route 53 加 ALIAS 记录指向 CloudFront。

4. ACM(证书)

# 申请证书
aws acm request-certificate \
--domain-name "*.example.com" \
--validation-method DNS \
--subject-alternative-names "example.com" \
--region us-east-1

# DNS 验证(按提示加 CNAME)

ACM 自动续期。CloudFront 必须用 us-east-1 区域的证书

5. ALB(应用负载均衡)

5.1 创建

aws elbv2 create-load-balancer \
--name prod-alb \
--subnets subnet-aaa subnet-bbb \
--security-groups sg-xxx \
--type application

跨 AZ 高可用。

5.2 Target Group

后端 EC2 / Container:

aws elbv2 create-target-group \
--name app-tg \
--protocol HTTP --port 8080 \
--vpc-id vpc-xxx \
--health-check-path /health \
--health-check-interval-seconds 30 \
--healthy-threshold-count 2 \
--unhealthy-threshold-count 3

5.3 Listener 与规则

HTTPS:443 → 默认 → forward 到 app-tg

路径规则:
/api/* → forward 到 api-tg
/admin/* → forward 到 admin-tg
Host = old.example.com → redirect 301

6. EC2 部署

# 启动实例
aws ec2 run-instances \
--image-id ami-xxx \
--instance-type t3.medium \
--key-name my-key \
--subnet-id subnet-aaa \
--security-group-ids sg-xxx \
--user-data file://cloud-init.sh

cloud-init.sh

#!/bin/bash
apt update
apt install -y nginx nodejs npm
# 部署应用...

7. ECS / Fargate

容器化部署,比 EC2 更现代:

  • ECS EC2 模式:跑在 EC2 上
  • ECS Fargate:无服务器,按 vCPU/内存计费
# task-definition.json
{
"family": "frontend",
"networkMode": "awsvpc",
"containerDefinitions": [{
"name": "web",
"image": "ghcr.io/myorg/frontend:v1.0.0",
"portMappings": [{ "containerPort": 80 }],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/frontend",
"awslogs-region": "us-east-1"
}
}
}],
"cpu": "512",
"memory": "1024"
}

8. Route 53

8.1 ALIAS 记录

# 指向 CloudFront
aws route53 change-resource-record-sets --hosted-zone-id ZONE_ID --change-batch '{
"Changes": [{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "app.example.com",
"Type": "A",
"AliasTarget": {
"HostedZoneId": "Z2FDTNDATAQYW2",
"DNSName": "d111111abcdef8.cloudfront.net",
"EvaluateTargetHealth": false
}
}
}]
}'

ALIAS 是 AWS 专有,类似 CNAME 但根域可用且免费。

8.2 Health Check

定期探测后端,故障时 DNS 切到备份:

aws route53 create-health-check --health-check-config '{
"Type": "HTTPS",
"ResourcePath": "/health",
"FullyQualifiedDomainName": "app.example.com",
"Port": 443,
"RequestInterval": 30
}'

9. 成本控制

  • CloudFront Price Class(地区受限版本便宜)
  • S3 Lifecycle:旧文件转 IA / Glacier
  • EC2 reserved instance(包年省 50%+)
  • ALB 按小时 + LCU 计费,闲置删
  • Lambda / Fargate 按需付费
  • 设置 budget 告警

10. 常见反模式

  • S3 公开读 + 暴露 bucket URL:不走 CloudFront 缓存
  • CloudFront 证书没在 us-east-1:用不了
  • ALB 无 health check:流量发到挂的实例
  • 没设 CloudFront 失效策略:每次发版要等 24h 才生效
  • S3 没开版本控制:误删无法恢复
  • 没限制 IAM 权限:实例被入侵 = AWS 账户沦陷
  • 跨 region 流量:账单飙升
  • 不监控账单:突发费用月底才发现

11. 延伸阅读