从零开始:用 Terraform 在华为云上部署高可用 Web 应用架构

举报
wls666 发表于 2026/10/28 17:22:38 2026/10/28
【摘要】 # 从零开始:用 Terraform 在华为云上部署高可用 Web 应用架构> 本文面向有一定云基础、但刚接触基础设施即代码(IaC)的开发者。我们将用 Terraform 在华为云上一步到位地部署一套包含 VPC、子网、安全组、弹性负载均衡(ELB)和多台 ECS 的高可用 Web 应用架构——并解释每一行代码背后的含义。## 为什么选择 Terraform?如果你过去都是在控制台里手动点...

# 从零开始:用 Terraform 在华为云上部署高可用 Web 应用架构

> 本文面向有一定云基础、但刚接触基础设施即代码(IaC)的开发者。我们将用 Terraform 在华为云上一步到位地部署一套包含 VPC、子网、安全组、弹性负载均衡(ELB)和多台 ECS 的高可用 Web 应用架构——并解释每一行代码背后的含义。

## 为什么选择 Terraform?

如果你过去都是在控制台里手动点鼠标创建云资源,可能遇到过这些场景:

- 环境搭好了,想再复制一套测试环境,又得从头点一遍
- 团队来了新人,问他"这套架构怎么搭的",谁也说不清
- 手滑删错了一个资源,排查半天才知道影响范围

**基础设施即代码(Infrastructure as Code, IaC)** 就是解决这些问题的思路:把基础设施用代码描述出来,像管理应用代码一样管理基础设施——版本控制、代码审查、一键复现。

Terraform 是目前最主流的 IaC 工具之一,华为云提供了官方 Provider(`huaweicloud`),支持 200+ 种资源类型,覆盖计算、网络、存储、数据库等核心服务。

## 我们要部署什么?

一套经典的高可用 Web 应用架构:

```
                    ┌─────────────┐
                    │   ELB (公网)  │
                    │  负载均衡器   │
                    └──────┬──────┘
                           │
              ┌────────────┼────────────┐
              │            │            │
        ┌─────┴─────┐ ┌───┴─────┐ ┌───┴─────┐
        │  ECS-1    │ │  ECS-2  │ │  ECS-3  │
        │  Web应用  │ │  Web应用 │ │  Web应用 │
        └─────┬─────┘ └───┬─────┘ └───┬─────┘
              │            │            │
              └────────────┼────────────┘
                           │
                    ┌──────┴──────┐
                    │  VPC 内网子网 │
                    │  172.16.0.0/24│
                    └─────────────┘
```

**架构要点:**

| 组件 | 作用 | 高可用体现 |
|------|------|-----------|
| VPC + 子网 | 隔离的网络空间 | 资源在内网通信,不直接暴露 |
| 安全组 | 精确控制出入站规则 | 只开放必要端口 |
| ELB | 公网入口,分发流量 | 后端 ECS 故障自动摘除 |
| ECS × 3 | 运行 Web 应用 | 多实例分摊流量,单实例宕机不影响整体 |

## 前置准备

### 1. 安装 Terraform

```bash
# Linux / macOS
curl -fsSL https://releases.hashicorp.com/terraform/1.7.5/terraform_1.7.5_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m).zip -o terraform.zip
unzip terraform.zip && sudo mv terraform /usr/local/bin/

# 验证安装
terraform version
```

> **提示:** 华为云提供了 Terraform 的国内镜像源,如果从 HashiCorp 官方下载慢,可以在 `~/.terraformrc` 中配置镜像加速:
> ```hcl
> provider_installation {
>   registry_mirrors {
>     "registry.terraform.io" = "https://mirrors.huaweicloud.com/terraform-provider"
>   }
> }
> ```

### 2. 准备华为云认证信息

你需要以下信息(在华为云控制台的"我的凭证"页面获取):

- **AK / SK**:访问密钥
- **Region**:区域,如 `cn-north-4`(华北-北京四)
- **Project ID**:项目 ID

建议通过环境变量传入,避免硬编码到代码中:

```bash
export HW_ACCESS_KEY="你的AK"
export HW_SECRET_KEY="你的SK"
export HW_REGION="cn-north-4"
export HW_PROJECT_ID="你的项目ID"
```

## 开始编写 Terraform 代码

### 项目结构

```
huaweicloud-ha-web/
├── main.tf       # 主配置:provider + 资源定义
├── variables.tf  # 输入变量
└── outputs.tf    # 输出信息
```

### 第一步:variables.tf — 定义可复用的参数

