AWS网络架构解析

在 AWS 上跑任何应用,都绕不开三个网络问题:服务怎么被用户访问、容器怎么访问外部 API、数据库怎么不暴露到公网。回答这三个问题需要理解一组组件:路由表、IGW、NAT Gateway、安全组、VPC Endpoint。本文按机制原理逐层拆开,不堆 API 字段、只回答 “ 为什么这样实现 “。

1. VPC 与 Region/AZ 关系

先把地基铺平:VPC 是 Region 内的一张虚拟网络,可以横跨同 Region 内多个 AZ,但不能跨 Region。AZ(Availability Zone)是同 Region 内物理隔离的机房,毫秒级延迟互通。生产环境跨 AZ 部署是高可用的最低门槛——任一 AZ 整体故障时,其它 AZ 还能扛住流量。

VPC 不是物理交换机,而是 AWS 基于 SDN 实现的一套虚拟地址系统:用户在控制台看到的 10.0.1.5 只是一条逻辑记录,真实包在 AWS 物理网络上转发时会被加一层封装,宿主机之间靠一张全局映射表寻址。这层抽象决定了一件事:VPC 主 CIDR 一旦创建就不能改——它是映射表的主索引,改主索引等于重建全表。要扩容只能挂辅助 CIDR。

因此规划阶段切 CIDR 一定要留足余地,详见 §12。

1.1 VPC 内部互通

同一 VPC 里两台 EC2 互相 ping,宿主机查映射表拿到对端物理位置后封装转发,对用户视角的 10.0.0.0/16 完全透明,不走二层广播。

1.2 关键边界

维度VPC 不是什么VPC 是什么
物理实体不是一台虚拟交换机SDN 控制平面里的一条租户记录
跨 Region不能仅在 Region 内可跨 AZ
主 CIDR不能改只能追加辅助 CIDR

配额(us-west-2,2026-04 快照):每账户每 Region 默认 5 个 VPC、每 VPC 默认 200 个子网、每路由表默认 50 条手动路由、每 SG 默认 60 入 + 60 出且 SG×规则 ≤ 1,000。多数瓶颈出在子网数和路由条目上。

2. 路由表:流量导航的唯一裁判

“ 这个子网是公有还是私有?” 唯一可靠的判定是:子网关联的路由表里,0.0.0.0/0 指向哪里。指 IGW 即公有,指 NAT GW 即私有,不存在这条规则即隔离子网。子网的名字、Tag、CIDR 段都是给人看的;路由表才是给数据包看的。

2.1 最长前缀匹配

路由表匹配规则只有一条——最长前缀匹配,越具体优先级越高,与下发顺序、AZ 编号都无关。同时存在 10.0.1.0/2410.0.0.0/160.0.0.0/0 三条规则时,去 10.0.1.5 走 /24,去 10.0.2.5 走 /16,去外网才落到 /0 默认路由。AWS 路由表没有 “ 自定义优先级 “ 字段,工程师能控制的只有 “ 前缀写多细 “。

每张路由表自带一条不可删除的 local 路由——目标是 VPC 主 CIDR、下一跳为 local,覆盖整个 VPC 内部互通。每个 VPC 有且只有一张主路由表(Main Route Table),未做显式关联的子网默认套用它。生产实践强烈建议每个子网都做显式关联,主表只留作 fallback;否则新建子网会沉默继承到主表的出口,是 AWS 网络事故里出现频次最高的几个根因之一。

2.2 三种子网形态

flowchart LR
    PUB[公有子网]:::pub --> RT1[路由表A<br/>0.0.0.0/0 → IGW]:::rt --> IGW((IGW)):::gw
    PRI[私有子网]:::pri --> RT2[路由表B<br/>0.0.0.0/0 → NAT GW]:::rt --> NAT((NAT GW)):::warn
    ISO[隔离子网]:::iso --> RT3[路由表C<br/>仅 local]:::rt
    classDef pub fill:#10B981,stroke:#10B981,color:#fff
    classDef pri fill:#3B82F6,stroke:#3B82F6,color:#fff
    classDef iso fill:#EF4444,stroke:#EF4444,color:#fff
    classDef rt fill:#fff,stroke:#3B82F6,color:#3B82F6
    classDef gw fill:#10B981,stroke:#10B981,color:#fff
    classDef warn fill:#F59E0B,stroke:#F59E0B,color:#fff
看到这条规则子网类型典型用途
0.0.0.0/0 → igw-xxx公有子网ALB、NAT GW、堡垒机
0.0.0.0/0 → nat-xxx私有子网应用层 EC2/ECS、Lambda VPC
local 一条隔离子网RDS、ElastiCache、内网中间件

2.3 QA

Q:判断子网公有还是私有,最可靠的方式?

A:看其关联路由表中 0.0.0.0/0 的下一跳——指 IGW 即公有,指 NAT GW 即私有,都没有就是隔离子网。

3. IGW 与公有 IP 的真相

