AWS US-East-1 宕机生存指南:2026 多区域架构实战

发布: 2026-05-09 • 阅读: 7 分钟 • 标签: AWS, US-East-1, 宕机, 多区域架构, 灾备, CloudFront, RDS, Route53

2026 年 5 月 8 日,AWS US-East-1(北弗吉尼亚) 发生大规模宕机,影响范围包括 Coinbase、FanDuel 等依赖该区域的知名服务。这不是第一次,也不会是最后一次——US-East-1 长期以来都是 AWS 宕机事故的重灾区。

问题在于:为什么这么多团队仍然把全部鸡蛋放在一个篮子里?费用原因?复杂度原因?还是"它应该不会在我头上倒"的侥幸心理?

本文从实战角度出发,手把手搭建一个真正能在 US-East-1 挂掉时继续服务的多区域架构。

📋 你需要的基础

AWS 账号(预算充足)、Terraform 基础操作能力、对 DNS 和网络的基本理解。示例使用 AWS CDK 和 Terraform 混合展示。

1. 为什么 US-East-1 特别容易出问题?

这不是玄学。US-East-1 是 AWS 最老的区域(2006 年上线),承载了海量 legacy 基础设施。根据 AWS 自己的 PES(Provisioned Elasticity System) 文档,老区域的控制平面和数据平面耦合更深,单点故障面更大。

加上大量 SaaS 公司和加密货币平台默认选 us-east-1(延迟最优、服务最全),形成了依赖的单点集中效应——一个区域出事,半个互联网跟着抖。

⚠️ 血泪教训

即使是高可用架构内部的单区域部署(多 AZ),当整个区域的控制平面挂掉时,AZ 间故障转移也救不了你。

2. 分层防御:多区域架构的四个层次

真正的多区域高可用分为四个层次,每层解决不同粒度的故障:

  1. DNS 层 — 流量入口故障转移(R53 + CloudFront)
  2. 计算层 — 多区域应用部署(EKS / ECS 多集群)
  3. 数据层 — 跨区域数据同步(RDS 跨区域副本 + S3 CRR)
  4. 缓存层 — 全局缓存兜底(CloudFront + ElastiCache 全局数据存储)
┌─────────────────────────────────────────────────────┐ │ CloudFront (Global) │ │ Origin Groups + 故障转移 │ ├─────────────────────────────────────────────────────┤ │ Route53 健康检查 + 故障转移策略 │ ├──────────────┬──────────────────┬──────────────────┤ │ us-east-1 │ us-west-2 │ eu-west-1 │ │ (主区域) │ (备区域 1) │ (备区域 2) │ │ ALB │ ALB │ ALB │ │ EKS 集群 │ EKS 集群 │ EKS 集群 │ │ RDS 主库 │ RDS 只读副本 │ RDS 只读副本 │ │ S3 主桶 │ S3 跨区域副本 │ S3 跨区域副本 │ └──────────────┴──────────────────┴──────────────────┘

3. Route53 DNS 故障转移(第一道防线)

多区域架构的入口是 DNS。Route53 的故障转移路由策略配合健康检查,可以在几十秒内切换流量。

核心配置思路:

# Route53 故障转移示例(Terraform)
resource "aws_route53_health_check" "primary" {
  type              = "HTTPS"
  resource_path     = "/health"
  fqdn              = "api-primary.example.com"
  port              = 443
  failure_threshold = 3
  request_interval  = 10  # 每 10 秒检查一次
}
resource "aws_route53_record" "api" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "api.example.com"
  type    = "A"
  set_identifier = "primary"
  failover_routing_policy {
    type = "PRIMARY"
  }
  alias {
    name                   = aws_lb.primary.dns_name
    zone_id                = aws_lb.primary.zone_id
    evaluate_target_health = true
  }
  health_check_id = aws_route53_health_check.primary.id
}
resource "aws_route53_record" "api_secondary" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "api.example.com"
  type    = "A"
  set_identifier = "secondary"
  failover_routing_policy {
    type = "SECONDARY"
  }
  alias {
    name                   = aws_lb.secondary.dns_name
    zone_id                = aws_lb.secondary.zone_id
    evaluate_target_health = true
  }
}
💡 最佳实践