把可能变化的值提取成变量,是 Terraform 的基本习惯。这样同一套代码可以部署到不同区域、不同规格,只需改变量值。

```hcl
# variables.tf

variable "region" {
  description = "华为云区域"
  type        = string
  default     = "cn-north-4"
}

variable "ecs_flavor" {
  description = "ECS 规格(CPU/内存)"
  type        = string
  default     = "s6.large.2"  # 2核4G
}

variable "ecs_count" {
  description = "ECS 实例数量"
  type        = number
  default     = 3
}

variable "image_id" {
  description = "ECS 镜像 ID(EulerOS 2.9)"
  type        = string
  # 请替换为你账号下可用的镜像 ID,可通过控制台或 hcloud CLI 查询
  default     = "your-image-id-here"
}

variable "admin_password" {
  description = "ECS 管理员密码"
  type        = string
  sensitive   = true  # 标记为敏感值,日志中会脱敏
  default     = "YourStrongPassword123!"
}
```

> **关于 `sensitive = true`:** 这个标记会让 Terraform 在 plan/apply 的输出中用 `(sensitive value)` 代替明文,避免密码出现在日志里。但注意,state 文件中仍然是明文存储的,所以 state 文件本身也要妥善保管。

### 第二步:main.tf — 核心资源配置

这是文章的主体,我们逐块讲解。

#### 2.1 Provider 配置

```hcl
# main.tf

terraform {
  required_providers {
    huaweicloud = {
      source  = "huaweicloud/huaweicloud"
      version = ">= 1.50.0"
    }
  }
}

provider "huaweicloud" {
  region     = var.region
  # AK/SK 通过环境变量传入,不写在这里
}
```

**为什么 AK/SK 不写在代码里?** 代码会进版本控制系统(Git),密钥不应该跟着代码走。通过环境变量传入是最基本的安全实践。

#### 2.2 VPC 和子网

```hcl
# VPC — 虚拟私有云,相当于你在云上的一块隔离网络
resource "huaweicloud_vpc" "main" {
  name = "ha-web-vpc"
  cidr = "172.16.0.0/16"
}

# 子网 — VPC 内的更细分段,ECS 都部署在子网内
resource "huaweicloud_vpc_subnet" "web" {
  name       = "ha-web-subnet"
  vpc_id     = huaweicloud_vpc.main.id
  cidr       = "172.16.0.0/24"
  gateway_ip = "172.16.0.1"
}
```

**VPC 和子网是什么关系?** 打个比方:VPC 是你租的一整栋楼,子网是楼里的一层。CIDR `172.16.0.0/16` 定义了整栋楼能用的地址范围,`172.16.0.0/24` 是其中一层的地址段。

#### 2.3 安全组

```hcl
# 安全组 — 控制 ECS 的出入站流量,相当于贴在门上的访问规则
resource "huaweicloud_networking_secgroup" "web" {
  name        = "ha-web-sg"
  description = "安全组:允许 ELB 转发的 HTTP 流量,允许 SSH 管理"
}

# 入站规则:允许 80 端口(HTTP)
resource "huaweicloud_networking_secgroup_rule" "allow_http" {
  direction         = "ingress"
  ethertype         = "IPv4"
  protocol          = "tcp"
  port_range_min    = 80
  port_range_max    = 80
  remote_ip_prefix  = "0.0.0.0/0"
  security_group_id = huaweicloud_networking_secgroup.web.id
}

# 入站规则:允许 22 端口(SSH)
# 注意:生产环境建议限制来源 IP,不要对全网开放
resource "huaweicloud_networking_secgroup_rule" "allow_ssh" {
  direction         = "ingress"
  ethertype         = "IPv4"
  protocol          = "tcp"
  port_range_min    = 22
  port_range_max    = 22
  remote_ip_prefix  = "0.0.0.0/0"  # 生产环境请改为你的管理 IP,如 203.0.113.10/32
  security_group_id = huaweicloud_networking_secgroup.web.id
}
```

> **⚠️ 安全提醒:** 上面的 SSH 规则对 `0.0.0.0/0` 开放,这在教程中方便演示,但在生产环境中是**高风险**的3——相当于把你服务器的管理端口对全世界开放。正确做法是只允许你的堡垒机或管理 IP 访问,把 `remote_ip_prefix` 改成具体的 IP 地址,如 `203.0.113.10/32`。

#### 2.4 弹性负载均衡(ELB)