“ 挂了 IGW 怎么还连不上网?” 是 AWS 工单频率最高的一类提问。误区是把 IGW 当 “ 上网开关 “。事实:IGW 不会给任何资源分配公有 IP,只负责把已经持有公有 IP 的包转出去。

资源真正能上网需要两个必要条件:① 子网路由表的 0.0.0.0/0 指向 IGW;② 实例的 ENI 上已经绑了公有 IP(自动分配、启动时勾选、绑定弹性 IP 三选一)。两者缺一不可。

3.1 1:1 静态 NAT,无状态

IGW 的实现是 1:1 静态 NAT:每张持有公有 IPv4 的 ENI,在 IGW 内部都对应一条静态映射 私有 IP ↔ 公有 IP,出站时改源地址,入站时改目的地址。这条映射的关键属性是无状态——IGW 不维护连接表,因此无连接表上限,水平能力随 AWS 骨干带宽线性扩展。这是它和 §4 NAT Gateway 的本质区别。

公有 IPv4 来源只有三种:子网开启 “Auto-assign public IPv4”、启动 EC2 时手动勾选、显式绑定弹性 IP(EIP)。前两种 IP 随实例停止释放,只有 EIP 能跨生命周期保留。

flowchart LR
    EC2[EC2 ENI<br/>私有 10.0.1.5<br/>公有 54.1.2.3]:::user --> RT[路由表<br/>0.0.0.0/0 → IGW]:::rt
    RT --> IGW{IGW<br/>1:1 静态 NAT<br/>无状态}:::gw
    IGW --> NET((Internet)):::net
    classDef user fill:#10B981,stroke:#10B981,color:#fff
    classDef rt fill:#fff,stroke:#3B82F6,color:#3B82F6
    classDef gw fill:#3B82F6,stroke:#3B82F6,color:#fff
    classDef net fill:#F59E0B,stroke:#F59E0B,color:#fff

3.2 必踩的 4 种组合

路由 0.0.0.0/0 → IGWENI 有公有 IP能否上网
✅ 有✅ 有✅ 通
✅ 有❌ 无❌ 出站包无公有源地址,IGW 直接丢
❌ 无✅ 有❌ 路由表没出口,包走不到 IGW
❌ 无❌ 无❌ 隔离子网

3.3 公有 IPv4 收费(重要)

自 2024-02-01 起,AWS 对所有公有 IPv4 收费 $0.005/小时在用与闲置同价(us-west-2,2026-04 快照,行为变更公告)。EIP 申请下来即使没绑任何 ENI,照样按小时计费。ALB / NAT GW / NLB 自带的公有 IP 同样计入这笔账,不因 “AWS 托管 “ 而豁免。

定期审计闲置 EIP:

1
aws ec2 describe-addresses --query 'Addresses[?AssociationId==null]'

4. NAT Gateway

私有子网 ECS 拉镜像偶发超时:SG 放行、路由 0.0.0.0/0 → nat-xxx、NAT GW available、带宽只 2 Gbps,docker pull 却间歇 timeout。问题大概率落在 NAT GW 的端口表上限——IGW 永远不会遇到的瓶颈。

4.1 多对一 PAT,有状态

IGW 是 1:1 静态 NAT,NAT GW 走多对一 NAT(PAT)。把 N 个实例的 (源 IP, 源端口) 重写成 (NAT EIP, 新源端口),回包按一张连接表反向还原。这本账叫 conntrack 表,每个并发连接占一条。NAT GW 自身必须放在公有子网:自身 ENI 走 0.0.0.0/0 → igw-xxx 出网,再把 EIP 替换到包源地址上。

flowchart LR
    A[10.0.2.5:45001]:::pri --> NAT
    B[10.0.2.6:51200]:::pri --> NAT
    C[10.0.2.7:33880]:::pri --> NAT
    NAT[NAT GW<br/>EIP 52.x.x.10]:::gw
    NAT -->|52.x.x.10:30001| OUT((Internet)):::net
    NAT -->|52.x.x.10:30002| OUT
    NAT -->|52.x.x.10:30003| OUT
    classDef pri fill:#10B981,stroke:#10B981,color:#fff
    classDef gw fill:#3B82F6,stroke:#3B82F6,color:#fff
    classDef net fill:#F59E0B,stroke:#F59E0B,color:#fff

4.2 端口耗尽

单 EIP 对同一 (dst IP, dst port, protocol) 组合最多 55,000 并发(us-west-2,2026-04 快照)。批量任务全打到同一镜像仓库 IP+443 极易触顶——超出后新连接静默丢,CloudWatch 指标 ErrorPortAllocation 立即非零,监控这一条即可:

1
2
3
4
aws cloudwatch get-metric-statistics \
--namespace AWS/NATGateway --metric-name ErrorPortAllocation \
--statistics Sum --period 60 \
--start-time 2026-04-26T00:00:00Z --end-time 2026-04-26T01:00:00Z

解法是给 NAT GW 关联多个 EIP(Secondary IPv4),按 EIP 数线性扩展并发。

4.3 跨 AZ 陷阱