健康检查端点不要只返回 200。要检查数据库连接、缓存连接、下游依赖等。如果数据库已经挂了返回 200,DNS 不会切换,用户遭遇的却是 500。

3.1 更现代化的方案:CloudFront Origin Groups

如果业务适合用 CDN 分发(静态站点、API 通过 CloudFront 代理),CloudFront 的 Origin Groups 是比 R53 故障转移更好的选择:

# CloudFront Origin Group 配置
resource "aws_cloudfront_distribution" "site" {
  origin {
    domain_name = aws_lb.primary.dns_name
    origin_id   = "primary-origin"
    custom_origin_config {
      http_port              = 80
      https_port             = 443
      origin_protocol_policy = "https-only"
      origin_ssl_protocols   = ["TLSv1.2"]
    }
  }
  origin {
    domain_name = aws_lb.secondary.dns_name
    origin_id   = "secondary-origin"
    custom_origin_config {
      http_port              = 80
      https_port             = 443
      origin_protocol_policy = "https-only"
      origin_ssl_protocols   = ["TLSv1.2"]
    }
  }
  origin_group {
    origin_id = "multi-region-group"
    failover_criteria {
      status_codes = [403, 404, 500, 502, 503, 504]
    }
    member {
      origin_id = "primary-origin"
    }
    member {
      origin_id = "secondary-origin"
    }
  }
  default_cache_behavior {
    target_origin_id = "multi-region-group"
    # ... 其他缓存配置
  }
}

CloudFront 的优势在于:故障转移发生在边缘节点级别,客户端 DNS 缓存不成为瓶颈。而且 Origin Group 会在收到 5xx 后的毫秒级切换到备用源站。

4. 多区域 RDS:跨区域灾备

数据层是跨区域架构中最头疼的部分。数据库不能简单地 DNS 切换了事——主库写到一半宕了怎么办?

4.1 方案一:RDS 跨区域只读副本 + 手动提升

最简单的方案:在其他区域创建一个 Cross-Region Read Replica。故障时手动提升为独立主库,修改应用连接串。

# RDS 跨区域只读副本
resource "aws_db_instance" "primary" {
  identifier = "mysql-primary"
  engine     = "mysql"
  # ... 基础配置
  backup_retention_period = 7
}
resource "aws_db_instance" "replica_west" {
  provider = aws.us-west-2
  identifier = "mysql-replica-west"
  replicate_source_db = aws_db_instance.primary.arn
  instance_class      = "db.r6g.xlarge"
  skip_final_snapshot = true
}

局限性:提升操作需要几秒到几分钟。RPO(恢复点目标)取决于复制延迟,通常 < 5 秒。RTO(恢复时间)取决于你发现故障+手动操作的速度。

4.2 方案二:Aurora Global Database

如果用的是 Aurora,Aurora Global Database 是更好的选择:

# Aurora Global Database
resource "aws_rds_global_cluster" "global" {
  global_cluster_identifier = "aurora-global"
  engine                    = "aurora-mysql"
  engine_version            = "8.0.mysql_aurora.3.07"
  storage_encrypted         = true
}
resource "aws_rds_cluster" "primary" {
  provider = aws.us-east-1
  cluster_identifier      = "aurora-primary"
  global_cluster_identifier = aws_rds_global_cluster.global.id
  # ... 其他配置
}
resource "aws_rds_cluster" "secondary" {
  provider = aws.us-west-2
  cluster_identifier      = "aurora-secondary"
  global_cluster_identifier = aws_rds_global_cluster.global.id
  source_region             = "us-east-1"
  # ... 其他配置
}
💡 省钱技巧

灾备区域的 Aurora 副本可以配置为"可读",日常承载读流量和分析查询。不浪费钱。

5. 多区域 EKS:Kubernetes 跨集群部署

如果跑在 EKS 上,多区域意味着多个独立的 EKS 集群。Kubernetes 本身不提供跨集群服务发现,需要自己搭桥。

5.1 用 AWS LB Controller + 外部 DNS 自动注册

核心思路:每个区域的 EKS 集群各自部署服务,通过 AWS Load Balancer Controller 创建 ALB/NLB,然后利用 ExternalDNS 自动注册到 R53 的故障转移记录:

