SiyaR-SSH/gcp-ha-web-tier

GitHub: SiyaR-SSH/gcp-ha-web-tier

该项目演示了如何在 GCP 上通过 gcloud CLI 构建跨多可用区的高可用 Web 层,实现负载均衡与自动故障恢复。

Stars: 0 | Forks: 0

# Google Cloud 上的高可用、负载均衡 Web 层 ## 目标 将 Web 层从单点故障转变为具有弹性的服务。与其使用单个 VM,不如运行一个分布在多个可用区的、由相同服务器组成的**托管实例组** (managed instance group),在其前端放置一个**负载均衡器** (load balancer),并添加一个**健康检查** (health check),以便自动替换不健康的实例。 完成后的环境包含: - 一个定义了可复现 Web 服务器的**实例模板** (instance template) (通过启动脚本运行 nginx) - 一个运行在跨多个可用区的 2 个以上实例的**区域托管实例组 (MIG)** - 一个通过端口 80 监控每个实例的**健康检查** - 一个在健康实例之间分配流量的**全球 HTTP 负载均衡器** - **自我修复**:销毁一个实例,MIG 会自动重建它 - 用于管理访问的 **基于 IAP 的 SSH** —— 无需在任何地方硬编码家庭 IP ## 架构 ``` Internet | +-----------v------------+ | Global HTTP Load | single public IP | Balancer | (forwarding rule → proxy → URL map) +-----------+------------+ | +-----------v------------+ | Backend Service | + Health Check (HTTP :80) +-----------+------------+ | +---------------+---------------+ | | | +----v----+ +----v----+ +----v----+ | web-vm | | web-vm | | web-vm | Regional MIG | zone-a | | zone-b | | zone-c | (spread across zones) +---------+ +---------+ +---------+ \_______________|_______________/ | VPC: secure-vpc / public-subnet (10.0.1.0/24) ``` **高可用理念:** 任何单个实例——甚至单个可用区——的宕机都不会导致网站下线。负载均衡器仅将流量发送到健康检查报告为健康的实例,并且 MIG 通过重建任何死掉的实例来保持组的规模达到目标大小。 ## 关键概念(构建前值得了解) - **实例模板** (Instance template) —— VM 的不可变蓝图。MIG 从中复制出相同的实例。修改配置 = 新建模板,而不是编辑运行中的 VM。 - **托管实例组 (MIG)** (Managed Instance Group) —— 根据模板维护目标数量的实例。*区域* (Regional) MIG 将实例分布在多个可用区,比*可用区* (zonal) MIG 具有更高的可用性。 - **健康检查** (Health check) —— 定期探测每个实例。不健康的实例将被移出轮询,并且(通过自动修复)被重新创建。 - **负载均衡器组件** —— GCP 的负载均衡器由多个部分组装而成:*转发规则* (forwarding rule) (公网 IP) → *目标代理* (target proxy) → *URL 映射* (URL map) (路由规则) → *后端服务* (backend service) (哪个组服务流量,以及健康检查)。手动构建它们可以让你了解各个部分是如何组合在一起的。 ## 负载均衡器的实际工作原理(组件链) 这个实验教会我的最重要的一点是:在 GCP 中,负载均衡器**不是一个单一对象** —— 它是一条由你组装的、执行单一任务的小型资源链。请求沿着这条链传递: ``` Visitor → Forwarding rule → Target proxy → URL map → Backend service → Instance group → VM ``` | 组件 | 它的唯一职责 | 通俗易懂的作用解释 | |---|---|---| | **转发规则** (Forwarding rule) | 持有公网 IP + 端口 | 前门——唯一的公共入口 | | **目标 HTTP 代理** (Target HTTP proxy) | 在特定协议下终止连接 | 负责应答的前台(HTTP 还是 HTTPS;在 HTTPS 下,SSL 证书附加在这里) | | **URL 映射** (URL map) | 根据主机/路径将请求路由到后端 | 交换机目录(`/api` → 一个后端,`/images` → 另一个) | | **后端服务** (Backend service) | 持有策略 + 健康检查 | 管理者:哪个池服务流量,以及谁处于健康状态 | | **后端** (Backend) | 附加到该服务的一个池 | 管理者名册上的一个团队(指向一个*组*,而不是单个 VM) | | **实例组 (MIG)** | 跨可用区运行相同的 VM | 实际提供页面服务的工人 | | **健康检查** (Health check) | 通过 :80 探测每个实例 | 主管的点名——死掉的实例会被移出轮询 | **为什么它是自下而上构建的:** 你不能将某个东西连接到一个尚不存在的资源上,因此构建顺序是 workers → health check → backend service → URL map → proxy → forwarding rule。转发规则(公共门)是在机器内部的整个部分准备好*之后*创建的。 **“后端服务”与“一个后端”——命名陷阱:** *后端服务*是管理者(规则 + 健康检查)。*一个后端*是一个附加到其上的池——我的实例组 `web-mig`。后端指向一整个**组**,而不是单个 VM;这种间接性正是消除单点故障的关键。 **每个组件都是必不可少的粘合剂,而不是装饰品:** 转发规则不能直接指向 URL map——它只能指向*目标代理* (target proxy),而目标代理又是唯一可以引用 URL map 的对象。移除任何中间链接,链条就无法组装(在构建时)或会中断服务(如果在运行时被删除),即使 VM 保持完全健康也是如此。 ## 构建方式(`gcloud` CLI) 在这里,CLI 实际上比控制台*更容易*——负载均衡器有许多组件,逐个点击屏幕比执行这些命令要慢。请在 Cloud Shell 中运行。 ### 0. 网络基础(如果已销毁,请重建 Phase 1 的网络) ``` gcloud compute networks create secure-vpc --subnet-mode=custom gcloud compute networks subnets create public-subnet \ --network=secure-vpc --region=us-central1 --range=10.0.1.0/24 ``` ### 1. 防火墙规则 ``` # 允许健康检查和 load-balancer 流量访问 Web 层。 # 这两个范围是 Google 的健康检查 / LB 源范围 —— 并非任意指定。 gcloud compute firewall-rules create allow-health-check \ --network=secure-vpc --direction=INGRESS --action=ALLOW \ --rules=tcp:80 \ --source-ranges=130.211.0.0/22,35.191.0.0/16 \ --target-tags=web-server # 仅通过 IAP 进行 Admin SSH —— 基于身份,任何地方都不使用家庭 IP。 gcloud compute firewall-rules create allow-ssh-iap \ --network=secure-vpc --direction=INGRESS --action=ALLOW \ --rules=tcp:22 --source-ranges=35.235.240.0/20 --target-tags=web-server ``` ### 2. 实例模板 ``` gcloud compute instance-templates create web-template \ --machine-type=e2-micro \ --network=secure-vpc --subnet=public-subnet --region=us-central1 \ --tags=web-server \ --image-family=debian-12 --image-project=debian-cloud \ --metadata=startup-script='#! /bin/bash apt update && apt install -y nginx echo "