NAT GW 按 AZ 部署。私有子网在 AZ-b、NAT GW 只起在 AZ-a,AZ-b 出向流量得先跨 AZ。同 Region 跨 AZ $0.01/GB 单方向,回包同价,双向合计 $0.02/GB(us-west-2,2026-04 快照,AWS Pricing API SKU VJSFUFWPB2TZ7RG3 验证)。

维度同 AZ(每 AZ 各一 NAT GW)跨 AZ(仅 AZ-a 一台)
小时费$0.045/h × N$0.045/h × 1
数据处理费$0.045/GB$0.045/GB
跨 AZ 流量费$0/GB$0.02/GB(双向合计)

3 AZ 共用 1 台表面省小时费,跑量上来跨 AZ 反超——决策点是流量规模,详见 §14。

4.4 QA

Q:NAT Gateway 为什么必须放在公有子网?

A:自身也要出公网做 PAT,ENI 必须走 0.0.0.0/0 → IGW 才能把流量送出去。

Q:3 个 AZ 应该共用 1 个 NAT GW 吗?

A:流量小可共用省小时费;跑量上去后跨 AZ $0.02/GB 反超,应每 AZ 各起一台。

5. VPC Endpoint

-4 算过一笔账:私有子网经 NAT GW 拉一次 S3,要付 $0.045/GB 数据处理费(us-west-2,2026-04 快照)。把这条流量搬到 VPC Endpoint,对 S3/DynamoDB 的账单可以直接归零。但 Endpoint 分两种:Gateway Endpoint 完全免费,Interface Endpoint 按小时和流量收费。差价根因不在商业策略,而在两者实现机制不同。

简化为一句话:Gateway Endpoint 只动路由表,是路由层的把戏;Interface Endpoint 要在子网起 ENI 并劫持 DNS,按 AZ 起、按资源算钱。后者就是 AWS 所说的 PrivateLink。

5.1 两种实现机制

Gateway Endpoint:在子网关联的路由表里塞一条新规则,目标是 AWS 维护的前缀列表(prefix list 是 “ 某服务当前全部公网 IP 段 “ 的动态名单,形如 pl-xxx,对应 com.amazonaws.us-west-2.s3),下一跳指向 endpoint。包到达后由 SDN 控制面直接送进服务后端,不创建任何 ENI、不消耗子网 IP、不跨 AZ、不需私有 DNS。整条路径在 SDN 平面完成,数据面零新增资源——这才是免费的真正原因。代价是产品口径只支持 S3 与 DynamoDB。

Interface Endpoint:在每个目标 AZ 的子网里创建一张 ENI,分配一个 VPC 内部私有 IP;同时启用私有 DNS,由 Route 53 Resolver 把服务公网域名(如 s3.us-west-2.amazonaws.com)的解析结果改写成 ENI 私有 IP。应用代码无需改动、SDK 不必更新,DNS 一查就走私网。覆盖 100+ 服务(ECR、SQS、CloudWatch、KMS、STS、Secrets Manager 等)。每张 ENI 都是真实占用子网 IP 的资源,AWS 因此按小时和流量计费。

flowchart LR
    subgraph G[Gateway 路径 · 免费]
      ECS1[ECS]:::user --> RT1[路由表<br/>pl-xxx → vpce]:::rt --> S3A[(S3)]:::svc
    end
    subgraph I[Interface 路径 · 收费]
      ECS2[ECS]:::user --> DNS[私有 DNS<br/>解析到 ENI]:::dns --> ENI[Endpoint ENI<br/>每 AZ 一张]:::eni --> S3B[(ECR / SQS / KMS)]:::svc
    end
    classDef user fill:#10B981,stroke:#10B981,color:#fff
    classDef rt fill:#fff,stroke:#3B82F6,color:#3B82F6
    classDef dns fill:#F59E0B,stroke:#F59E0B,color:#fff
    classDef eni fill:#3B82F6,stroke:#3B82F6,color:#fff
    classDef svc fill:#EF4444,stroke:#EF4444,color:#fff

5.2 对比与计费

维度Gateway EndpointInterface Endpoint
实现路由表 + 前缀列表子网 ENI + 私有 DNS
支持服务仅 S3 / DynamoDB100+(ECR、SQS、CloudWatch …)
每 AZ 部署不需要,VPC 级需要,每 AZ 一张 ENI
费用免费$0.01/h/AZ + ~$0.01/GB

3 AZ 部署一个 Interface Endpoint 静态成本约 $0.03/h ≈ $21.6/月,对换 NAT GW 的 $0.045/GB 数据处理费,每月跑量超 ~480 GB 即回本(us-west-2,2026-04 快照)。

Interface Endpoint 的反面是 PrivateLink Service。把自家的 NLB 暴露给别人的 VPC 私网访问——服务方发布服务(如 SaaS API、跨账号 RDS Proxy),消费者在自己 VPC 内用 Interface Endpoint 接入,流量全程走 AWS 骨干、不出公网。典型场景:

  • 企业内部跨账号共享中台 API
  • SaaS 厂商把控制面提供给客户 VPC 接入(Snowflake、Datadog 等)
  • B2B 数据集成省去 VPN/公网打通