```hcl
# ELB 负载均衡器 — 公网入口,将流量分发到后端多台 ECS
resource "huaweicloud_elb_loadbalancer" "web" {
  name            = "ha-web-elb"
  vpc_id          = huaweicloud_vpc.main.id
  network_type    = "external"  # 对外提供公网访问
  admin_state_up  = true
}

# ELB 监听器 — 监听 80 端口的 HTTP 流量
resource "huaweicloud_elb_listener" "http" {
  name            = "ha-web-listener"
  protocol        = "HTTP"
  protocol_port   = 80
  loadbalancer_id = huaweicloud_elb_loadbalancer.web.id
}

# 后端服务器组 — ECS 集群
resource "huaweicloud_elb_pool" "web" {
  name            = "ha-web-pool"
  protocol        = "HTTP"
  lb_algorithm    = "ROUND_ROBIN"  # 轮询,流量均匀分配
  listener_id     = huaweicloud_elb_listener.http.id
}

# 健康检查 — ELB 定期检查后端 ECS 是否正常,异常的自动摘除
resource "huaweicloud_elb_monitor" "health" {
  pool_id       = huaweicloud_elb_pool.web.id
  protocol      = "HTTP"
  port          = 80
  path          = "/"
  interval      = 10   # 每 10 秒检查一次
  timeout       = 5    # 超时 5 秒
  max_retries   = 3    # 连续 3 次失败才标记为异常
}
```

**健康检查为什么重要?** 假设 ECS-2 因为应用崩溃无法响应,如果没有健康检查,ELB 还会往它转发流量,用户就会偶尔碰到报错。有了健康检查,ELB 在 30 秒内(`interval × max_retries`)就会把异常实例摘除,用户完全无感知。

#### 2.5 ECS 集群

```hcl
# ECS 实例 — 用 count 创建多台,实现高可用
resource "huaweicloud_compute_instance" "web" {
  count              = var.ecs_count  # 默认 3 台
  name               = "ha-web-ecs-${count.index + 1}"
  flavor_id          = var.ecs_flavor
  image_id           = var.image_id
  admin_pass         = var.admin_password
  security_group_ids = [huaweicloud_networking_secgroup.web.id]

  # 网络配置:接入子网,自动分配内网 IP
  network {
    uuid = huaweicloud_vpc_subnet.web.id
  }

  tags = {
    app     = "ha-web"
    role    = "web-server"
    managed = "terraform"
  }
}

# 将 ECS 加入 ELB 后端服务器组
resource "huaweicloud_elb_member" "web" {
  count         = var.ecs_count
  pool_id       = huaweicloud_elb_pool.web.id
  address       = huaweicloud_compute_instance.web[count.index].access_ip_v4
  protocol_port = 80
  weight        = 1
}
```

**`count` 是什么?** 这是 Terraform 的元参数(meta-argument)。`count = 3` 意味着这个 resource 会创建 3 个实例,通过 `count.index`(0, 1, 2)区分它们。改一个数字就能调整集群规模——这就是 IaC 的威力。

#### 2.6 EIP(弹性公网 IP)

```hcl
# 给 ELB 绑定一个弹性公网 IP,让外部能访问
resource "huaweicloud_vpc_eip" "elb" {
  publicip {
    type = "5_bgp"  # BGP 多线,网络质量更好
  }
  bandwidth {
    name        = "ha-web-bw"
    size        = 5  # 5 Mbit/s
    share_type  = "PER"
    charge_mode = "traffic"
  }
}
```

### 第三步:outputs.tf — 输出关键信息

部署完成后,我们想知道 ELB 的公网 IP 是多少,方便验证。

```hcl
# outputs.tf

output "elb_public_ip" {
  description = "ELB 公网访问 IP"
  value       = huaweicloud_vpc_eip.elb.address
}

output "ecs_private_ips" {
  description = "ECS 内网 IP 列表"
  value       = huaweicloud_compute_instance.web[*].access_ip_v4
}

output "vpc_id" {
  description = "VPC ID"
  value       = huaweicloud_vpc.main.id
}
```

## 执行部署

### 1. 初始化

```bash
terraform init
```

这一步会下载华为云 Provider 插件。如果配置了华为云镜像源,下载速度会快很多。

### 2. 预览变更

```bash
terraform plan
```

**这是 Terraform 最重要的安全机制之一。** `plan` 会告诉你它准备创建、修改、删除哪些资源,但不会真正执行。你可以在执行前检查是否符合预期:

