使用 Terraform 在华为云上自动化部署 Web 应用基础架构(VPC + ECS + ELB + RDS)

举报
yd_212422989 发表于 2026/11/11 09:59:42 2026/11/11
【摘要】 使用 Terraform 在华为云上自动化部署 Web 应用基础架构(VPC + ECS + ELB + RDS) 前言作为基础设施即代码(IaC)的践行者,我一直在用 Terraform 管理华为云资源。本文将分享一个完整的实战案例:用 Terraform 一键部署一个包含 VPC、子网、安全组、ELB 负载均衡、ECS 服务器和 RDS 数据库的 Web 应用基础架构。无论你是刚接触 ...

使用 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,在实践中理解每个资源块的含义。遇到问题可以查阅下方参考资料,也欢迎在评论区交流!

参考资料

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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