5.4 QA

Q:为什么 Gateway Endpoint 免费而 Interface Endpoint 要付费?

A:Gateway 只在路由表注入前缀列表,无新增数据面资源;Interface 要在每个 AZ 起 ENI,AWS 按 ENI 小时数与流量计费。

Q:S3 同时配 Gateway 和 Interface Endpoint,流量走哪个?

A:Interface 启用私有 DNS 时走 Interface(DNS 先命中 ENI);想走免费 Gateway 需关掉 Interface 的私有 DNS。

6. 安全组与 NACL

安全组只放行入站 80,服务返回的响应包为什么不需要再写一条出站规则?只配一条规则,包却双向都通——这背后是 ENI 在替每条流偷偷记账。

6.1 Conntrack 让 SG “ 有状态 “

每张 ENI 都挂一份连接跟踪表(conntrack table),按 5 元组 (src IP, src port, dst IP, dst port, protocol) 索引每条活跃流。SG 的 “ 有状态 “ 就落在这里:出去的包一旦匹配出站规则,conntrack 立即为反向流量加一条临时表项;回包到达时直接命中表项放行,根本不会再去查入站规则。

高并发反代型实例(API 网关、爬虫汇聚节点)偶发出现 SG 没改却丢包/RST,多半是 conntrack 表项耗尽。CloudWatch 指标 ConntrackAllowanceExceeded 非零就是实锤,解法是升级实例规格或缩短长连接。

6.2 SG Vs NACL

维度安全组 SG网络 ACL NACL
实现机制conntrack(有状态)无状态,每个包独立判断
作用层级ENI子网
默认行为入站全拒、出站全放入站全放、出站全放
规则类型仅 allowallow + deny
评估顺序全部规则取并集按 rule number 从小到大首匹配
典型用途应用级精细放行子网边界粗粒度黑名单

NACL 何时仍要保留:粗粒度 IP 黑名单、多账号共享 VPC 由网络管理员强制边界、合规审计要求子网层留独立策略。日常应用层精细放行仍交给 SG,NACL 只做兜底。

6.3 QA

Q:安全组的 “ 有状态 “ 到底是什么意思?

A:每张 ENI 维护一份 conntrack 表,按 5 元组记录出站流;回包命中表项直接放行,无需在入站再写规则。

7. VPC 内的 DNS

排错经验:” 网络配置看起来都对、Reachability Analyzer 也判可达,但应用就是连不上 “,相当一部分根因不在三四层,而在 DNS。VPC 里的 DNS 由两个开关 + 两类区域决定,先把它们摸清楚。

7.1 两个 VPC 级开关

  • enableDnsSupport:默认 ON,关掉后 VPC 内部完全没有 DNS 解析。基本不要动。
  • enableDnsHostnames:默认 OFF(旧 VPC)/ ON(控制台新建),决定 EC2 是否自动获得 ip-10-0-1-5.us-west-2.compute.internal 这种 AWS 默认主机名。Interface Endpoint 私有 DNS、RDS 私有 DNS 端点都依赖这个开关——很多 “ 域名解析不到 ENI 私有 IP” 的问题,根因就是这一开关默认关。

7.2 默认解析器:.2 地址

每个 VPC 主 CIDR 的 +2 地址(如 10.0.0.2)是 AWS 内置的 Route 53 Resolver。EC2 默认 DNS 指向它,由它解析三类东西:

  1. AWS 公网域名(含 endpoint 私有 DNS 改写)
  2. *.compute.internal 默认主机名
  3. 关联到 VPC 的 Route 53 Private Hosted Zone

7.3 Private Hosted Zone

自定义内部域名(如 db.internal.acme.com → rds-prod.xxxxx.us-west-2.rds.amazonaws.com)就靠 Private Hosted Zone。新建 Hosted Zone 时勾 “Private”、关联到目标 VPC、添加 A/CNAME 记录即可。VPC 内的实例自动能解析这些域名,VPC 外(或没关联的 VPC)解析不到。

跨 VPC / 混合云解析:用 Route 53 Resolver Endpoint 在 VPC 边界开通 DNS 转发——Inbound 让本地数据中心解析 VPC 内私有域名,Outbound 让 VPC 解析本地 AD 域名。

7.4 QA

Q:Interface Endpoint 创建好了,应用却仍解析到 S3 公网 IP?

A:99% 是 VPC 的 enableDnsHostnames 关着,私有 DNS 改写未生效。

8. ALB / NLB 与目标组

选 LB 看两件事:协议层、源 IP 处理。

8.1 ALB Vs NLB

ALB(Application LB) 工作在 L7,处理 HTTP/HTTPS。每个 AZ 创建一张 ENI 作为入口,反向代理时会修改源 IP——后端 ENI 看到的 src 是 ALB 自己的内网 IP,应用必须从 X-Forwarded-For 头解析真实客户端 IP(链式追加,最右一跳离 ALB 最近)。2023 年起 cross-zone 默认启用且免费。