```
Plan: 14 to add, 0 to change, 0 to destroy.

  # huaweicloud_vpc.main will be created
  # huaweicloud_vpc_subnet.web will be created
  # huaweicloud_networking_secgroup.web will be created
  # huaweicloud_elb_loadbalancer.web will be created
  # huaweicloud_compute_instance.web[0] will be created
  # huaweicloud_compute_instance.web[1] will be created
  # huaweicloud_compute_instance.web[2] will be created
  ...
```

### 3. 正式部署

```bash
terraform apply
```

输入 `yes` 确认后,Terraform 会按照依赖关系自动编排创建顺序。整个过程通常 3-5 分钟。

部署完成后,你会看到输出信息:

```
Apply complete! Resources: 14 added, 0 changed, 0 destroyed.

Outputs:

elb_public_ip = "114.116.xxx.xxx"
ecs_private_ips = [
  "172.16.0.10",
  "172.16.0.11",
  "172.16.0.12",
]
```

### 4. 验证

用浏览器或 curl 访问 ELB 的公网 IP:

```bash
curl http://114.116.xxx.xxx
```

如果你在 ECS 上部署了 Web 应用,应该能收到响应。多次请求,可以通过查看 ECS 日志确认流量被轮询分发到了不同实例。

## 日常运维:改一个数字就能扩容

假设你的应用流量增长,需要从 3 台扩到 5 台。用传统方式,你得去控制台手动创建 2 台 ECS、配置网络、加入负载均衡。用 Terraform:

```bash
# 修改变量
export TF_VAR_ecs_count=5

# 预览变更 — 只会新增 2 台,已有的不受影响
terraform plan
# Plan: 2 to add, 0 to change, 0 to destroy.

# 执行
terraform apply
```

**这就是 IaC 的核心价值:基础设施的变更和应用的变更一样,可预览、可追溯、可回滚。**

## 清理资源

验证完成后,记得清理资源,避免产生不必要的费用:

```bash
terraform destroy
```

输入 `yes` 确认,Terraform 会按照依赖关系的逆序依次删除所有资源。

> **注意:** `destroy` 会删除所有 Terraform 管理的资源,且不可逆。执行前请确认环境无误。

## 回顾与思考

### 我们做了什么

用约 120 行 Terraform 代码,部署了一套包含 14 个资源的高可用 Web 应用架构:VPC、子网、安全组、安全组规则、ELB(负载均衡器 + 监听器 + 后端组 + 健康检查)、3 台 ECS、EIP 和带宽。

### 为什么这比手动操作好

| 对比维度 | 控制台手动操作 | Terraform IaC |
|---------|-------------|---------------|
| 可复现性 | 靠记忆和文档,容易遗漏 | 代码即文档,`terraform apply` 一键复现 |
| 可审查性 | 变更无记录,出了问题难追溯 | 每次变更都有 diff,可走 Code Review |
| 团队协作 | "只有张三知道怎么搭的" | 代码在 Git 里,人人可读可改 |
| 扩缩容 | 手动逐台操作,容易出错 | 改一个数字,plan 确认,apply 生效 |
| 环境一致性 | 开发/测试/生产容易不一致 | 同一套代码,不同变量值,天然一致 |

### 进阶方向

本文是一个入门教程,实际生产环境还需要考虑:

1. **多可用区(AZ)部署**:将 ECS 分布在不同 AZ,整个 AZ 故障时仍可服务
2. **自动伸缩(AS)**:根据 CPU/内存指标自动增减 ECS 实例数
3. **数据库层**:加入 RDS 作为后端存储,配置只读实例分担读流量
4. **CI/CD 集成**:把 Terraform 代码纳入 GitLab CI / CodeArts 流水线,实现基础设施的持续交付
5. **State 远程存储**:将 state 文件存到 OBS,支持团队多人协作和状态锁定

### 写在最后

从"在控制台点鼠标"到"用代码描述基础设施",这个转变不需要你一次性掌握所有东西。从本文这样一个小项目开始,先把一套环境用 Terraform 管起来,体验 `plan → apply → destroy` 的完整流程,再逐步加入更多资源、更多环境。

当你发现改一行代码、敲一个命令就能完成过去半小时的手动操作时,你就回不去了。

---

**相关链接:**

- [Terraform 官方文档](https://developer.hashicorp.com/terraform/docs)
- [华为云 Terraform Provider](https://registry.terraform.io/providers/huaweicloud/huaweicloud/latest/docs)
- [华为云 Terraform 实践最佳实践](https://support.huaweicloud.com/terraform/index.html)

> 本文示例代码已开源,欢迎 Star 和 PR。如果在实践过程中遇到问题,欢迎在评论区交流。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。