使用 Terraform 在华为云上自动化部署 Web 应用基础架构(VPC + ECS + ELB + RDS)
使用 Terraform 在华为云上自动化部署 Web 应用基础架构(VPC + ECS + ELB + RDS)
前言
作为基础设施即代码(IaC)的践行者,我一直在用 Terraform 管理华为云资源。本文将分享一个完整的实战案例:用 Terraform 一键部署一个包含 VPC、子网、安全组、ELB 负载均衡、ECS 服务器和 RDS 数据库的 Web 应用基础架构。
无论你是刚接触 Terraform 的云新手,还是正在寻找华为云 IaC 最佳实践的开发者,希望这篇文章能给你带来实用的参考。
一、架构设计
我们要部署的架构如下:
- VPC:一个虚拟私有云,网段 192.168.0.0/16
- 子网:两个子网分别用于 ECS 和 RDS,分布在不同可用区以实现高可用
- 安全组:ECS 安全组放通 80/443/22 端口,RDS 安全组仅放通 3306 给 ECS 子网
- ELB:弹性负载均衡,将 HTTP 流量分发到两台 ECS
- ECS:两台 s6.large.2 规格的云服务器,运行 Nginx
- RDS:一台 GaussDB(for MySQL) 数据库实例,主备高可用
架构图如下:
┌─────────────┐
│ Internet │
└──────┬──────┘
│
┌──────┴──────┐
│ ELB (公网) │
│ HTTP :80 │
└──────┬──────┘
│
┌────────────┼────────────┐
│ │
┌────────┴────────┐ ┌────────┴────────┐
│ ECS-1 (AZ-a) │ │ ECS-2 (AZ-b) │
│ Nginx :80 │ │ Nginx :80 │
│ s6.large.2 │ │ s6.large.2 │
└────────┬────────┘ └────────┬────────┘
│ │
└────────────┬────────────┘
│
┌──────┴──────┐
│ RDS (主备) │
│ MySQL 8.0 │
│ AZ-a + AZ-b│
└─────────────┘
二、环境准备
2.1 安装 Terraform
推荐使用华为云镜像源加速安装:
# 下载 Terraform(以 ARM64 为例)
wget https://mirrors.huaweicloud.com/terraform/terraform_1.6.0_linux_arm64.zip
unzip terraform_1.6.0_linux_arm64.zip
mv terraform /usr/local/bin/
# 验证安装
terraform version
2.2 配置 Provider
创建 provider.tf 文件,配置华为云 Provider:
terraform {
required_providers {
huaweicloud = {
source = "huaweicloud/huaweicloud"
version = "~> 1.50"
}
}
}
provider "huaweicloud" {
region = "cn-north-4"
access_key = var.access_key
secret_key = var.secret_key
}
创建 variables.tf 管理变量:
variable "access_key" {
description = "华为云 AK"
type = string
sensitive = true
}
variable "secret_key" {
description = "华为云 SK"
type = string
sensitive = true
}
variable "db_password" {
description = "RDS 数据库管理员密码"
type = string
sensitive = true
default = "MyDb@Pass2024!"
}
安全提示:AK/SK 不要硬编码在
.tf文件中,建议通过环境变量传入:export HW_ACCESS_KEY="你的AK" export HW_SECRET_KEY="你的SK"
三、编写 Terraform 代码
3.1 网络层 — VPC 与子网
# vpc.tf
resource "huaweicloud_vpc" "web_vpc" {
name = "web-app-vpc"
cidr = "192.168.0.0/16"
}
resource "huaweicloud_vpc_subnet" "web_subnet" {
name = "web-subnet-az1"
vpc_id = huaweicloud_vpc.web_vpc.id
cidr = "192.168.1.0/24"
gateway_ip = "192.168.1.1"
availability_zone = "cn-north-4a"
}
resource "huaweicloud_vpc_subnet" "db_subnet" {
name = "db-subnet-az2"
vpc_id = huaweicloud_vpc.web_vpc.id
cidr = "192.168.2.0/24"
gateway_ip = "192.168.2.1"
availability_zone = "cn-north-4b"
}
这里有个值得注意的点:两个子网放在不同的可用区(AZ-a 和 AZ-b),这是实现高可用的基础。如果某个可用区发生故障,另一个可用区的资源仍然可用。
3.2 安全组 — 最小权限原则
# security.tf
# ============ ECS 安全组 ============
resource "huaweicloud_networking_secgroup" "web_sg" {
name = "web-server-sg"
}
# 放通 HTTP
resource "huaweicloud_networking_secgroup_rule" "web_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_sg.id
}
# 放通 HTTPS
resource "huaweicloud_networking_secgroup_rule" "web_https" {
direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = 443
port_range_max = 443
remote_ip_prefix = "0.0.0.0/0"
security_group_id = huaweicloud_networking_secgroup.web_sg.id
}
# 放通 SSH(生产环境建议改为你的管理 IP)
resource "huaweicloud_networking_secgroup_rule" "web_ssh" {
direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = 22
port_range_max = 22
remote_ip_prefix = "0.0.0.0/0"
security_group_id = huaweicloud_networking_secgroup.web_sg.id
}
# ============ RDS 安全组 ============
resource "huaweicloud_networking_secgroup" "db_sg" {
name = "db-server-sg"
}
# 仅允许 ECS 子网访问 3306
resource "huaweicloud_networking_secgroup_rule" "db_mysql" {
direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = 3306
port_range_max = 3306
remote_ip_prefix = "192.168.1.0/24"
security_group_id = huaweicloud_networking_secgroup.db_sg.id
}
注意:RDS 安全组只放通了 ECS 子网网段
192.168.1.0/24,而不是0.0.0.0/0。数据库不应该对公网开放,这是基本的安全原则。很多新手容易在这里踩坑,直接把数据库暴露在公网上。
3.3 计算层 — ECS 服务器
# ecs.tf
# 查询 CentOS 镜像
data "huaweicloud_images_image" "centos" {
name = "CentOS 7.9 64bit"
most_recent = true
}
# 创建两台 ECS,分布在不同可用区
resource "huaweicloud_compute_instance" "web_server" {
count = 2
name = "web-server-${count.index + 1}"
image_id = data.huaweicloud_images_image.centos.id
flavor_id = "s6.large.2"
availability_zone = count.index == 0 ? "cn-north-4a" : "cn-north-4b"
network {
uuid = huaweicloud_vpc_subnet.web_subnet.id
}
security_group_ids = [huaweicloud_networking_secgroup.web_sg.id]
# 通过 user_data 自动安装 Nginx
user_data = base64encode(<<-EOF
#!/bin/bash
yum install -y nginx
systemctl start nginx
systemctl enable nginx
echo "Server ${count.index + 1}" > /usr/share/nginx/html/index.html
EOF
)
tags = {
Environment = "production"
Component = "web-server"
}
}
这里用了 count = 2 配合 count.index 实现两台服务器的批量创建,配合 user_data 在启动时自动安装 Nginx,无需手动登录配置。
3.4 负载均衡 — ELB
# elb.tf
# 创建负载均衡器
resource "huaweicloud_elb_loadbalancer" "web_elb" {
name = "web-app-elb"
vpc_id = huaweicloud_vpc.web_vpc.id
subnet_id = huaweicloud_vpc_subnet.web_subnet.id
l7_flavor_id = "l7.flavor.small"
}
# HTTP 监听器
resource "huaweicloud_elb_listener" "web_listener" {
name = "web-http-listener"
protocol = "HTTP"
protocol_port = 80
loadbalancer_id = huaweicloud_elb_loadbalancer.web_elb.id
}
# 后端服务器组
resource "huaweicloud_elb_pool" "web_pool" {
name = "web-backend-pool"
protocol = "HTTP"
lb_algorithm = "ROUND_ROBIN"
listener_id = huaweicloud_elb_listener.web_listener.id
}
# 将两台 ECS 加入后端组
resource "huaweicloud_elb_member" "web_members" {
count = 2
pool_id = huaweicloud_elb_pool.web_pool.id
address = huaweicloud_compute_instance.web_server[count.index].access_ip_v4
protocol_port = 80
subnet_id = huaweicloud_vpc_subnet.web_subnet.id
}
3.5 数据库层 — GaussDB(for MySQL)
# rds.tf
resource "huaweicloud_rds_instance" "web_db" {
name = "web-app-db"
flavor = "rds.mysql.com.s6.large.2.ha"
availability_zone = "cn-north-4a,cn-north-4b" # 主备双可用区
db {
type = "MySQL"
version = "8.0"
}
volume {
type = "SSD"
size = 50
}
vpc_id = huaweicloud_vpc.web_vpc.id
subnet_id = huaweicloud_vpc_subnet.db_subnet.id
security_group_id = huaweicloud_networking_secgroup.db_sg.id
password = var.db_password
}
availability_zone 写成 cn-north-4a,cn-north-4b 表示主实例在 AZ-a,备实例在 AZ-b,自动实现跨可用区高可用。
3.6 输出 — 方便验证
# outputs.tf
output "elb_vip" {
description = "ELB 虚拟 IP"
value = huaweicloud_elb_loadbalancer.web_elb.vip_address
}
output "ecs_private_ips" {
description = "ECS 私网 IP"
value = huaweicloud_compute_instance.web_server[*].access_ip_v4
}
output "rds_address" {
description = "RDS 连接地址"
value = huaweicloud_rds_instance.web_db.public_ip
sensitive = true
}
四、部署与验证
4.1 初始化与计划
# 初始化 Provider(会自动下载华为云 Provider 插件)
terraform init
# 查看执行计划
terraform plan
terraform plan 会列出所有将要创建的资源,大概是这样的输出:
Plan: 16 to add, 0 to change, 0 to destroy.
# huaweicloud_vpc.web_vpc will be created
# huaweicloud_vpc_subnet.web_subnet will be created
# huaweicloud_vpc_subnet.db_subnet will be created
# huaweicloud_networking_secgroup.web_sg will be created
# huaweicloud_networking_secgroup.db_sg will be created
# huaweicloud_networking_secgroup_rule.web_http will be created
# ...(共 16 个资源)
仔细检查后确认无误,执行部署:
terraform apply
输入 yes 确认,等待几分钟即可完成部署。
4.2 验证部署结果
# 获取 ELB 的虚拟 IP
terraform output elb_vip
# 访问 Web 服务,多次请求会看到轮询到不同的 ECS
curl http://$(terraform output -raw elb_vip)
# 输出: Server 1
curl http://$(terraform output -raw elb_vip)
# 输出: Server 2
4.3 销毁资源
测试完成后,一键清理所有资源:
terraform destroy
五、关键经验总结
5.1 状态管理
生产环境不要使用本地 state 文件,建议配置远程后端(如 OBS):
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "web-app/terraform.tfstate"
region = "cn-north-4"
endpoint = "obs.cn-north-4.myhuaweicloud.com"
}
}
这样团队成员可以共享状态,避免本地 state 丢失或冲突。
5.2 安全最佳实践
| 实践 | 说明 |
|---|---|
| 安全组最小权限 | 数据库安全组只放通应用子网,不对公网开放 |
| AK/SK 管理 | 使用环境变量或 IAM 临时凭证,不硬编码在代码中 |
| 多可用区部署 | ECS 和 RDS 都跨可用区,保证高可用 |
| 敏感变量标记 | 密码等使用 sensitive = true,不在日志中明文显示 |
| SSH 限制来源 | 生产环境的 SSH 安全组应限制为管理 IP,而非 0.0.0.0/0 |
5.3 模块化建议
当资源变多时,建议将代码拆分为可复用的模块:
modules/
├── network/ # VPC, 子网, 安全组
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
├── compute/ # ECS, ELB
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── database/ # RDS
├── main.tf
├── variables.tf
└── outputs.tf
然后在根目录引用:
module "network" {
source = "./modules/network"
vpc_cidr = "192.168.0.0/16"
}
module "compute" {
source = "./modules/compute"
vpc_id = module.network.vpc_id
subnet_id = module.network.web_subnet_id
sg_id = module.network.web_sg_id
instance_count = 2
}
module "database" {
source = "./modules/database"
vpc_id = module.network.vpc_id
subnet_id = module.network.db_subnet_id
sg_id = module.network.db_sg_id
}
六、总结
通过 Terraform,我们用约 150 行代码就描述了一个包含 VPC、ECS、ELB、RDS 的完整 Web 应用基础架构。相比手动在控制台操作,IaC 的优势在于:
- 可重复:同一套代码可以在不同环境(dev/staging/prod)快速复制
- 可审计:所有变更都有 Git 记录,谁改了什么一目了然
- 可销毁:
terraform destroy一键清理所有资源,不留残渣 - 一致性:消除"雪花服务器"问题,所有环境配置完全一致
如果你刚开始接触 Terraform,建议从简单的单台 ECS 开始,逐步加上 VPC、ELB、RDS,在实践中理解每个资源块的含义。遇到问题可以查阅下方参考资料,也欢迎在评论区交流!
参考资料
- [华为云 Terraform Provider 官方文档]
- [Terraform 官方文档]
- 华为云 Terraform 用户指南
- 点赞
- 收藏
- 关注作者
评论(0)