NLB(Network LB) 工作在 L4(TCP/UDP),保留源 IP——后端直接看到真实客户端 IP,性能也比 ALB 高一档。代价是 cross-zone 默认禁用:流量只在同 AZ 的目标组成员间分发,启用 cross-zone 后跨 AZ 部分按 $0.01/GB 单方向计费(us-west-2,2026-04 快照)。

维度ALBNLB
协议层L7(HTTP/HTTPS)L4(TCP/UDP)
源 IP 处理改写为 LB 内网 IP保留源 IP
Cross-zone 默认ON(2023 起)OFF
Cross-zone 计费免费启用后 $0.01/GB/方向
典型用途网站 / API 网关高性能 TCP / 低延迟

8.2 健康检查:实战 80% 的 “ 不通 “ 根因

“ 应用启起来了,ALB 却返回 502/504”,绝大多数死在健康检查。目标组(Target Group)的 Health Check 配置决定了哪些 task 会被纳入流量分发:

  • 路径:默认 /,业务侧务必提供轻量 /health 端点,避免误命中重业务接口
  • 协议/端口:要与目标实际监听端口一致;ECS task 端口动态时用 traffic-port
  • 阈值HealthyThresholdCount 默认 5、Interval 默认 30s——意味着新 task 上线后最长要 2.5 分钟才进入分发,蓝绿发布时容易误判 “ 切流量后 502”

容易踩的两个坑:

  1. SG 没放行健康检查端口:ALB 的 SG 必须能访问目标组成员端口,且后端实例 SG 必须允许 ALB SG 入站。
  2. 健康端点返回 4xx 也算失败:默认期望 200,自定义 Matcher 接受 200-399

8.3 ALB HTTPS 与 ACM

公网 ALB 暴露 HTTPS 必绑证书。AWS Certificate Manager(ACM)签发的证书完全免费,且自动续期。流程:在 ACM 申请域名证书 → DNS 验证(在 Route 53 一键创建 CNAME)→ ALB Listener 选 443 + ACM 证书 ARN。注意证书必须签发在 ALB 所在 Region。

8.4 QA

Q:ALB 后面的应用怎么拿到真实客户端 IP?

A:从 X-Forwarded-For 头取最右一跳 IP——ALB 反代会把源 IP 改成自己的内网地址。

Q:ALB 健康检查 502,应用日志却没收到请求?

A:先查目标组成员的 SG 入站是否放行 ALB SG + 健康检查端口。

9. ECS Fargate 的 Awsvpc 网络模式

Fargate(以及 ECS EC2 模式开启 awsvpc)的网络模型与 EC2 直觉不同:每个 task 独占一张 ENI,不是和宿主机共享。这条事实带出三个常见踩坑点。

9.1 每 Task 一张 ENI 的含义

  • 每 task 占一个子网 IP:批量任务(数据处理、scheduled task)一启就吃 IP,子网 /24(256 IP)跑 200 个并发就会撞 IP 不足。CIDR 切片要给私有子网留足空间,详见 §12。
  • task 自己的 SG:SG 直接挂在 task 的 ENI 上,不再像 EC2 模式那样 “ 实例 SG 包一切 task”,颗粒度更细。
  • ENI 配额:账号有每 Region ENI 总数配额(默认 5,000),大批量 Fargate 时可能撞顶,可提工单上调。

9.2 公网拉镜像的两条路

Fargate task 默认无公网,需要拉 ECR 镜像 / 访问外部 API 时,路径有二选一:

  1. 走 NAT GW:私有子网路由 0.0.0.0/0 → nat-xxx,最简单但流量都过 NAT 数据处理费
  2. 挂 ECR Interface Endpoint:ECR 是 Interface Endpoint 大头流量,单服务跑量稍大就值得挂 endpoint,详见 §5

实际生产推荐 NAT GW + ECR endpoint 组合:常规出网走 NAT,镜像拉取走 endpoint 省钱。

9.3 QA

Q:Fargate task 启动失败,日志写 “ 子网 IP 不足 “?

A:每 task 占一个 IP,把私有子网换到 /20 或更大,避免 /24 容量上限。

10. 跨 VPC 互通:Peering Vs TGW Vs PrivateLink

业务长大就会撞到跨 VPC 互通——不同环境(dev/prod)、不同账号(business unit)、不同 Region(多活)。AWS 给了三套工具,选错要么贵要么慢。

10.1 三者对比

VPC Peering:两 VPC 间的点对点直连,无中间设备、无额外计费(仅跨 AZ/Region 流量费)。最便宜、延迟最低,但拓扑是网状——N 个 VPC 全互通要 N(N-1)/2 条 peering,路由表要在每个 VPC 手动维护。CIDR 不能重叠是硬约束。

Transit Gateway(TGW):星型 hub,所有 VPC 接到同一个 TGW、路由集中决策。把网状复杂度从 N² 降到 N,并能同时接 VPN、Direct Connect 把混合云收口。代价是付费组件——按附件小时费 + 数据处理费收。