Served by: $(hostname)

" > /var/www/html/index.html' ``` *`$(hostname)` 技巧意味着每个实例都会显示自己的名字——因此,当你刷新负载均衡器时,你可以切实看到流量命中了不同的后端。* ### 3. 区域托管实例组(多可用区) ``` gcloud compute instance-groups managed create web-mig \ --template=web-template --size=2 --region=us-central1 # 告诉实例组哪个端口提供 HTTP 服务(LB 需要这个命名端口) gcloud compute instance-groups managed set-named-ports web-mig \ --named-ports=http:80 --region=us-central1 ``` ### 4. 健康检查 ``` gcloud compute health-checks create http web-health-check \ --port=80 --request-path=/ ``` ### 5. 组装负载均衡器 ``` # Backend service,已连接到健康检查 gcloud compute backend-services create web-backend \ --protocol=HTTP --port-name=http \ --health-checks=web-health-check --global # 将该 instance group 作为 backend 附加 gcloud compute backend-services add-backend web-backend \ --instance-group=web-mig --instance-group-region=us-central1 --global # URL map → target proxy → forwarding rule(公共入口点) gcloud compute url-maps create web-map --default-service=web-backend gcloud compute target-http-proxies create web-proxy --url-map=web-map gcloud compute forwarding-rules create web-forwarding-rule \ --global --target-http-proxy=web-proxy --ports=80 ``` ### 6. 获取负载均衡器的公网 IP ``` gcloud compute forwarding-rules describe web-forwarding-rule \ --global --format="get(IPAddress)" ``` 将该 IP 粘贴到浏览器中。*给它几分钟时间*——一个新的 LB 在开始提供服务之前可能需要 3-5 分钟。刷新几次,观察后端之间的主机名变化。 ### 7. (可选)自动扩缩容 ``` gcloud compute instance-groups managed set-autoscaling web-mig \ --region=us-central1 --min-num-replicas=2 --max-num-replicas=4 \ --target-cpu-utilization=0.6 --cool-down-period=60 ``` ## 验证与乐趣——证明高可用性 | 测试 | 预期结果 | |---|---| | 反复刷新 LB IP | 主机名发生改变 → 流量正在实例之间进行负载均衡 ✅ | | 控制台 → 检查后端健康状况 | 实例报告为 **健康** (Healthy) ✅ | | 手动删除一个实例 | MIG 检测到它并**自动重建**(自我修复) ✅ | | 检查实例的可用区 | 它们分布在 `us-central1-a/b/c` → 具备可用区弹性 ✅ | **尝试自我修复演示** —— 这是这个实验中最好的面试故事: ``` # 列出该组的实例,然后故意删除其中一个 gcloud compute instance-groups managed list-instances web-mig --region=us-central1 gcloud compute instances delete --zone= -q # 一分钟后重新列出 —— MIG 已经将其重建,恢复至大小 2 ``` ## ⚠️ 费用警告——离开前请务必阅读 与 Phase 1 不同,**负载均衡器不是免费的**。无论是否有人访问,全球转发规则每小时大约都会扣费,并且它不包含在永久免费层级中。你的 $300 额度可以轻松承担一个实验的费用,**但你必须在完成后将其销毁**——转发规则运行一个月是要花真金白银的。如有需要,请设置日历提醒。 ## 清理(按相反的依赖顺序删除) ``` gcloud compute forwarding-rules delete web-forwarding-rule --global -q gcloud compute target-http-proxies delete web-proxy -q gcloud compute url-maps delete web-map -q gcloud compute backend-services delete web-backend --global -q gcloud compute health-checks delete web-health-check -q gcloud compute instance-groups managed delete web-mig --region=us-central1 -q gcloud compute instance-templates delete web-template -q gcloud compute firewall-rules delete allow-health-check allow-ssh-iap -q gcloud compute networks subnets delete public-subnet --region=us-central1 -q gcloud compute networks delete secure-vpc -q ``` 一天后,确认 **Billing → Reports** 费用图表降为零。 ## 展现的技能 高可用性设计 · 负载均衡(后端服务、URL 映射、目标代理、转发规则) · 托管实例组与实例模板 · 健康检查与自我修复 · 多可用区弹性 · 自动扩缩容 · 基于身份的访问 (IAP) · 通过 CLI (`gcloud`) 管理基础设施 ## 我学到了什么 核心教训是 GCP 负载均衡器是一个*由独立资源组成的链条*,而不是一个单一对象——只有当你通过它追踪一个请求(转发规则 → 代理 → URL 映射 → 后端服务 → 实例组)时,这些组件才有意义。将“后端服务”(管理者)与“一个后端”(附加的组)区分开来是豁然开朗的时刻。我还了解到,这些组件必须自下而上构建,因为每个组件都引用了它下方的资源。 在运维方面,有两点让我印象深刻:销毁顺序很重要——我在删除 VPC 时遇到了一个错误,因为之前 NAT 设置中遗留的 Cloud Router 仍然连接在上面,这教会了我当子资源引用父资源时,GCP 会阻止删除该父资源。此外,我还学会了将长 `gcloud` 命令作为单行干净的命令行运行,而不是依赖反斜杠行继续符,因为之前行中间多余的 `\ ` 一直在破坏我的参数。 *(在发布之前,请用你自己的语言重新表述这些内容——你的措辞比我的更好。)* ## 🔒 发布前——敏感信息遮挡检查清单 这是我从 Phase 1 中学到的:将每张屏幕截图都视为攻击面。在任何图片进入这个公开仓库之前,请涂黑(使用实心框,不要模糊处理): - IP 地址(如果你愿意,包括负载均衡器的公网 IP) - 项目 ID 和账号号码 - 电子邮件地址 ## 本系列的下一步 - **Phase 3** — 安全加固(IAM 最小权限、Cloud Armor WAF、Secret Manager) - **Phase 4** — 使用 Terraform 将所有内容重建为基础设施即代码 - **Phase 5** — 监控、日志记录与警报 - **Phase 6** — 毕业项目:完整的、安全的、高可用的云应用程序 *实验完成时间:2026-07-26 · 云服务提供商:Google Cloud Platform*
标签:Google Cloud, Nginx, 云计算, 架构设计, 自动化运维, 规则引擎, 负载均衡