# ExternalDNS 配置
apiVersion: v1
kind: ServiceAccount
metadata:
  name: external-dns
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::xxx:role/external-dns
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: external-dns
spec:
  containers:
  - args:
    - --source=service
    - --source=ingress
    - --domain-filter=example.com
    - --provider=aws
    - --aws-zone-type=public
    - --policy=upsert-only

5.2 跨集群服务发现:AWS Cloud Map

如果不同区域的微服务需要互相调用(比如灾备区域的服务需要读主区域的数据),可以用 AWS Cloud Map 进行跨集群服务发现,配合 App Mesh 做多区域流量路由。

6. S3 跨区域复制 + CloudFront 兜底

S3 的静态资源是最容易做多区域的:

# S3 跨区域复制
resource "aws_s3_bucket" "primary" {
  bucket = "assets-primary"
}
resource "aws_s3_bucket_versioning" "primary" {
  bucket = aws_s3_bucket.primary.id
  versioning_configuration {
    status = "Enabled"
  }
}
resource "aws_s3_bucket_replication_configuration" "cross_region" {
  bucket = aws_s3_bucket.primary.id
  role   = aws_iam_role.replication.arn
  rule {
    status = "Enabled"
    destination {
      bucket = aws_s3_bucket.secondary.arn
    }
  }
}
resource "aws_s3_bucket" "secondary" {
  provider = aws.us-west-2
  bucket   = "assets-secondary"
}

关键点:CloudFront 的 Origin Group 同时配置主区域和灾备区域的 S3 桶作为源站。主区域挂了自动切到灾备区域桶。

7. 测试你的多区域架构

架构搭好了不去测试,等于没搭。强烈建议定期做混沌工程演练:

7.1 AWS Fault Injection Simulator (FIS)

AWS 的 FIS 可以直接注入故障:断开 AZ 连接、停止 EC2 实例、模拟 API 限流等。

# FIS 实验:停止 us-east-1 的应用实例
resource "aws_fis_experiment_template" "stop_primary" {
  description = "Stop primary region instances"
  role_arn    = aws_iam_role.fis_role.arn
  action {
    name      = "stop-instances"
    action_id = "aws:ec2:stop-instances"
    target {
      key   = "Instances"
      value = "primary-instances"
    }
  }
  target {
    name           = "primary-instances"
    resource_type  = "aws:ec2:instance"
    resource_arns  = aws_instance.app_primary[*].arn
    selection_mode = "ALL"
  }
}

7.2 手动模拟

如果你还没有用 FIS(或者觉得它太复杂),工程化的手动测试也有效:

  1. 修改安全组入站规则,拒绝所有流量(模拟区域网络故障)
  2. 停止 RDS 主库(模拟数据库故障)
  3. 缩放应用实例到 0(模拟计算资源耗尽)
  4. 观察 DNS 故障转移时间和客户端恢复情况
⚠️ 测试时机

不要在业务高峰期测试。挑选凌晨流量最小的时候,并准备好回滚方案。如果是主动故障转移,先确认灾备区域确实能接住流量。

8. 成本估算:多区域要花多少钱?

很多团队不做多区域就是因为"太贵"。实际上,热备 + CloudFront + Aurora 全球数据库 的配置在月账单上大约比单区域多 60-100%。但和一次 US-East-1 宕机造成的营收损失比,这个溢价很值。

💡 渐进式投入

• 第一阶段:S3 跨区域复制 + CloudFront Origin Group(成本几乎为零)
• 第二阶段:RDS 跨区域只读副本(灾备区域用小实例节省费用)
• 第三阶段:ECS/EKS 多集群部署(成本最高,建议只在关键服务上做)

总结

US-East-1 宕机不是"如果"的问题,而是"什么时候"的问题。2026 年 5 月的这次事件再次提醒我们:

真正经历了 US-East-1 宕机并存活下来的团队,不是那些用了最多 AWS 服务的团队,而是那些不把所有依赖压在单一区域的团队。

希望你读到这篇文章的时候,你的服务还活着。


文中 Terraform 配置示例基于 v1.10+。实际生产部署请结合具体业务场景和安全合规要求调整。