PrivateLink:通过 NLB + Interface Endpoint 暴露具体服务,不打通整个网段。安全性最高(消费方只能访问发布的服务、看不到对端 VPC 其它资源),但只能做单向服务消费,不适合双向互通。

10.2 选型决策

场景推荐理由
2-3 个 VPC 简单互通Peering便宜,复杂度可控
≥4 VPC 或跨账号TGW网状管理成本压不住
接 VPN / Direct ConnectTGW自带混合云接入
只让对方访问某个 APIPrivateLink最小权限、不打通网段
跨 Region 互联TGW Inter-Region Peering经 AWS 骨干,更稳

10.3 QA

Q:VPC Peering 能传递吗(A↔B、B↔C,A 能访问 C 吗)?

A:不能。Peering 不传递路由,A→C 必须额外建 A↔C peering,这正是 N² 复杂度的来源,也是 TGW 的卖点。

11. SSM Session Manager 替代 Bastion

Bastion Host 是公有子网最常见的角色,但 2026 年还在配它就落伍了。一台带公网 IP、22 端口对外的跳板机,多一个被扫的入口,多一份 SSH key 分发与轮换负担,还要自己拼 syslog 做命令审计;EIP 和常驻 EC2 也在月底账单上一直走表。SSM Session Manager 把这些问题一次抹平。

11.1 反向连接机制

EC2 上的 SSM Agent(Amazon Linux 2/2023、Ubuntu 官方 AMI 默认预装)启动后主动建立到 SSM 服务的 outbound HTTPS 长连接,挂在那里等指令。控制台或 CLI 发起 session 时,指令顺着这条已建立的反向通道下发,全程不走 SSH 协议,22 端口可以彻底关掉。

正因为是反向连接,EC2 既不需要公网 IP、也不需要在 SG 里开任何入站端口。前提只有两条:

  1. EC2 绑定的 IAM Role 含 AmazonSSMManagedInstanceCore policy
  2. 实例所在子网能访问 SSM endpoint:要么走 NAT GW 出公网,要么挂 ssm / ssmmessages / ec2messages 三个 Interface VPC Endpoint(私有子网纯内网方案)

任缺一条,session 都连不上。

11.2 Bastion Vs SSM 对比

维度Bastion HostSSM Session Manager
暴露面公网 IP + 22 端口对外无公网 IP、零入站端口
SG 入站要求允许办公网/VPN 段 22 入站完全不需要入站规则
操作便利维护 SSH key、跳板登录两跳一条 CLI 直达,无需 key
审计能力自建 syslog/auditd原生接 CloudWatch Logs / S3
费用一台常驻 EC2 + EIPsession 本身免费

实战命令一条够用:

1
aws ssm start-session --target i-0a1b2c3d4e

11.3 QA

Q:SSM Session Manager 为什么不需要给 EC2 分公有 IP?

A:反向连接——SSM Agent 主动 outbound 到 SSM 服务,指令走这条已建立的通道下发。

12. 三层架构 + CIDR 模板 + Terraform 骨架

12.1 CIDR 切分模板

主 CIDR 取 10.0.0.0/16(65,536 IP),按 /20 切片每段 4,096 IP。前 9 段填满 “3 AZ × (公有 + 私有 + 数据库)” 三层结构,后 7 段保留扩展。

1
2
3
4
5
10.0.0.0/16  (65,536 IPs)
├── AZ-a 10.0.0.0/20 公有 | 10.0.16.0/20 私有 | 10.0.32.0/20 数据库
├── AZ-b 10.0.48.0/20 公有 | 10.0.64.0/20 私有 | 10.0.80.0/20 数据库
├── AZ-c 10.0.96.0/20 公有 | 10.0.112.0/20 私有 | 10.0.128.0/20 数据库
└── 预留 10.0.144.0/20–10.0.240.0/20 (7 段, ≈ 28K IP)

每段 4,096 个 IP 扣掉 AWS 保留的 5 个还剩 4,091 个,足够单 AZ 跑千级容器编排。预留段后续可整段挪给 EKS Pod 子网、TGW 附加。

12.2 三层架构

flowchart TB
    NET((Internet)):::net --> IGW{IGW}:::gw
    IGW --> ALB[ALB / 公有]:::pub
    ALB --> ECSa[ECS / AZ-a 私有]:::pri
    ALB --> ECSb[ECS / AZ-b 私有]:::pri
    ALB --> ECSc[ECS / AZ-c 私有]:::pri
    ECSa --> RDS[(RDS Multi-AZ<br/>主 AZ-a / 备 AZ-b)]:::db
    ECSb --> RDS
    ECSc --> RDS
    classDef net fill:#F59E0B,stroke:#F59E0B,color:#fff
    classDef gw fill:#3B82F6,stroke:#3B82F6,color:#fff
    classDef pub fill:#10B981,stroke:#10B981,color:#fff
    classDef pri fill:#3B82F6,stroke:#3B82F6,color:#fff
    classDef db fill:#EF4444,stroke:#EF4444,color:#fff
