← back to blog/

从零搭建多区域个人云基础设施

2026-05-11 · 12 min read · AWSCloudflareNginxSRE

TL;DR — 用一个晚上从零搭出来:3 个 AWS 区域 + Cloudflare CDN + 域名 + 个人网站。中间踩了不少坑,包括一次把 SSH 配置弄炸然后用 EBS 卷救援。这是我准备 AWS SAA 时的实战笔记。

动机

作为正在备考 AWS SAA 的 CS 学生,我意识到读 Cantrill 课程和刷 Tutorials Dojo 题,远远比不上真实运维一套基础设施。所以决定用一晚上时间,从零搭一个属于自己的小型云架构 —— 多区域、有 CDN、有域名、有监控。

目标是练手以下 SAA 考点:

架构总览

Internet / DNS
Cloudflare CDN + DNS
隐藏源站 IP · 全球 200+ PoP
🇯🇵
Tokyo
主用
t3.micro
🇦🇺
Melbourne
亚太备用
t3.micro
🇺🇸
Oregon
北美备用
t3.micro

1. EC2 选型

最初我选了 t3.small,因为想留余量。运行一周后看 CloudWatch,CPU 平均 5%,内存 50%。完全过度配置

降级到 t3.micro 后省了 47% 成本( → /月),同时性能完全够用。一个良好的实例选型应该:

负载建议
个人轻量服务t3.micro / t4g.micro
持续中等流量t3.small / t4g.small
计算密集c6i / c7g
网络密集c6gn
💡 教训:right-sizing 不是猜,是看 CloudWatch 指标后调整。SAA 考试里这是 high-frequency 题型。

2. 多区域设计

为什么选这 3 个区域?

区域角色原因
🇯🇵 ap-northeast-1主用亚太低延迟(对中文用户)
🇦🇺 ap-southeast-4本地我人在墨尔本时延迟最低
🇺🇸 us-west-2灾备地理隔离 + 北美定价低

三个区域形成主动-主动-灾备架构。任何一个挂掉,业务可继续。

跨区域延迟实测

ping -c 10 $TOKYO_IP

# 从墨尔本→Tokyo:        ~120ms
# 从墨尔本→Melbourne:    ~3ms
# 从墨尔本→Oregon:       ~180ms

3. 内核优化: BBR

Linux 默认 TCP 拥塞控制是 cubic。对跨太平洋的高延迟、有丢包的链路来说,这不够好。BBR 是 Google 提出的新算法,对差网络鲁棒得多。

echo 'tcp_bbr' | sudo tee /etc/modules-load.d/bbr.conf
echo 'net.core.default_qdisc=fq' | sudo tee -a /etc/sysctl.conf
echo 'net.ipv4.tcp_congestion_control=bbr' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

在 Tokyo 这台机器实测,单连接下载速度从 ~2 Mbps 提升到 ~15 Mbps。免费的速度优化,何乐不为。

⚠️ 坑:BBR 设置完后重启会失效,因为 tcp_bbr 内核模块没自动加载。必须创建 /etc/modules-load.d/bbr.conf 才会持久化。我第一次没加,重启后 BBR 静默失败,花了 20 分钟才发现。

4. Swap 配置 (t3.micro 必备)

t3.micro 只有 1 GB 内存。一次 apt upgrade 就能把它跑满,触发 OOM kill。配 1 GB swap 作为内存的应急气囊:

sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

实测一次启动多个 Docker 容器时,进程没被 OOM 杀掉,性能稍降但服务正常。

5. EBS 卷救援实战

当晚最戏剧性的事故。我尝试用 systemd socket override 给 SSH 加备用端口,结果改错了让 sshd 在握手阶段拒绝所有连接。SSH 整个挂了。

排查链路

救援层级结果
1. SSH 22❌ kex_exchange_identification 拒绝
2. EC2 Instance Connect❌ 走的也是 sshd,同样失败
3. SSM Session Manager❌ 实例无 IAM Role
4. Serial Console + 密码登录❌ 云镜像默认 ubuntu 用户无密码
5. GRUB 单用户模式❌ Ubuntu 26.04 GRUB Timeout=0,菜单不显示
6. EBS 卷救援✅ 成功

救援过程

  1. AWS Console 停掉坏实例
  2. 分离根 EBS 卷
  3. 同一可用区开一台 t3.nano 救援机(注意:EBS 卷不能跨 AZ 挂载)
  4. 把坏卷以 /dev/sdf 挂到救援机
  5. 救援机里:sudo mount /dev/nvme1n1p1 /mnt/broken
  6. 删除导致 sshd 崩溃的配置文件
  7. 卸载、分离
  8. 把卷以 /dev/sda1(root device name)挂回原实例
  9. 启动原实例 → SSH 恢复
  10. 销毁救援机
✅ 学到的:EBS 卷可以离线挂载到任意同 AZ 实例修改 —— 这是 SAA 课程里讲过但容易忽视的灾难恢复手段。真的踩过坑才记得住

事后的预防

这次事故的根本原因是缺乏运维救援通道。现在所有实例都附加了 IAM Role + SSM 权限:

IAM Role: EC2-SSM-Access
Policy:   AmazonSSMManagedInstanceCore

下次 SSH 出问题,可以直接 SSM Session Manager 进去,不用动 EBS 卷

6. Cloudflare CDN 集成

注册了一个域名 zhenyuruan.com(用 Cloudflare Registrar,$10/年无加价)。配 DNS 时关键点:

验证 IP 已隐藏

dig zhenyuruan.com +short
104.21.0.139
172.67.128.15

# 返回的是 Cloudflare IP,不是 AWS Tokyo IP ✅

7. Nginx 部署

Tokyo 上 nginx 配置要点:

server {
    listen 443 ssl;
    http2 on;
    server_name zhenyuruan.com www.zhenyuruan.com;

    ssl_certificate     /etc/nginx/ssl/zhenyuruan.crt;
    ssl_certificate_key /etc/nginx/ssl/zhenyuruan.key;
    ssl_protocols       TLSv1.2 TLSv1.3;

    # Security headers
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header Referrer-Policy strict-origin-when-cross-origin;

    root /var/www/zhenyuruan.com;
    server_tokens off;  # 隐藏 nginx 版本
}

证书目前用自签(因为 Cloudflare SSL 模式是 Full,不验证证书链)。未来升级到 Full (strict) 模式时,会改用 Cloudflare Origin Certificate(15 年有效期,免费)。

8. SSH 加固

SSH 配置:

9. 月成本

资源月费
3 × t3.micro (Tokyo + Melb + Oregon)~$24
3 × Elastic IP$0(attached)
EBS 24 GB~$2.5
域名 zhenyuruan.com$0.83 (摊销)
Cloudflare CDN$0 (免费层)
合计~$27/月

10. 复盘

做对的

做错的 / 学到的

下一步


这一晚学到的 SAA 考点比刷一周题都扎实。如果你也在准备 SAA,建议至少做一遍真实部署 —— 哪怕只跑 t3.micro 一台。理论 + 实战才是完整学习。

© 2026 ZR · ~/zr