AWS核心服务实战技巧
新手在 AWS 上最容易踩两类坑:一类是凭证 / 账单失控(root key 泄露、NAT GW 忘关、僵尸 EBS),另一类是架构基础没打稳(公私子网混用、SG 写 CIDR、Multi-AZ 当读写分离用)。这篇把这两类都覆盖:第 0 章先把账户安全和账单看护配齐,1 到 9 章依次过 VPC / ELB / NAT / EC2 / S3 / CloudFront / RDS / 缓存 / 弹性与告警,第 10 章用 30 分钟搭出一套跨 AZ 高可用的 Web 服务,第 11 章交代怎么从手动 CLI 走向 IaC 与容器化。
环境准备:本文示例统一基准 Region 为
us-west-2(俄勒冈),CLI 命令均带--region us-west-2。价格抓取自 AWS 官方页(截至 2026-04),生产决策请以 AWS Pricing Calculator 为准。
0. 入门必做:账户安全与账单看护
第一次开 AWS 账户,先别着急建 EC2。下面四件事不做,后面都白搭:root 凭证一旦泄露整个账号一起没;账单不看着,一个忘关的 NAT GW 一个月就能烧掉 $30。
0.1 根账户与 MFA
注册 AWS 时填的邮箱 + 密码就是 root 用户。它能干掉账号本身、改账单地址、解绑 MFA,权力远超日常工作所需。规则就两条:
- root 立刻开 MFA(控制台右上角用户名 → My Security Credentials → Multi-factor authentication)
- root 永远不创建 access key;日常一律用 IAM 用户
如果之前已经为 root 建过 access key,现在去 IAM 控制台删掉,没有例外。
0.2 IAM 用户、Role、最小权限
IAM(Identity and Access Management,身份与访问管理)的三个常用对象:
- IAM 用户(User):一个真人或一个长期凭证,对应一组 access key
- IAM 角色(Role):可被临时扮演的身份,常给 AWS 服务(如 EC2、Lambda)用
- IAM 策略(Policy):JSON 描述的权限规则,挂到用户或角色上
新手常见错误是图省事给 IAM 用户挂 AdministratorAccess,相当于复制了一份 root。正确做法分两步:
- 给自己建一个 IAM 用户(开 MFA),日常控制台登录用它,不用 root
- 给应用 / EC2 / Lambda 用 Role,不用长期 access key
为什么应用要用 Role?Role 给出来的是 15 分钟到 12 小时滚动失效的临时凭证,泄露窗口短;access key 一旦写进 git 仓库或日志,可以被滥用到你 revoke 为止。
最小权限的实操原则:先给只读策略跑通流程(如 AmazonEC2ReadOnlyAccess),需要写操作时再具体加,不要先开全集再收紧。IAM 服务本身不收费。
0.3 凭证安全:access Key 不进 Git
access key 泄露是 AWS 用户被攻击的头号路径。GitHub 上每分钟都有扫描器在扒公开仓库里的 AKIA 开头字符串。三条底线:
- access key 不写进配置文件、不进 git、不发 Slack
- 本机用
aws configure把 key 存到~/.aws/credentials,加chmod 600 - 怀疑泄露立刻在 IAM 控制台 Deactivate + Delete,再生成新 key
CI / 服务器上跑的脚本,能用 IAM Role(OIDC、EC2 Instance Profile)就不用 access key。
0.4 账单看护:Budgets + Cost Explorer
AWS 不会主动通知你「快花超了」,账单警觉得自己开。两件事一起配:
- AWS Budgets(预算):设置月度阈值,超过 80% / 100% 发邮件。前两个 budget 免费,足够日常用
- AWS Cost Explorer(成本浏览器):可视化看每天每个服务花多少,按 tag 拆分。免费
新建账户后立刻去 Billing → Budgets 建一个月度预算(如 $50),收件人填自己邮箱。再开 Cost Explorer(默认关闭,Billing → Cost Explorer 一键启用)。这两步不到五分钟,能把「账单意外」从大概率事件压到几乎不会发生。
进阶:如果有团队多账户,用 AWS Organizations + Consolidated Billing 把所有子账户账单合并,配合 Cost Allocation Tags(成本分配标签)按项目 / 环境 / 团队分摊;单账户场景不用上这套。
账户安全和账单看护配齐后,下一步开始动结构:先把资源放在地球的哪里、网络边界划在哪两件事定下来。
1. 网络基础:Region / AZ / VPC
在 AWS 上跑应用,先把三个名词分清:Region(区域)、AZ(Availability Zone,可用区)、VPC(Virtual Private Cloud,虚拟私有云)。这三个词决定了你的资源在地球上的哪里、容灾级别多高、网络隔离边界划在哪。
1.1 概念三件套
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#3B82F6', 'primaryTextColor': '#1E3A5F', 'primaryBorderColor': '#2563EB', 'lineColor': '#60A5FA'}}}%%
flowchart TD
subgraph Region ["Region(区域)"]
direction TB
subgraph AZ1 ["可用区 A"]
DC1["数据中心 1"]
DC2["数据中心 2"]
end
subgraph AZ2 ["可用区 B"]
DC3["数据中心 3"]
end
subgraph AZ3 ["可用区 C"]
DC5["数据中心 4"]
end
end
AZ1 <--> |"低延迟 ≤2ms"| AZ2
AZ2 <--> |"低延迟 ≤2ms"| AZ3
classDef region fill:#DBEAFE,stroke:#2563EB,color:#1E3A5F
classDef az fill:#D1FAE5,stroke:#059669,color:#065F46
classDef dc fill:#FEF3C7,stroke:#D97706,color:#92400E
class Region region
class AZ1,AZ2,AZ3 az
class DC1,DC2,DC3,DC5 dc| 概念 | 定义 | 类比 |
|---|---|---|
| Region(区域) | AWS 在全球的物理地理区域(如 us-east-1、ap-northeast-1) | 城市 |
| AZ(可用区) | Region 内物理隔离的数据中心集群,独立电力 / 冷却 / 网络 | 城市内的独立园区 |
| VPC(虚拟私有云) | Region 内逻辑隔离的私有网络,由你掌控 IP / 子网 / 路由 | 园区里你租下的那栋楼 |
一个 Region 通常含 3 个或以上 AZ;同 Region 内 AZ 之间走 AWS 自己的高带宽光纤,往返延迟一般 1 到 2 ms。VPC 是 Region 级资源,一个 VPC 不能跨 Region,但子网可分布在不同 AZ。
1.2 Region 选择策略
按下面四个维度排顺序基本不会错:
| 维度 | 决策建议 |
|---|---|
| 延迟 | 选离用户最近的 Region。中国大陆访问国外服务器,东京 ap-northeast-1 或新加坡 ap-southeast-1 通常优于美西 |
| 合规 | 涉及个人数据要符合当地法规(GDPR、个人信息保护法、HIPAA 等)时,必须选数据落地在合规辖区的 Region |
| 灾备 | 关键业务建议主备分别部署在两个 Region,主区与备区距离不要太近(如 us-east-1 + us-west-2 而非 us-east-1 + us-east-2) |
| 成本 | 同样的 EC2 机型在不同 Region 价差能到 10% 至 30%。us-east-1 通常最便宜,ap-northeast-1 通常最贵 |
实操原则:先满足合规与延迟,再在剩余候选里挑成本最低的。
💰 同机型 m6i.large(按需)月度价格对照(按官方 API 抓取):us-east-1 约 $63、us-west-2 约 $69、ap-northeast-1 约 $86。三地年度成本差能到 30%。
来源:AWS EC2 On-Demand Pricing
1.3 多可用区架构与跨 AZ 流量费
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#3B82F6'}}}%%
flowchart TB
subgraph VPC ["VPC: my-vpc (10.0.0.0/16)"]
subgraph AZA ["us-west-2a"]
PubA["public-subnet-a 10.0.1.0/24"]
PriA["private-subnet-a 10.0.2.0/24"]
end
subgraph AZB ["us-west-2b"]
PubB["public-subnet-b 10.0.3.0/24"]
PriB["private-subnet-b 10.0.4.0/24"]
end
end
PubA --> |"ELB, NAT GW"| PriA
PubB --> |"ELB 节点"| PriB
PriA --> |"EC2, RDS主"| PriB
PriB --> |"EC2, RDS备"| PriA
classDef pub fill:#DBEAFE,stroke:#2563EB
classDef pri fill:#FEE2E2,stroke:#DC2626
class PubA,PubB pub
class PriA,PriB pri💰 跨 AZ 流量:us-west-2 内同 Region 跨 AZ 流量 $0.01/GB,发送方和接收方各按出方向计一次费,所以一次 1 GB 的跨 AZ 调用,账单上是 $0.02。
来源:AWS EC2 Pricing API JSON (us-west-2)
AZ 间延迟 1 到 2 ms,对绝大多数应用可忽略。跨 AZ 部署是性价比最高的高可用方案,单 AZ 故障不会拖垮服务。但要警惕大流量服务的跨 AZ 账单:EC2 与 RDS 主备频繁同步、应用层与缓存层不在同一 AZ,月底账单可能比想象的多一截。
1.4 VPC 子网三分法
把 VPC 内的子网按互联网可达性分成三类,是几乎所有生产架构的默认起手式:
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#3B82F6'}}}%%
flowchart LR
Internet((Internet))
subgraph VPC ["VPC 10.0.0.0/16"]
direction TB
subgraph Pub ["公有子网 Public"]
ALB["ALB / NAT GW / 堡垒机"]
end
subgraph Pri ["私有子网 Private"]
APP["EC2 / ECS 应用层"]
end
subgraph Iso ["隔离子网 Isolated"]
DB["RDS / ElastiCache 数据层"]
end
end
Internet <--> |"IGW"| Pub
Pub --> |"NAT GW"| Pri
Pri --> Iso
classDef pub fill:#DBEAFE,stroke:#2563EB,color:#1E3A5F
classDef pri fill:#FEF3C7,stroke:#D97706,color:#92400E
classDef iso fill:#FEE2E2,stroke:#DC2626,color:#7F1D1D
class Pub,ALB pub
class Pri,APP pri
class Iso,DB iso- 公有子网(Public):路由表含
0.0.0.0/0 → IGW,子网内资源可双向访问公网。放对外暴露的组件:ALB、NAT Gateway、堡垒机 - 私有子网(Private):路由表含
0.0.0.0/0 → NAT GW,能访问公网(拉镜像、调外部 API),但公网无法主动连入。放业务应用层:EC2、ECS、Lambda 的 VPC ENI - 隔离子网(Isolated):路由表无
0.0.0.0/0默认路由,与公网完全断开。放数据层:RDS、ElastiCache、自建数据库
为什么这么分?最小爆破半径加安全分层。万一应用层被攻陷,攻击者也无法从私有子网直接 SSH 出去外联 C2 服务器;万一应用层 SSRF 被利用,隔离子网的数据库也连不上外网,无法把数据偷偷传出去。每多一层路由隔离,就多一道兜底防线。
1.5 路由表与 IGW
理清两个组件的关系就够了:
- IGW(Internet Gateway,互联网网关):VPC 边界的「互联网门」,挂在 VPC 上,本身没有带宽限制也不收费
- 路由表(Route Table):每个子网必须关联一个路由表;表里有
0.0.0.0/0 → igw-xxx的子网就是公有子网
判断一个子网是公有还是私有,只看它关联的路由表里 0.0.0.0/0 指向哪里,不看子网的名字。
1.6 安全组:实例级白名单
VPC 里有两层防火墙:Security Group(安全组,作用在实例网卡)和 Network ACL(NACL,作用在子网)。新手 99% 时间只用 SG 就够:SG 之间可以互相引用(如 ALB-SG 作为 EC2-SG 的 source),表达力强且有状态省心。NACL 通常只在阻挡某段恶意 IP 或合规要求子网级强制隔离时用,其他时候保持默认全开。
理解了网络隔离边界,下一步看流量怎么进入 VPC:ALB 与 HTTPS 终结。
2. 入站流量:ELB 与 HTTPS
ELB(Elastic Load Balancing,弹性负载均衡)是 AWS 应用入口的事实标准。它把外部流量分发给后端 EC2、容器或 Lambda,承担 HTTPS 终止、健康检查、跨 AZ 容灾。
2.1 三种 ELB 选型
| 类型 | OSI 层 | 协议 | 典型场景 | 何时不选 |
|---|---|---|---|---|
| ALB(Application Load Balancer) | L7 | HTTP / HTTPS / gRPC | Web 应用、微服务路径 / Host 路由、WebSocket、Lambda target | 极致低延迟、TCP 直通、需要静态入口 IP |
| NLB(Network Load Balancer) | L4 | TCP / UDP / TLS | 高并发长连接、游戏、DB 代理、需要静态 IP(每 AZ 一个 EIP)、TLS 透传 | 需要 HTTP 路由 / Host / Path |
| CLB(Classic Load Balancer) | L4 / L7 | HTTP / TCP | 仅老系统兼容 | 新项目一律不选 |
实操原则:99% 的新项目从 ALB 起手;只有当应用是纯 TCP/UDP 或要求静态入口 IP 时才考虑 NLB;CLB 是历史遗留,新项目不要碰。
💰 ALB 计费:$0.0225/h + $0.008/LCU-h。LCU(Load Balancer Capacity Unit)按 4 维度取最高维计费:每秒新建连接 25、活动连接 3,000、处理流量 1 GB/h、规则评估 1,000/s。一个轻量 Web 应用通常每月 $20 到 $30 起步。
来源:AWS ELB Pricing
2.2 ELB → Target Group → Targets 三层关系
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#3B82F6'}}}%%
flowchart LR
User["用户请求"] --> ALB["ALB"]
ALB --> |"/api/*"| TG1["API Target Group"]
ALB --> |"/web/*"| TG2["Web Target Group"]
TG1 --> EC2A["EC2-API-1"]
TG1 --> EC2B["EC2-API-2"]
TG2 --> EC2C["EC2-Web-1"]
TG2 --> EC2D["EC2-Web-2"]
classDef alb fill:#3B82F6,stroke:#2563EB,color:#fff
classDef tg fill:#10B981,stroke:#059669,color:#fff
classDef ec2 fill:#F59E0B,stroke:#D97706,color:#fff
class ALB alb
class TG1,TG2 tg
class EC2A,EC2B,EC2C,EC2D ec2ALB 不直连 EC2,而是通过 Target Group(目标组)解耦。一个 ALB 可按路径或 Host 把流量分给不同 Target Group;同一个 Target Group 也可同时挂在多个 ALB 上。Target Group 内部按健康检查筛选可用 target,再按算法(轮询 / 最少未完成请求)分发流量。这层解耦让蓝绿发布、按路径拆服务、共享后端实例都很自然:只换 Target Group 成员,不动 ALB。
2.3 健康检查关键决策
path指向轻量、不触发副作用的端点(如/healthz、/readiness),不要用/,首页可能很重或带统计副作用matcher默认 200,业务有 302 / 204 等正常响应时记得放宽到200-299interval × unhealthy_threshold ≈ 故障摘除时间。30 s × 2 = 60 s 是合理起步;过短会被瞬时抖动误摘,过长则故障实例久久无法剔除- 负载均衡算法:轮询(默认)或最少未完成请求;后者更适合后端处理时长差异大的场景
2.4 创建 ALB
1 | # 前置:已有 VPC、跨 AZ 公有子网、ALB 安全组、Target Group |
监听器要点:80 端口默认 action 用 redirect → HTTPS:443(HTTP_301 永久重定向)而不是 forward,避免用户敲 http:// 时拿到不安全连接。
2.5 HTTPS 与 ACM 证书
最常见的模式:浏览器到 ALB 走 HTTPS(TLS 1.3),ALB 在边界处终止 TLS,转给后端 EC2 走 HTTP。理由:
- 证书集中在 ALB 管理,无需在每台 EC2 配置和续签
- TLS 解密耗 CPU,由 ALB 集中处理,后端 EC2 节省算力
- VPC 内部网络已是受信环境,HTTP 足够
ACM(AWS Certificate Manager,证书管理器)申请要点:
- 在 us-west-2(与 ALB 同 Region)申请。ACM 证书是 Region 级资源,跨 Region 不可用。例外:CloudFront 必须用 us-east-1,详见第 6 章
- 推荐 DNS 验证(自动续订)而非邮箱验证(每年要手动确认)
- 公有证书对接 ALB / CloudFront / API Gateway 等 AWS 服务完全免费
2.6 SG 引用而非 CIDR
新手常见做法:把 EC2 SG 入站 80 端口的 source 设为 0.0.0.0/0,让 ALB 来连。这意味着任何人只要拿到 EC2 公网 IP 就能直接连后端,绕过了 ALB:健康检查、HTTPS、WAF 全部失效。
正确做法是把 EC2 SG 入站 source 设为 ALB 的 SG。SG 互引用 AWS 原生支持:
1 | # ALB SG |
效果:即使 EC2 有公网 IP,外部也无法绕过 ALB 直连。这是 VPC 内部「零信任」模式的最小落地。
入站流量被 ALB 收齐后,反方向问题接踵而来:私有子网里的应用怎么对外发起请求?
3. 出站流量:NAT 与 VPC Endpoint
私有子网里的 EC2 想拉镜像、调外部 API、装系统包,需要一条到公网的出口,但又不能让公网直接连进来。AWS 给了三条路:NAT Gateway、NAT Instance、VPC Endpoint。
3.1 三条路怎么选
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#3B82F6'}}}%%
flowchart LR
EC2["私有子网 EC2"]
NATGW["NAT Gateway<br/>(公有子网)"]
VPCE["VPC Endpoint"]
IGW["Internet Gateway"]
Backbone["AWS 内部骨干网"]
Internet((Internet))
AWSSvc["S3 / DynamoDB<br/>SQS / KMS 等"]
EC2 --> |"路径 1: 任意公网"| NATGW
EC2 --> |"路径 2: AWS 服务"| VPCE
NATGW --> IGW
IGW --> Internet
VPCE --> Backbone
Backbone --> AWSSvc
classDef ec2 fill:#FEF3C7,stroke:#D97706,color:#92400E
classDef gw fill:#DBEAFE,stroke:#2563EB,color:#1E3A5F
classDef ok fill:#D1FAE5,stroke:#059669,color:#065F46
class EC2 ec2
class NATGW,IGW,Backbone gw
class VPCE,AWSSvc ok- 想访问任意公网(GitHub、外部 API、包管理器仓库):生产用 NAT Gateway,AWS 全托管。NAT Instance 是自建 EC2 当 NAT 用,看似省钱但单点故障 + 自维护成本远超那点节省,新项目不要碰
- 只想访问特定 AWS 服务(S3、DynamoDB、SQS、KMS、Secrets Manager):用 VPC Endpoint,省钱且延迟低,流量不出 AWS 骨干网
3.2 NAT Gateway 计费
NAT GW 是出站流量的「按表收费的水龙头」:小时费 + 数据处理费。
💰 NAT Gateway:按小时 $0.045 + 按数据处理 $0.045/GB(us-west-2)。一个 100 GB/天流量的服务每月账单约 $32.4(小时费)+ $135(数据处理)= $167。
来源:AWS VPC Pricing
注意:NAT GW 的数据处理费叠加在出向公网流量费之上。EC2 到互联网 1 GB,账单上是 $0.045(NAT 处理)+ $0.09(互联网出向)= $0.135/GB。这是新手最容易忽略的「双重收费」。
💰 互联网出方向流量(叠加在 NAT 数据处理费之上):us-west-2 出向公网前 10 TB $0.09/GB,next 40 TB $0.085/GB。每月有 100 GB 免费额度(聚合所有 AWS 服务和 Region)。
来源:AWS Data Transfer Pricing API
3.3 VPC Endpoint:S3 / DynamoDB 走 Gateway 省钱
VPC Endpoint 让你直接走 AWS 内部骨干网访问 AWS 服务,不经过 NAT GW 和互联网。分两类:
| 类型 | 支持服务 | 计费 |
|---|---|---|
| Gateway Endpoint | 仅 S3、DynamoDB | 免费 |
| Interface Endpoint(PrivateLink) | 大部分 AWS 服务(SQS / SNS / KMS / Secrets Manager / ECR / Lambda 等) | 按小时(每 AZ 一个 ENI)+ 数据处理 $0.01/GB |
举一个常见省钱场景:应用频繁向 S3 上传日志,月流量 1 TB。
| 方案 | NAT GW 数据处理 | 互联网出向 | Gateway Endpoint | 月成本(仅流量) |
|---|---|---|---|---|
| 走 NAT GW | 1024 × $0.045 = $46 | 1024 × $0.09 = $92 | — | $138 |
| 走 Gateway Endpoint | — | — | 免费 | $0 |
仅靠一个免费 Gateway Endpoint,每月省 $138。实战要点:在路由表里给 S3 / DynamoDB 加一条目标为 vpce-xxx 的路由,应用代码无需改动,SDK 走默认 endpoint 即可被路由命中。Interface Endpoint 别忘了勾「启用私有 DNS」,否则 SDK 仍解析到公共域名,命中默认路由走 NAT GW。
💡 进阶 / 容灾:NAT Gateway 在单 AZ 内自动冗余,但单 AZ 故障时该 AZ 内私有子网会失去出网能力。生产建议每个 AZ 部署一个独立 NAT GW,对应 AZ 的私有子网路由表指向本 AZ 的 NAT GW。这样既消除跨 AZ 故障传播,又避免 NAT GW 处理跨 AZ 流量产生额外的 $0.01/GB。代价是 NAT GW 数量翻倍,3 AZ 部署的小时费基线就从 $32.4 涨到 $97.2/月。
网络通了,接着把跑应用的「机器」放进私有子网里。
4. 计算:EC2 与存储
EC2(Elastic Compute Cloud,弹性计算云)是 AWS 上跑应用的根基。这一章只讲 80% 场景必备的部分:选机型、Launch Template、IMDSv2、user-data、Session Manager、EBS 扩容。
4.1 实例族速查
| 族系 | 类型 | 典型场景 | 代表机型 |
|---|---|---|---|
| T(Burstable) | 突发型 | 低流量 Web、开发测试、CI Runner | t3.medium、t4g.medium |
| M(General) | 通用型 | Web 应用、微服务、中等数据库 | m6i.large、m7g.large |
| C(Compute) | 计算优化 | 视频编码、批量计算、HPC | c7g.large、c7i.large |
| R(Memory) | 内存优化 | 内存数据库、缓存、Spark | r6i.large、r7g.large |
带 g 后缀的是 ARM(Graviton),性价比比 Intel / AMD 同级别高 20% 至 40%,绝大多数 Linux 应用可无痛迁移。GPU、超大内存、本地 SSD 等专用族系新手用不到,需要时再查文档。
💰 EC2 实例按需价(us-west-2 Linux):t3.medium $0.0416/h(约 $30/月)、m6i.large $0.0960/h(约 $69/月)、c7g.large $0.0725/h(约 $52/月)、r6i.large $0.1260/h(约 $91/月)。
来源:AWS EC2 On-Demand Pricing API
实操原则:先按内存 / CPU 比例选族系(默认起手 M 族),再按性价比选代际(新代际优先 Graviton)。机型不必一步到位,跑稳几周后用 CloudWatch 看实际利用率再调整。
4.2 AMI 与 Launch Template
AMI(Amazon Machine Image)= 操作系统 + 预装软件 + 启动配置的快照。Launch Template(启动模板)= AMI + 实例类型 + SG + IAM Role + user-data 等所有启动参数的封装,是 Auto Scaling Group(第 9 章)的前置基础。
为什么不直接「Launch Instance」?Launch Template 可版本化(v1 → v2 → vN),方便回滚;ASG 必须基于 Launch Template 才能批量起实例;团队协作时一份模板共享,避免每人手动凑参数。
1 | # 前置:已有 AMI ID、SG、IAM Instance Profile |
ASG 引用 Launch Template 时如果绑死具体版本号,更新模板后新实例还是旧版。改成 Version=$Latest 让 ASG 自动跟随最新版。
4.3 IMDSv2:把 SSRF 攻击堵死
IMDS(Instance Metadata Service,实例元数据服务)让 EC2 实例可以访问 http://169.254.169.254/ 拿到自己的元数据,包括临时 IAM 凭证。这意味着任何能在实例上发起 HTTP 请求的代码都能拿到凭证,典型威胁就是 SSRF(Server-Side Request Forgery,服务端请求伪造)。
Capital One 2019 年那次 1.06 亿用户数据泄露就是这条链:WAF 规则配错 → 攻击者发起 SSRF → 访问 IMDS 拿到 EC2 凭证 → 用这把钥匙读 S3。
IMDSv2 引入会话 token:调用方先 PUT 一个请求拿 token,再带 token GET 元数据。绝大多数 SSRF payload 只能发 GET,无法构造 PUT,从根上断了路径。
1 | # 强制实例只允许 IMDSv2 |
hop-limit 1 防止容器(多一跳)拿到元数据;如果跑 ECS / EKS,按官方文档设为 2。新建实例通过 Launch Template 默认强制 IMDSv2 是最佳实践(4.2 节示例已含)。
4.4 user-data:开机自动化
user-data 是 EC2 第一次启动时自动执行的脚本(root 权限),用来装软件、拉应用、写配置:
1 |
|
把这段脚本放进 Launch Template 的 UserData 字段(base64 编码),新起实例自动执行。配合 ASG,30 秒内一台新机器就能加入服务。注意:user-data 默认只在首次启动执行,后续重启不会再跑。
4.5 Session Manager:不开 22 端口的远程登录
传统 SSH 模式的痛点:必须给实例开 22 端口入站、管理 SSH key 分发、堡垒机维护成本。Session Manager(AWS Systems Manager 的功能)让你无需开任何端口就能登录实例。前置:实例附带 AmazonSSMManagedInstanceCore 策略,且 SSM Agent 在跑(Amazon Linux 2 起默认安装)。
1 | aws ssm start-session --target i-0123456789abcdef0 --region us-west-2 |
工作原理:实例上的 SSM Agent 主动出站连到 SSM 服务(走 443),形成长连接,CLI 通过 SSM API 把会话流量隧道过去。安全收益是 EC2 SG 完全不开 22 端口、不用管理 SSH key、所有会话被 CloudTrail 记录、可以基于 IAM 策略授权「只能登录某些 tag 的实例」。
4.6 EBS 扩容三步走
EBS 扩容是新手最常踩的「操作分两层」问题:先在 AWS 控制面把卷扩大,再在 OS 内部把分区和文件系统扩大。
1 | # Step 1: AWS 控制面扩卷 |
只做 Step 1 不做 Step 2/3 的后果:df -h 看到磁盘还是原来大小,AWS 已经在多收费。
EBS 类型 99% 选 gp3,比 gp2 便宜约 20%,IOPS 和 Throughput 可独立加量,不用「为了 IOPS 多买容量」。OLTP 数据库受 IOPS 制约(小事务多),视频处理 / 日志归档受 Throughput 制约(大文件少),gp3 两边都能调。
💰 EBS gp3:$0.08/GB-月 + $0.005/IOPS- 月(超出 3,000)+ $0.06/MB·s- 月(超出 125)。
来源:AWS EBS Pricing
4.7 EC2 Vs ECS Fargate Vs Lambda
文章一路讲 EC2 + ASG,但 2026 年的「新项目起手」早已不是单一选项。简单的判断:
| 工作负载 | 选 |
|---|---|
| 长跑 Web 服务,团队懂 Linux 运维,需要自定义内核 / GPU | EC2 + ASG |
| 容器化应用,不想管 OS 和补丁,按容器粒度计费 | ECS Fargate(推荐起手) |
| 事件驱动、按调用计费、毫秒级冷启动可接受 | Lambda |
新项目如果只是跑普通 Web / API,强烈建议 ECS Fargate。它比 EC2 + ASG 少了 OS 维护、AMI 更新、user-data 调试。这篇为了讲清楚网络和弹性的基础原理选了 EC2 路径,理解之后迁移到 Fargate 大概率更省心。
💡 进阶 / 长期省钱:On-Demand 是默认按小时按量付费,最贵;想长期省钱有两条路。Reserved Instances(预留实例):承诺 1 年或 3 年用某机型,省 30% 至 60%,但绑定机型;Savings Plans(储蓄计划):承诺每小时付 $X 用任意 EC2 / Fargate / Lambda,更灵活,省 27% 至 66%。起步建议:跑稳 3 个月、机型相对固定的工作负载,买 1 年期 Compute Savings Plan,立省 1/3 账单。
计算节点的本地盘只装系统和短期数据;用户上传、日志、备份这些「不能丢、要长留」的东西归到对象存储。
5. 对象存储:S3 进阶
S3(Simple Storage Service)几乎每个 AWS 账户都开过一个 bucket。但「会用 S3」和「用好 S3」差距很大,存储类、生命周期、桶策略、签名 URL 每一项都有讲究。
5.1 6 种存储类决策
| 存储类 | $/GB-月(us-west-2 首阶梯) | 最小存储期 | 取回延迟 | 典型场景 |
|---|---|---|---|---|
| Standard | $0.023 | — | ms 级 | 热数据:网站静态资源、应用上传文件 |
| Standard-IA(低频访问) | $0.0125 | 30 天 | ms 级 | 月级访问:备份、日志归档 |
| One Zone-IA | $0.01 | 30 天 | ms 级 | 可重生的冷数据 |
| Glacier Instant Retrieval | $0.004 | 90 天 | ms 级 | 季度访问:医疗影像、新闻档案 |
| Glacier Flexible Retrieval | $0.0036 | 90 天 | 分钟到小时 | 备份归档:年访问几次 |
| Glacier Deep Archive | $0.00099 | 180 天 | 12 小时 | 合规归档:7 到 10 年留存 |
💰 S3 存储类:从 Standard 到 Glacier Deep Archive 价差最高 23 倍。1 TB 数据从 Standard 转到 Deep Archive,月省约 $22。
来源:AWS S3 Pricing API
实操原则:写完后 30 天内会再访问的留 Standard;写完后多半不会再读的转 Standard-IA;仅合规留存的转 Glacier Flexible 或 Deep Archive。用生命周期规则自动转储,不要手动搬。
5.2 Cp Vs Sync
1 | aws s3 sync s3://bucket-name/path/ . --region us-west-2 # 下载整个目录 |
| 命令 | 行为 | 适用场景 |
|---|---|---|
aws s3 cp | 无条件复制所有文件,直接覆盖 | 单文件传输 |
aws s3 sync | 仅复制新增 / 更新的文件,配合 --delete 删除目标多余文件 | 目录同步、增量备份 |
新手最常踩:用 aws s3 cp 覆盖整个目录,把 100 MB 文件每次都重传一遍,浪费时间和钱。同步类操作一律 sync。
5.3 生命周期规则
让 S3 按对象年龄自动转储 / 删除,是省钱主力工具。一份典型 JSON(30 天转 IA、90 天转 Glacier、365 天删除):
1 | { |
1 | aws s3api put-bucket-lifecycle-configuration \ |
关键决策:IA 类对小文件不划算,按最少 128 KB 计费,1 KB 文件存 IA 反而比 Standard 贵;Glacier 类有最小存储期,转入后不到期就删仍按最小期付费;复杂业务可用 Intelligent-Tiering 自动按访问模式分层。
5.4 桶策略 Vs IAM 策略 Vs ACL
| 工具 | 作用对象 | 适合场景 | 推荐度 |
|---|---|---|---|
| IAM 策略 | IAM 用户 / 角色 | 「我的应用能否读这个 bucket」,权限挂在主体上 | 默认首选 |
| 桶策略(Bucket Policy) | 桶本身 | 「这个 bucket 能被谁访问」,跨账户访问、CloudFront OAC、公开静态站点 | 跨边界场景必用 |
| ACL(Access Control List) | 桶或对象 | 历史遗留 | 几乎不要用 |
实操:账户内部访问全用 IAM 策略;跨账户、对接 AWS 服务(CloudFront、Lambda)用桶策略;ACL 在创建桶时直接选「Bucket owner enforced」禁用即可。
5.5 签名 URL:临时下发上传 / 下载凭证
签名 URL(Presigned URL)= 一段带签名的临时链接,任何人拿到就能访问对应对象,不需要 AWS 凭证。常见用途:让前端直传文件到 S3,不经过你的服务器中转。
1 | // 上传签名 URL(Go SDK v2) |
安全要点:时效尽量短(上传链接 ≤ 15 分钟、下载链接 ≤ 5 分钟);不要把签名 URL 写日志;私密文件下载建议每次访问重新签发而非缓存。
5.6 私有桶 + CloudFront OAC
让桶完全 Block all public access,但允许 CloudFront 通过 OAC(Origin Access Control,源访问控制)访问:
1 | { |
OAC 是 OAI(旧版 Origin Access Identity)的替代品,2022 年起推荐使用。用 OAC 后桶可以彻底关闭公网访问,CloudFront 边缘节点用 SigV4 签名访问 S3,Condition 限定来源 distribution 防止其他 CloudFront 分发借桥。
💡 进阶 / 安全:开启桶版本控制(Versioning)后,每次覆盖或删除对象都保留旧版本,可恢复误操作。配合 MFA Delete(要求删除版本时通过 MFA 二次验证),即使 IAM 凭证泄露,攻击者也无法永久删除数据。代价是旧版本占存储空间,需配生命周期规则自动清理 N 天前的旧版本。
S3 把对象稳稳存下来,但用户从地球另一端取一张图仍要走半个地球——这正是 CDN 解决的问题。
6. 内容分发:CloudFront
CloudFront 是 AWS 的 CDN,把静态资源缓存到全球 600+ 边缘节点。用户从最近节点拿内容,既把首字节时间压到几十毫秒,也大幅降低源站出向带宽费。
6.1 工作原理
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#3B82F6'}}}%%
flowchart LR
User["用户浏览器"] -->|"请求"| Edge["最近的 CloudFront<br/>边缘节点"]
Edge -->|"缓存命中"| User
Edge -.->|"缓存未命中"| Origin["源站<br/>(S3 / ALB / 自定义)"]
Origin -.->|"返回内容"| Edge
Edge -.->|"缓存 + 返回"| User
classDef user fill:#FEF3C7,stroke:#D97706,color:#92400E
classDef edge fill:#3B82F6,stroke:#2563EB,color:#fff
classDef origin fill:#10B981,stroke:#059669,color:#fff
class User user
class Edge edge
class Origin originDNS 把 CDN 域名解析到离用户最近的边缘节点。命中时直接返回,未命中才回源拉取并顺带缓存到本节点。典型静态站点接入后缓存命中率通常 80% 至 95%,源站只扛 5% 至 20% 的请求。
6.2 缓存策略三件套
CloudFront 的缓存键由三件套 Policy 共同决定,是命中率的关键:
| Policy | 作用 | 关键字段 |
|---|---|---|
| Cache Policy | 决定缓存键 + TTL(缓存有效期) | 是否包含 Query String、Header、Cookie;min/max/default TTL |
| Origin Request Policy | 决定哪些信息转发到源站(不影响缓存键) | Header、Query String、Cookie |
| Response Headers Policy | 给响应加 / 改 Header | CORS、HSTS、Cache-Control 等 |
默认起手:Cache Policy 选 AWS 托管的 Managed-CachingOptimized(不带 Cookie / Query String,TTL 24 h),Origin Request Policy 默认即可,Response Headers Policy 加一个 SecurityHeadersPolicy。
误区是把 Cache Policy 配成「转发所有 Cookie / All Headers」。缓存键会随每个用户的 sessionid / UA 爆炸膨胀,命中率骤降到接近 0,CloudFront 等于白开。Cookie / Header 转发只在确需个性化的资源(如登录后页面)开启,并用单独的 Cache Behavior 限定到特定路径。
6.3 ACM 证书必须在 Us-east-1
CloudFront 是全球服务:分发配置由 AWS 全球控制面统一管理,控制面物理实例就在 us-east-1。证书要被全球边缘节点统一拉取使用,必须放在控制面所在的 ACM Region。其它 Region 的 ACM 证书 CloudFront 根本看不到。
对比:ALB 是 Region 级资源,证书必须与 ALB 同 Region。新手最容易混的两条路:
- 应用域名(指向 ALB) → 证书在 ALB 所在 Region(如 us-west-2)
- CDN 域名(指向 CloudFront) → 证书必须在 us-east-1
生产实践通常是同一个域名在 us-east-1 与 ALB 所在 Region 各申一张,DNS 验证共用同一组 CNAME 记录。
6.4 缓存失效
更新源站资源后,需要强制让 CloudFront 重新回源拉取:
1 | # CloudFront 命令统一带 --region us-east-1 |
💰 CloudFront 失效:每月前 1,000 路径免费,超出后 $0.005/路径。频繁全量失效(
/*)只算 1 个路径,但会让全球缓存命中率瞬间归零、源站压力暴涨。
来源:AWS CloudFront Pricing
💰 CloudFront 流量:北美 / 欧洲 edge 出向每月前 1 TB 永久免费,超出后约 $0.085/GB。HTTPS 请求每月前 1,000 万次免费。
来源:AWS CloudFront Pricing
最佳实践:版本化文件名替代失效。把 app.css 改成 app.v1.2.3.css,加版本号即新文件,永远不需要失效;CI/CD 构建时自动注入 hash(如 app.[contenthash].css),从根上免去失效操作。
静态资源走完了「就近加速」的路径,接下来的难题在动态数据:怎么把数据库托管起来、又不丢可用性。
7. 关系数据库:RDS
RDS(Relational Database Service)是 AWS 托管的关系数据库。你只管 schema、SQL、索引;AWS 负责打补丁、备份、监控、主备切换这些「机房 DBA」的活。
7.1 引擎选择
| 引擎 | 兼容性 | 性能 | 存储扩展 | 起步成本 |
|---|---|---|---|---|
| RDS MySQL | 原生 MySQL,社区生态最广 | 中等 | 手动加卷 | db.t3.medium 单 AZ $0.068/h |
| RDS PostgreSQL | 原生 PostgreSQL,复杂查询、JSONB、地理空间 | 中等 | 手动加卷 | 同量级 |
| Aurora MySQL/PG | 兼容 MySQL/PG | 高(约 RDS 3 至 5 倍) | 自动扩到 128 TB | 比同规格 RDS 略高 |
💰 RDS MySQL(us-west-2):db.t3.medium 单 AZ $0.068/h(约 $49/月)、Multi-AZ $0.136/h;db.m6i.large 单 AZ $0.171/h(约 $123/月)。备份存储超出免费额度部分 $0.095/GB- 月。
来源:AWS RDS Pricing API
实操:个人 / 小项目用 RDS MySQL 或 PostgreSQL 起 t3 类;中大型生产关心 P99 延迟和读写分离用 Aurora。
7.2 创建数据库实例
1 | # 前置:已有 VPC、隔离子网、SG、Secrets Manager 中存好密码 |
要点:选隔离子网(无 0.0.0.0/0);SG 入站只放 EC2 / 应用 SG 作 source(不开 CIDR);--multi-az 立即开同步副本;--backup-retention-period 7 自动备份保留 7 天(最长 35)。
7.3 参数组:修改 max_connections
RDS 实例的参数(max_connections、innodb_buffer_pool_size)通过参数组修改,不能直接 SET GLOBAL。
1 | # Step 1 创建自定义参数组 |
参数分 dynamic(修改即生效)和 static(必须重启):max_connections 是 dynamic、innodb_log_file_size 是 static。
7.4 备份机制
| 类型 | 触发 | 保留期 | 恢复粒度 |
|---|---|---|---|
| 自动备份 | 每天一次完整备份 + 持续事务日志 | 1 至 35 天(实例删除后默认清除) | PITR(时间点恢复)到任意秒 |
| 手动快照 | 用户主动触发 | 永久(直到手动删除) | 仅快照那一刻 |
1 | aws rds restore-db-instance-to-point-in-time \ |
删除实例时默认会一并清掉自动备份。想保留得提前手动 snapshot。快照只包含数据,参数组关联和 SG 关联是实例级配置不在快照里,恢复后立即重新关联。
7.5 Multi-AZ 不是读写分离
新手最常混淆这两个概念,它们解决的问题完全不同:
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#3B82F6'}}}%%
flowchart LR
subgraph MultiAZ ["Multi-AZ:高可用"]
AppA["应用"] --> Primary["主库 (AZ-a)<br/>读写"]
Primary -.->|"同步复制"| Standby["备库 (AZ-b)<br/>不可读"]
end
subgraph ReadReplica ["只读副本:读写分离"]
AppB["应用"] -->|"写"| Master["主库"]
AppB -->|"读"| RR1["只读副本 1"]
AppB -->|"读"| RR2["只读副本 2"]
Master -.->|"异步复制"| RR1
Master -.->|"异步复制"| RR2
end
classDef primary fill:#3B82F6,stroke:#2563EB,color:#fff
classDef standby fill:#FEE2E2,stroke:#DC2626,color:#7F1D1D
classDef rr fill:#10B981,stroke:#059669,color:#fff
classDef app fill:#FEF3C7,stroke:#D97706,color:#92400E
class Primary,Master primary
class Standby standby
class RR1,RR2 rr
class AppA,AppB app| 维度 | Multi-AZ | 只读副本(Read Replica) |
|---|---|---|
| 复制方式 | 同步(强一致) | 异步(秒级延迟) |
| 备库可读 | 不可读(仅待命) | 可读(专门用来读) |
| 故障切换 | 自动 60 至 120 秒 | 手动提升为主库 |
| 解决的问题 | 高可用 | 读写分离、降低主库压力 |
典型生产架构:Multi-AZ + 多个只读副本,同时拿到高可用 + 读扩展。
7.6 应用层容错配套
Multi-AZ 自动切换 60 至 120 秒期间,应用拿到的是 connection refused 或读超时。如果应用层没重试,用户照样看到 5xx。三件事一起配:
- 连接池配
connection timeout≤ 5 秒、max retries≥ 3,指数退避 - 写操作幂等设计(用幂等 key 或唯一约束),切换中重试不会重复扣款 / 重复下单
- 健康检查端点
/readiness真探一次 DB(如SELECT 1),DB 不可达就返回 503,让 ALB 把流量切到其他实例
不做这套配套,Multi-AZ 给你的是「数据不丢」,但不是「用户无感」。
7.7 Performance Insights 与用户管理
Performance Insights 是 RDS 内置的性能分析工具:Top SQL 按等待时间排名当前最耗资源的 SQL;等待事件展示 CPU、IO、锁各维度时间分布;保留期免费 7 天,扩展到 2 年另收费。新手用法是控制台 RDS → 实例 → Performance Insights,鼠标点点就能定位「哪条 SQL 占了 60% CPU」。
用户管理建议按读 / 写 / 管理分至少 3 套账号,master 账号只用来建库建用户,应用一律用业务账号:
1 | -- 读写 |
密码放 Secrets Manager 而非配置文件,应用启动时通过 SDK 拉密码(带缓存)。Secrets Manager 可配置每 30 天自动轮换:调用 Lambda 函数生成新密码 → 更新到 RDS → 更新到 Secret,应用层无感。
数据库扛得住事务但抗不住并发热点;缓存层把读请求挡在 DB 之前。
8. 缓存:ElastiCache
缓存层把热点数据从 DB 抬到内存,挡掉 80% 的读。AWS 自家用 ElastiCache 覆盖这块,支持 Redis(含 Valkey 这个开源 fork)和 Memcached。
8.1 三种形态
| 形态 | 自动扩缩 | 数据分片 | 适用 |
|---|---|---|---|
| Serverless | 自动 | 自动 | 不想管节点;流量波动大 |
| Cluster Mode Disabled | 手动 | 单分片 + 副本 | 小数据集、需 Redis 全部命令 |
| Cluster Mode Enabled | 手动 | 多分片(slot 分布) | 大数据集、高吞吐;客户端必须 cluster-aware |
💰 ElastiCache:Serverless 按 ECPU $0.0023/百万次(Valkey/Redis OSS)+ 数据存储 $0.084/GB·h;节点形态按实例小时费 + 备份存储 $0.085/GiB- 月。
来源:AWS ElastiCache Pricing
8.2 Redis Vs Memcached
| 维度 | Redis | Memcached |
|---|---|---|
| 数据结构 | 丰富(String/List/Hash/Set/Sorted Set/Stream/Geo) | 仅 String |
| 持久化 | RDB / AOF 可选 | 无 |
| 主从复制 | 原生支持 | 无 |
| 集群 | Cluster Mode | 客户端分片 |
| 典型用途 | 会话、计数器、排行榜、消息队列、限流 | 纯读缓存(缓存 SQL 结果、HTML 片段) |
99% 新项目选 Redis。AWS 推荐用 Valkey(Redis 7.x 的开源 fork,与 Redis OSS 协议兼容,价格更低)。
1 | # Serverless 创建:前置已有 VPC、隔离子网、SG(开 6379 端口入站只放应用 SG) |
💡 进阶 / 成本:缓存层主要成本是内存。省钱思路:给所有 key 设合理的 TTL(如
SETEX user:123 600 ...)让自然过期不占内存;配置内存淘汰策略maxmemory-policy allkeys-lru在达到内存上限时自动淘汰最少使用的 key;大对象(> 1 MB)尽量序列化压缩或拆小存。忘了 TTL,1 个月内存涨到爆,被迫升级实例规格,比一开始就配 TTL 贵几倍。
存储和缓存就位后,剩下两件事决定能不能扛住流量:实例数量随负载自动伸缩、异常发生时第一时间被看到。
9. 弹性伸缩与可观测性
固定数量 EC2 撑不起波动的流量。Auto Scaling Group(ASG)让实例数量随指标自动伸缩;CloudWatch 把日志、指标、告警串起来,让你在用户工单到来之前就看到异常。这两件事放一章讲,因为 ASG 离不开 CloudWatch 指标驱动。
9.1 ASG 三件套
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#3B82F6'}}}%%
flowchart LR
LT["Launch Template<br/>(AMI + 实例类型 + SG + IAM Role + user-data)"]
ASG["Auto Scaling Group<br/>(min/desired/max + 子网 + 健康检查)"]
SP["Scaling Policy<br/>(目标追踪 / 步进 / 计划)"]
EC2["EC2 实例 × N"]
LT --> ASG
SP --> ASG
ASG -->|"按需起/停"| EC2
classDef lt fill:#FEF3C7,stroke:#D97706,color:#92400E
classDef asg fill:#3B82F6,stroke:#2563EB,color:#fff
classDef sp fill:#10B981,stroke:#059669,color:#fff
classDef ec2 fill:#FEE2E2,stroke:#DC2626,color:#7F1D1D
class LT lt
class ASG asg
class SP sp
class EC2 ec2- Launch Template 是「实例长什么样」的模板(详见 4.2)
- ASG 是「我要 N 台实例分布在哪些子网」的容器:min(最少)/ desired(期望)/ max(最多)
- Scaling Policy 是「什么时候改 desired」的规则
ASG 自动维持 desired 数量的健康实例:有实例挂了自动起新的,触发扩容时自动起更多。新起的实例自动注册到指定 Target Group,缩容时自动注销。ASG 本身不收费,只为底层 EC2 实例付费。
9.2 扩缩策略与健康检查
| 策略 | 触发方式 | 适用 |
|---|---|---|
| Target Tracking(目标追踪) | 维持指标在目标值(如 CPU 平均 50%) | 通用首选 |
| Step Scaling(步进) | 按指标阈值阶梯扩缩 | 需对突发流量分级响应 |
| Scheduled(计划) | 按时间表(每天 9 点扩到 10 台、22 点缩到 2 台) | 已知流量模式 |
99% 项目用 Target Tracking,目标值设 50% 给突增留 buffer,简单稳健。
ASG 判定实例健康的两种方式:EC2 健康检查(默认)只看实例 running 状态,应用进程死了 OS 还活着也判活;ELB 健康检查跟随 ALB Target Group 的 7 层探活,应用挂了即使实例还活着也会被替换。生产强烈建议开 ELB 健康检查。
1 | aws autoscaling update-auto-scaling-group \ |
grace-period 300:实例新起后给应用 5 分钟冷启动时间再开始 ELB 健康检查,避免冷启动期被误判。
9.3 创建 ASG
1 | # 前置:已有 Launch Template、跨 AZ 私有子网、Target Group |
Version=$Latest 让 ASG 自动跟随 Launch Template 最新版本。绑死具体版本号是新手最常见的踩坑:升级模板后新实例还是旧版。
9.4 CloudWatch 三件套
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#3B82F6'}}}%%
flowchart LR
subgraph Sources ["数据源"]
EC2["EC2 / ECS<br/>(CloudWatch Agent)"]
ALB["ALB / RDS<br/>(自动发指标)"]
App["应用代码<br/>(SDK 主动发)"]
end
Sources --> Logs["Logs<br/>(日志组 / 日志流)"]
Sources --> Metrics["Metrics<br/>(数值时序)"]
Metrics --> Alarms["Alarms<br/>(阈值 + 评估周期)"]
Alarms --> SNS["SNS Topic"]
SNS --> Email["邮件"]
SNS --> Slack["Slack / Lambda"]
classDef src fill:#FEF3C7,stroke:#D97706,color:#92400E
classDef store fill:#3B82F6,stroke:#2563EB,color:#fff
classDef alarm fill:#FEE2E2,stroke:#DC2626,color:#7F1D1D
classDef out fill:#10B981,stroke:#059669,color:#fff
class EC2,ALB,App src
class Logs,Metrics store
class Alarms alarm
class SNS,Email,Slack out- Logs 存非结构化或结构化日志,可全文搜索 / SQL 风格查询
- Metrics 存数值时序,自动按 1 分钟 / 5 分钟聚合
- Alarms 监听 Metrics 命中阈值发送 SNS 通知
CloudWatch Logs 三级层级:Log Group(按应用 / 服务划分)→ Log Stream(通常按实例 ID 或 hostname)→ Log Event(具体一条日志)。
9.5 Logs Insights:5 个常用查询
Logs Insights 用类 SQL 语法查日志,覆盖 90% 排查场景:
1 | -- 错误统计(每 5 分钟一个 bucket) |
@timestamp 和 @message 是 CloudWatch 自动注入的字段;其它字段需要日志本身是 JSON 结构化(CloudWatch 自动解析顶层字段)。
9.6 告警链路:Metric → Alarm → SNS → 邮件
1 | # Step 1 创建 SNS Topic |
Slack 通知通过 SNS → Lambda → Slack Webhook 实现,Lambda 用官方模板 1 小时搞定。
💰 CloudWatch:Logs 摄取 $0.50/GB、存储 $0.03/GB- 月;自定义指标前 10,000 个 $0.30/月每个;标准告警 $0.10/告警 - 月。
来源:AWS CloudWatch Pricing
💡 进阶 / 成本:CloudWatch Logs 默认保留期是「Never Expire」,不改的话日志永久存,几个月后存储费可能比摄取费还贵。省钱优先级:每个 Log Group 都设保留期,按 RPO 选 30 天 / 90 天 / 1 年;高频低价值日志(健康检查、心跳)改 sample 或本地丢弃;用 Subscription Filter 转出冷数据到 S3,原 Log Group 设短保留。这 3 步通常能砍掉 50%+ 日志账单。
零散的服务讲到这里,前 9 章的概念该串起来了——下一章用一套可跑的最小架构把它们落地。
10. 实战配方:30 分钟搭建生产 Web 服务
本章独立可读:把前 9 章的概念串成一个能跑起来的最小生产架构。读完跟着做完,你就有了一个跨 AZ 高可用、HTTPS 域名访问、可弹性伸缩、有告警的 Web 服务。
10.0 前置与目标
必备前置:
- AWS 账户已开通,账单告警已配置(参见第 0 章)
- 本机已
aws configure,当前 IAM 凭证拥有 EC2 / VPC / RDS / ELB / Auto Scaling / CloudWatch / Route 53 / ACM 完整权限 - 一个已托管在 Route 53 的域名(或可手动加 CNAME 到第三方 DNS 的域名)
- 本文统一基准 Region:us-west-2
目标架构:
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#3B82F6'}}}%%
flowchart TB
User["用户浏览器"]
R53["Route 53<br/>app.example.com"]
ACM["ACM 证书<br/>(us-west-2)"]
subgraph VPC ["VPC 10.0.0.0/16 — us-west-2"]
subgraph PubA ["公有子网 us-west-2a (10.0.1.0/24)"]
ALBnodeA["ALB 节点 A"]
NATa["NAT GW"]
end
subgraph PubB ["公有子网 us-west-2b (10.0.3.0/24)"]
ALBnodeB["ALB 节点 B"]
end
subgraph PriA ["私有子网 us-west-2a (10.0.2.0/24)"]
EC2a["EC2 (ASG)"]
end
subgraph PriB ["私有子网 us-west-2b (10.0.4.0/24)"]
EC2b["EC2 (ASG)"]
end
subgraph IsoA ["隔离子网 us-west-2a (10.0.5.0/24)"]
RDSa["RDS Primary"]
end
subgraph IsoB ["隔离子网 us-west-2b (10.0.6.0/24)"]
RDSb["RDS Standby"]
end
end
User -->|"DNS 解析"| R53
User -->|"HTTPS"| ALBnodeA
User -->|"HTTPS"| ALBnodeB
ALBnodeA --> EC2a
ALBnodeB --> EC2b
EC2a -.->|"读写"| RDSa
EC2b -.->|"读写"| RDSa
RDSa -.->|"同步"| RDSb
EC2a --> NATa
classDef pub fill:#DBEAFE,stroke:#2563EB
classDef pri fill:#FEF3C7,stroke:#D97706
classDef iso fill:#FEE2E2,stroke:#DC2626
classDef ext fill:#10B981,stroke:#059669,color:#fff
class PubA,PubB,ALBnodeA,ALBnodeB,NATa pub
class PriA,PriB,EC2a,EC2b pri
class IsoA,IsoB,RDSa,RDSb iso
class User,R53,ACM ext最终成品:跨 2 AZ 高可用(任一 AZ 故障不影响服务);HTTPS 域名访问;ASG 弹性伸缩 min=2, max=4;RDS Multi-AZ 自动故障切换;CloudWatch 三个关键告警(5xx / CPU / DB 连接数);月成本约 $200 至 $300(不含域名注册)。
架构思路一句话:流量从 Route 53 进 ALB,ALB 跨 AZ 把请求分到私有子网里的 EC2 集群,EC2 读写隔离子网里的 RDS Multi-AZ。三层各自独立 SG,数据库不暴露任何公网入口。
10.1 步骤 1:VPC + 双 AZ 子网(5 分钟)
公有放需要被公网直连的组件(ALB 节点、NAT GW),私有放走 NAT 出网但不被公网直连的应用(EC2),隔离连 NAT 都没有只接受私有子网内部流量(RDS)。
1 | VPC_ID=$(aws ec2 create-vpc --cidr-block 10.0.0.0/16 --region us-west-2 --query 'Vpc.VpcId' --output text) |
⚠️ 完整 CLI 涉及路由表创建、关联、NAT GW + Elastic IP,命令较长。生产环境强烈建议用 Terraform / CloudFormation 管,参见第 11 章。本节给关键骨架,详见 AWS VPC 官方教程。NAT GW 一台每月固定 $32 + 流量费,是这套架构里仅次于 RDS 的固定成本头号。做实验就建一台跨 AZ 共用,正式生产再考虑每 AZ 一台规避 NAT 单点。
10.2 步骤 2:三件套安全组(3 分钟)
链式引用:Internet:443 → sg-alb → sg-ec2:80 → sg-rds:3306。每一层只放上一层的 SG 作 source,不写 CIDR。
1 | # ALB SG:接公网 443(80 用于 80→443 重定向) |
链式 SG 引用让流量路径单向受控,任何外部 IP 都无法直连 EC2 或 RDS,只能从 ALB 进。这里不要写 CIDR 当 source(如 --cidr 10.0.0.0/16),那样整个 VPC 内任何资源都能连 EC2,等于把内部边界拆了。新手最常见的错配是给 sg-rds 开 0.0.0.0/0:3306,配合公网子网就是把数据库直接挂到公网上,几小时就被扫到。
10.3 步骤 3:RDS Multi-AZ MySQL(8 分钟)
Multi-AZ 在另一 AZ 起一台同步副本(Standby),不对外提供读流量,只用作故障切换。主库挂了或被 AZ 级故障带走时,RDS 在 60 至 120 秒内把 DNS 端点切到副本,应用代码不用改。
1 | # DB Subnet Group 用两个隔离子网 |
10.4 步骤 4:Launch Template + user-data(5 分钟)
1 | cat > /tmp/user-data.sh <<'EOF' |
HttpTokens=required 强制 IMDSv2,把 SSRF 取凭证的链路断掉(参见 4.3)。HttpPutResponseHopLimit=1 防止容器内进程多跳一次拿到元数据;如果在这台 EC2 上跑 Docker / ECS Agent,按官方文档设为 2。user-data 在首次启动自动执行,配合 ASG 弹性伸缩时新机器从无到有上线只要 30 至 60 秒。
10.5 步骤 5:Auto Scaling Group(2 分钟)
1 | aws autoscaling create-auto-scaling-group \ |
health-check-type ELB 让 ASG 用 ALB 的 7 层健康检查替代默认的 EC2 状态检查,应用挂了但实例还活着的「僵尸」也会被踢出并替换。grace-period 300 给 user-data 留 5 分钟跑装包脚本,否则新实例还没起 nginx 就被判定不健康,循环 terminate / launch 烧钱。vpc-zone-identifier 必须填两个 AZ 的私有子网,只填一个 AZ 时那个 AZ 一挂全部容量归零,Multi-AZ RDS 也救不了。
10.6 步骤 6:ALB + Target Group + HTTPS(5 分钟)
ALB 与 EC2 之间用 HTTP 80 而不是 HTTPS。TLS 在 ALB 终结,证书只装一份;EC2 上跑普通 nginx 就行。ALB 与公网之间一律 HTTPS,并把 80 端口做 301 重定向到 443。
1 | TG_ARN=$(aws elbv2 create-target-group --name demo-tg --protocol HTTP --port 80 --vpc-id $VPC_ID \ |
10.7 步骤 7:Route 53 域名 + ACM 证书(2 分钟)
ACM 签发的证书只能给同 Region 的 AWS 服务用,给 us-west-2 的 ALB 装证书证书就必须在 us-west-2 申请。例外是 CloudFront,它要求证书在 us-east-1。本配方不涉及 CloudFront,同 Region 申就对了。
1 | # ACM 证书必须与 ALB 同 Region |
10.8 步骤 8:CloudWatch 告警(3 分钟)
告警不是越多越好,越多越容易被忽略。最小可用三条线打底:入口异常(5xx 突增)、容量异常(CPU 持续高位)、依赖异常(DB 连接数飙高)。
1 | TOPIC_ARN=$(aws sns create-topic --name demo-alarms --region us-west-2 --query 'TopicArn' --output text) |
10.9 验证清单
部署完成「看着都对」不等于真的可用。下面 5 项是最低验证集,专门把架构里「高可用」和「可观测」两个承诺打一遍。逐项确认(任一不通就回到对应步骤排查):
- 浏览器访问
https://app.example.com返回 200,证书绿锁 - 控制台手动 terminate 一台 ASG 实例,2 至 3 分钟内 ASG 自动起新实例补齐
- RDS 控制台触发「Reboot with failover」,应用短暂报错(约 60 至 120 秒)后恢复
aws sns publish --topic-arn $TOPIC_ARN --message test,邮箱能收到(确认订阅已生效)- CloudWatch Logs 控制台能看到应用日志流(如配了 CloudWatch Agent)
10.10 销毁脚本
⚠️ 本节最重要:实验做完一定要销毁。NAT GW + RDS Multi-AZ + ALB 三件套不停就是每天 $5 至 $10 的烧。
按依赖反向顺序销毁(销毁前再确认一次资源名 / VPC ID):
1 | # 1. CloudWatch + SNS |
「能跑」之后还差一步:把这套手工 CLI 换成可重复、可审计的代码,把僵尸资源管起来。
11. 走向生产
10 章配方让你能跑起来,但离「生产可用」还差最后一公里:手动 CLI 不可重复、僵尸资源会偷偷烧钱、容器化路径才是 2026 年的主流起手。这一章交代怎么从「能跑」走到「能交付」。
11.1 IaC:从 CLI 走到 Terraform
10 章的 CLI 脚本是为了让你看懂每个组件做了什么,不是给生产用的。手工命令链有三个问题:环境差异(你本地能跑,同事的机器跑不通)、不可重复(删错一个资源没法 undo)、不可审计(改了什么进了 git 没?)。
生产正解是 IaC(Infrastructure as Code,基础设施即代码):
| 工具 | 语言 | 适用 |
|---|---|---|
| Terraform | HCL | 多云、社区生态最广,强烈推荐起手 |
| AWS CDK | TypeScript / Python / Go | 只用 AWS、想用真编程语言写基础设施 |
| CloudFormation | YAML / JSON | AWS 原生、零依赖;CDK 编译产物也是它 |
10 章那套配方用 Terraform 写大约 200 行,terraform apply 一键起,terraform destroy 一键回收。改资源也是改代码进 PR、code review、自动 plan 出 diff,比 CLI 链条稳得多。新手起步建议直接学 Terraform,把配方先用代码复刻一遍。
11.2 资源回收:找出在偷偷烧钱的东西
大账单 80% 来自被遗忘的资源:忘释放的 Elastic IP、孤立的 EBS 卷、没删的 NAT GW、僵尸 RDS。每月一次扫一遍,能省下肉眼可见的钱。
1 | # 1. 未关联实例的 Elastic IP(每个 $3.6/月空挂) |
逐项核对:还在用就留,不在用就删。设个 cron 每月 1 号跑一次,结果发邮箱。
11.3 Trusted Advisor:免费的成本与安全自检
Trusted Advisor 是 AWS 自带的自动检查工具,免费版覆盖 6 项核心:低利用率 EC2、未关联 EIP、IAM 用户没开 MFA、Security Group 开 0.0.0.0/0、S3 桶公开访问、Service Limits 接近上限。控制台 → Trusted Advisor 一眼看到红黄绿。完整套件(涵盖 100+ 检查项)需要 Business Support 计划。
新建账户后立刻去看一眼 Trusted Advisor,把红色项处理掉。这一步常常能挖出注册时图省事开了的 root key、0.0.0.0/0 的 SG 等明显问题。
11.4 域名注册与 Route 53
10.0 假设你已有 Route 53 托管的域名。如果还没有,新人最快路径:
- AWS 控制台 → Route 53 → Domains → Register Domain,选域名(
.com约 $13/年) - 注册成功 AWS 自动建好一个 Hosted Zone($0.50/月每个),并把 NS 指向它
- 在 Hosted Zone 里加 ALIAS A 记录指向 ALB DNS
域名也可以注册在第三方(Namecheap / Cloudflare),把 NS 改到 Route 53 即可。Hosted Zone 必要原因是:ALIAS A 记录是 Route 53 特有的,能直接指向 ALB / CloudFront 而不收 DNS 查询费,第三方 DNS 只能用 CNAME,根域名 example.com(无前缀)不能 CNAME,必须 ALIAS。
11.5 容器化路径:什么时候离开 EC2 + ASG
把 10 章的 EC2 + ASG 跑稳之后,下一步通常是迁到容器。判断信号:
- 一个团队维护多个微服务,AMI 数量爆炸、Launch Template 难管 → ECS Fargate
- 应用启动 < 5 秒、流量极不规律(白天高夜里几乎为 0) → Lambda
- 用 Kubernetes 已经是公司标准 → EKS
ECS Fargate 是最容易的迁移路径:现有 Dockerfile 直接用,把 EC2 + ASG 换成 ECS Service + Fargate Task,ALB Target Group 改 target type 为 IP,其他几乎不变。Fargate 计费按 vCPU + 内存按秒算,跑稳几周后用 Compute Savings Plan 同样能省 30%+。
正文路径走完。附录把 10 个最高频的踩坑和日常用得最多的 CLI 集中放一起,方便事后回查。
附录
高频踩坑 Top 10
10 章的内容里散落着不少踩坑场景。下面 10 条是新手账户里最高频的,照着排查能解决 80% 的「为什么不通」「为什么这么贵」。
- 私有子网实例
apt update卡死:路由表0.0.0.0/0没指 NAT GW,或 NAT GW 建在了私有子网(NAT GW 必须在公有子网,它自己要走 IGW 出网) - EC2 SG source 写 CIDR 而非 SG,绕过 ALB:把 source 改成 ALB 的 SG ID,让 EC2 只接受 ALB 来的流量
- ACM 证书在 ALB 列表里看不到:证书 Region 错了。ALB 用同 Region 证书,CloudFront 必须用 us-east-1
- EBS 扩卷后
df -h不变:只扩了控制面,没扩 OS。growpart+resize2fs或xfs_growfs三步走 - Multi-AZ 备库当读副本用:备库不可读,只用作故障切换。读写分离用只读副本(Read Replica)
- CloudFront 命中率长期 < 5%:Cache Policy 把 Cookie 全转发了,缓存键随用户爆炸。改用
Managed-CachingOptimized - NAT GW 跨 AZ 流量费暴涨:单一 NAT GW 服务多 AZ,私有子网出网先跨 AZ。每 AZ 独立部署一个 NAT GW
- ASG 用 EC2 健康检查导致僵尸实例:应用挂了但 OS 还在,ASG 不替换。
--health-check-type ELB - Launch Template 改了版本但 ASG 用旧版:版本号绑死。
Version=$Latest让 ASG 自动跟随 - S3 签名 URL 时效设太长被泄露:上传 ≤ 15 分钟、下载 ≤ 5 分钟;前端「下载」动作每次重新请求后端签发
常用 CLI 速查
所有命令前置:已配置 awscli + IAM 权限 + 默认 Region us-west-2。
EC2
1 | # 列出运行中实例 |
S3
1 | aws s3 ls --region us-west-2 |
RDS
1 | # 列实例 |
CloudWatch
1 | # 列告警当前状态 |
ELB
1 | # 列 Load Balancer |
IAM / Secrets Manager
1 | # 看当前调用方身份 |
推荐进阶阅读
- AWS Well-Architected Framework(六大支柱:卓越运营 / 安全 / 可靠性 / 性能 / 成本 / 可持续):官方门户
- AWS 价格计算器:calculator.aws,任何价格疑问的第一站
- AWS 公开定价 API:
https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/<service>/current/<region>/index.json - AWS 中国官网博客:aws.amazon.com/cn/blogs/china/,中文实战案例
- Terraform AWS Provider 文档:registry.terraform.io/providers/hashicorp/aws
价格声明
文中价格抓取自 AWS 官方页(基准 Region us-west-2,抓取日期 2026-04-26),每张价格卡片带「来源」链接。价格随时调整,生产决策请以 AWS Pricing Calculator 实时查询为准。