组件部署子网理由
ALB公有需要被 IGW 直达
NAT GW公有自身 ENI 需 0.0.0.0/0 → IGW
ECS / Fargate私有默认无公网;走 NAT GW 拉镜像
RDS / ElastiCache数据库隔离子网,无 0.0.0.0/0
VPC Endpoint (S3/ECR)私有Interface 型放私有,Gateway 型挂路由

生产环境每 AZ 各起一台 NAT GW 是高可用底线——AZ-a 整个挂掉时只部署在 AZ-a 的那台直接消失,依赖它的 AZ-b/c 私有子网会跟着断网。预算紧的非生产环境(dev/staging)才考虑 3 AZ 共用一台省小时费。

12.3 Terraform 最小骨架

社区维护的 terraform-aws-modules/vpc 是事实标准,最小可投产配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"

name = "prod-vpc"
cidr = "10.0.0.0/16"
azs = ["us-west-2a", "us-west-2b", "us-west-2c"]

public_subnets = ["10.0.0.0/20", "10.0.48.0/20", "10.0.96.0/20"]
private_subnets = ["10.0.16.0/20", "10.0.64.0/20", "10.0.112.0/20"]
database_subnets = ["10.0.32.0/20", "10.0.80.0/20", "10.0.128.0/20"]

enable_nat_gateway = true
one_nat_gateway_per_az = true # 生产环境每 AZ 一台
enable_dns_hostnames = true # Interface Endpoint 私有 DNS 依赖
enable_dns_support = true
}

# S3 / DynamoDB Gateway Endpoint —— 必配,0 成本
resource "aws_vpc_endpoint" "s3" {
vpc_id = module.vpc.vpc_id
service_name = "com.amazonaws.us-west-2.s3"
vpc_endpoint_type = "Gateway"
route_table_ids = module.vpc.private_route_table_ids
}

12.4 QA

Q:3 个 AZ 应该部署几个 NAT GW?

A:生产环境 3 个,每 AZ 一台;任一 AZ 故障不波及其他 AZ 的出网。

13. 排错:Flow Logs + Reachability Analyzer

网络不通时不要靠猜。AWS 提供两个互补工具:Flow Logs 看实际流量,Reachability Analyzer 看路径推断。前者是事后诸葛,记录包真正走没走通;后者是事前分析,纯读配置就能告诉你包会被谁挡。

13.1 两者分工

Flow Logs:粒度可选 ENI / 子网 / VPC 三级,输出去向 S3 / CloudWatch Logs / Kinesis。action 字段只有两个值——ACCEPTREJECT,但不告诉你被哪一层挡(这正是 RA 出场的时机)。

Reachability Analyzer:静态分析路径,读取路由表 + SG + NACL + ENI + TGW / Endpoint 配置,模拟包从源 ENI 到目的 ENI 是否可达,命中阻塞时直接指出 “ 被 SG sg-abc 出站规则拒绝 “ 或 “ 路由表 rtb-xxx0.0.0.0/0“。注意 RA 仅覆盖 L3/L4,不验证 DNS、TLS、应用握手。

13.2 排错决策树

flowchart TD
    S[症状: 应用连不上]:::sym --> Q1{Flow Logs<br/>有包吗?}:::dec
    Q1 -->|无包| F1[查 DNS/应用层<br/>包没出 ENI]:::fix
    Q1 -->|有包| Q2{action 字段}:::dec
    Q2 -->|REJECT| F2[查 SG/NACL<br/>跑 RA 定位规则]:::fix
    Q2 -->|ACCEPT| F3[查路由表/对端 SG<br/>包出去回不来]:::fix
    classDef sym fill:#EF4444,color:#fff,stroke:#B91C1C
    classDef dec fill:#F59E0B,color:#fff,stroke:#B45309
    classDef fix fill:#10B981,color:#fff,stroke:#047857

Reachability Analyzer 三步走:

1
2
3
aws ec2 create-network-insights-path --source eni-aaa --destination eni-bbb --protocol tcp --destination-port 443
aws ec2 start-network-insights-analysis --network-insights-path-id nip-xxx
aws ec2 describe-network-insights-analyses --network-insights-analysis-ids nia-yyy
症状Flow Logs 表现第一步
connection timed out出向 ACCEPT、入向无包查对端 SG / 跨 VPC 路由是否回得来
connection refused双向 ACCEPT不是网络问题——查目标端口监听与应用
完全没日志无记录包没出 ENI——查客户端 DNS、本机路由

实战节奏:先开 ENI 级 Flow Logs 抓 5 分钟样本,落到决策树哪个分支后再用 RA 跑 A→B 验证。两步加起来通常 10 分钟内能出结论。

13.3 QA

Q:Reachability Analyzer 和 Flow Logs 的本质区别?

A:RA 是静态分析配置推断路径,Flow Logs 记录实际流量;前者预演、后者取证。

14. 费用全景与省钱手段

VPC 这层抽象本身不收钱:子网、路由表、IGW、SG、NACL 都是免费控制平面。但 VPC 一旦跑起来,每月账单必然冒出几个 “ 账单刺客 “:第一名 NAT GW(小时费 + 数据处理双重计费),第二名跨 AZ 流量(双向各计一次),第三名公有 IPv4(2024-02 起在用与闲置同价)。

14.1 组件费用总表

组件费用备注
VPC / 子网 / 路由表 / IGW / SG免费控制面
NAT GW 小时费$0.045/h每 AZ 一份独立计费
NAT GW 数据处理$0.045/GB流量经 NAT 必收
Data Transfer Out to Internet$0.09/GB(前 10 TB/月)任何 EC2 出 Internet 的流量都按此计
公有 IPv4$0.005/h在用 / 闲置同价,2024-02 起生效
Gateway Endpoint(S3/DynamoDB)免费必配项
Interface Endpoint$0.01/h/AZ + ~$0.01/GB每 AZ 一张 ENI
跨 AZ 流量$0.01/GB / 方向(双向 $0.02/GB)同 Region 内

费率均为 us-west-2,2026-04 快照。来源:VPC PricingEC2 On-DemandPublic IPv4 公告、AWS Pricing API SKU VJSFUFWPB2TZ7RG3

14.2 典型场景算账(三 AZ 中等流量)

  • NAT GW 小时费:3 × $0.045/h × 720h = $97.20
  • NAT GW 数据处理:100 GB/天 × 30 × $0.045 = $135.00
  • Internet 出口流量:3 TB × $0.09 = $276.48 (NAT GW 处理后还要叠 Internet 出口费)
  • 公有 IPv4:5 个 ALB × $0.005/h × 720h = $18.00
  • 月成本合计 ≈ $526.68

NAT GW 两项 + Internet 出口三项就吃掉 $508.68、占比 96%——刺客名副其实,省钱第一刀必须切在它身上。

14.3 省钱手段

手段节省点适用判断标准
Gateway Endpoint(S3/DynamoDB)NAT GW 数据处理 $0.045/GB → 0必配项,无量级门槛
Interface Endpoint(ECR / CW / KMS 等)NAT GW 流量改走 PrivateLink单服务月跑量 > ~480 GB 即回本
开发环境单 AZ NAT GW节省 2/3 NAT 小时费跨 AZ 流量 < 数十 GB / 月时合算
CloudFront 兜底静态资源Internet 出口费降到 CDN 价大量公网下行流量

排账拆 USAGE_TYPE 维度:

1
2
3
4
5
aws ce get-cost-and-usage \
--time-period Start=2026-04-01,End=2026-04-30 \
--granularity MONTHLY \
--metrics UnblendedCost \
--group-by Type=DIMENSION,Key=USAGE_TYPE

grep nat 找 NAT 费用、grep DataTransfer 找跨 AZ 与出口流量。

14.4 QA

Q:NAT GW 单月账单由哪几部分构成?

A:每 AZ 实例 $0.045/h 小时费 + $0.045/GB 数据处理费;出 Internet 的部分还要叠 EC2 Data Transfer Out($0.09/GB 前 10TB)。

15. 避坑清单

#误区 ❌正解 ✅严重度
1公有子网里的资源自动有公有 IP公有 IP 必须显式分配,子网 “ 自动分配公有 IP” 开关默认关🔴
2子网名字叫 “public” 就是公有子网唯一标准是路由表是否有 0.0.0.0/0 → IGW,名字纯属注释🔴
3有了 IGW 就能上网IGW 只是门,还需路由表指向它 + 资源持公有 IP/EIP🔴
4NAT Gateway 放在私有子网NAT GW 自身必须放公有子网(要 IGW 出口)🔴
5NAT Gateway 一个就够了NAT GW 单 AZ 故障会拖垮其他 AZ 出网,生产应每 AZ 各一台🟡
6所有出站都走 NAT GatewayS3/DynamoDB 走 Gateway Endpoint 免费,其它服务走 Interface Endpoint🟡
7IGW 和 NAT Gateway 可以互相替代IGW 是无状态 1:1 NAT,NAT GW 是有状态 PAT,定位完全相反🟡
8安全组默认拒绝出站安全组默认全放出站,只默认拒入站;与 NACL 双向默认放行不一样🟡
9跨 AZ 流量费可忽略双向 $0.02/GB,量大时比 NAT 处理费还贵🟡
10NAT Gateway 端口取之不尽单 EIP 对同一目标 IP:Port 仅约 55K 端口,监控 ErrorPortAllocation🟡
11Interface Endpoint 建好就能用关闭 “ 启用私有 DNS” 时原服务域名仍解析到公网 IP,流量绕开 Endpoint🟢
12不用的 EIP 放着没事未关联实例的 EIP 仍按 $0.005/h 计费,约 $3.6/月一个🟢
13VPC 内 DNS 默认就好enableDnsHostnames 默认关时 Interface Endpoint 私有 DNS 不生效🟡
14ALB 502 一定是应用挂了多半是健康检查端口未在 SG 放行或 /health 返回非 2xx🟡

参考文档