从手动到自动:用 Terraform 一键部署华为云 VPC + ECS 实战
# 从手动到自动:用 Terraform 一键部署华为云 VPC + ECS 实战
## 前言
如果你还在控制台里点点点,手动创建 VPC、子网、安全组、ECS……那你一定经历过这种痛:环境一多就分不清谁是谁,出了问题找不到当初怎么配的,换个账号又得重来一遍。
本文分享我用 Terraform 在华为云上从零搭建一套基础网络 + 云服务器环境的实战过程。不讲大道理,只讲实操中真正会遇到的问题和解决方式。
## 为什么选 Terraform?
一句话:**基础设施即代码(IaC),让环境变成可版本化、可复现的资产。**
- 声明式写法:你描述"我要什么",Terraform 负责怎么达到
- 状态管理:`terraform.tfstate` 记录当前基础设施的真实状态
- 可复用:同一份代码,改几个变量就能部署到不同区域、不同账号
- 团队协作:代码进 Git,每次变更都有 commit 记录
## 准备工作
### 1. 安装 Terraform
前往 Terraform 官方发布页下载对应平台的安装包(建议 1.7.x 版本),解压后将二进制文件移动到系统 PATH 路径下:
```bash
# Linux/Mac 示例
unzip terraform_1.7.5_linux_amd64.zip
sudo mv terraform /usr/local/bin/
terraform version # 验证安装
```
### 2. 配置华为云认证
推荐用环境变量,避免 AK/SK 硬编码进代码:
```bash
export HW_ACCESS_KEY="你的AK"
export HW_SECRET_KEY="你的SK"
export HW_REGION_NAME="cn-north-4" # 华北-北京四
export HW_PROJECT_ID="你的项目ID"
```
> **安全提醒**:千万别把 AK/SK 提交到 Git 仓库里。.gitignore 中务必加上 `*.tfvars` 和 `terraform.tfstate`。
## 实战:一份代码搭起整套环境
### 目录结构
```
huaweicloud-infra/
├── main.tf # 主配置:provider + 资源定义
├── variables.tf # 变量声明
├── outputs.tf # 输出有用的信息
└── terraform.tfvars # 变量赋值(不提交到 Git)
```
### main.tf —— 核心配置
```hcl
terraform {
required_providers {
huaweicloud = {
source = "huaweicloud/huaweicloud"
version = ">= 1.50.0"
}
}
}
provider "huaweicloud" {
region = var.region
}
# ========== 网络:VPC ==========
resource "huaweicloud_vpc" "main" {
name = var.vpc_name
cidr = "192.168.0.0/16"
}
# 子网
resource "huaweicloud_vpc_subnet" "web" {
name = "${var.vpc_name}-subnet-web"
vpc_id = huaweicloud_vpc.main.id
cidr = "192.168.0.0/24"
gateway_ip = "192.168.0.1"
}
# ========== 安全组 ==========
resource "huaweicloud_networking_secgroup" "web" {
name = "${var.vpc_name}-sg-web"
description = "Web 服务器安全组"
}
# 放行 SSH(仅限测试环境,生产建议用堡垒机)
resource "huaweicloud_networking_secgroup_rule" "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.id
}
# 放行 HTTP
resource "huaweicloud_networking_secgroup_rule" "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
}
# ========== 云服务器 ECS ==========
resource "huaweicloud_compute_instance" "web" {
name = "web-server-01"
image_id = var.image_id
flavor_id = "s6.large.2"
availability_zone = var.az
network {
uuid = huaweicloud_vpc_subnet.web.id
}
security_group_ids = [huaweicloud_networking_secgroup.web.id]
tags = {
Environment = "dev"
Team = "platform"
}
}
# ========== 弹性公网 IP ==========
resource "huaweicloud_vpc_eip" "web" {
publicip {
type = "5_bgp"
}
bandwidth {
name = "web-bandwidth"
size = 5
share_type = "PER"
charge_mode = "traffic"
}
}
# 将 EIP 绑定到 ECS
resource "huaweicloud_compute_eip_associate" "web" {
public_ip = huaweicloud_vpc_eip.web.address
instance_id = huaweicloud_compute_instance.web.id
}
```
### variables.tf —— 参数化
```hcl
variable "region" {
type = string
default = "cn-north-4"
}
variable "az" {
type = string
default = "cn-north-4a"
}
variable "vpc_name" {
type = string
default = "tf-demo-vpc"
}
variable "image_id" {
type = string
description = "ECS 镜像 ID,可通过控制台或 API 查询"
}
```
### outputs.tf —— 部署后输出关键信息
```hcl
output "ecs_public_ip" {
value = huaweicloud_vpc_eip.web.address
}
output "vpc_id" {
value = huaweicloud_vpc.main.id
}
output "subnet_id" {
value = huaweicloud_vpc_subnet.web.id
}
```
## 执行:四步搞定
```bash
# 第 1 步:初始化,下载 provider 插件
terraform init
# 第 2 步:检查格式和语法
terraform fmt
terraform validate
# 第 3 步:预览变更计划(重要!先看再执行)
terraform plan
# 第 4 步:正式部署(会要求输入 yes 确认)
terraform apply
```
执行 `terraform plan` 时你会看到类似这样的输出:
```
Plan: 8 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the following actions:
# huaweicloud_vpc.main will be created
# huaweicloud_vpc_subnet.web will be created
# huaweicloud_networking_secgroup.web will be created
...
```
**8 个资源,一条命令,几秒钟完成创建。** 这就是 IaC 的魅力。
## 实操中的三个踩坑点
### 坑一:state 文件冲突
多人协作时,如果大家都用本地 state,很容易互相覆盖。
**解法**:用 OBS 远程后端:
```hcl
terraform {
backend "local" {} # 改成远程后端
}
```
华为云目前可用 `http` 后端对接 OBS,或者用 S3 兼容接口。小团队本地 state 也够用,但记得加 `.gitignore`。
### 坑二:安全组规则重复创建
直接删除安全组资源时,关联的规则不会自动清理,再次 apply 会报规则已存在。
**解法**:安全组和规则分开定义为独立的 resource(就像上面代码那样),destroy 时会按依赖顺序自动清理。
### 坑三:ECS 创建失败 —— 镜像 ID 无效
不同区域的镜像 ID 不同,从 cn-north-4 拿的镜像 ID 拿到 cn-east-3 就用不了。
**解法**:用 `data` 数据源动态查询,而不是硬编码:
```hcl
data "huaweicloud_images_image" "ubuntu" {
name = "Ubuntu 22.04 server 64bit"
most_recent = true
}
resource "huaweicloud_compute_instance" "web" {
image_id = data.huaweicloud_images_image.ubuntu.id
# ...
}
```
## 销毁环境
测试完了,一条命令全部清理,不留垃圾:
```bash
terraform destroy
```
```
Plan: 0 to add, 0 to change, 8 to destroy.
```
**这比手动到控制台一个一个删快太多了,而且不会漏删导致持续计费。**
## 总结
| 对比项 | 手动控制台 | Terraform |
|--------|-----------|-----------|
| 部署速度 | 10-30 分钟 | 1-2 分钟 |
| 可复现性 | 靠记忆和文档 | 代码即文档 |
| 销毁清理 | 容易漏删 | 一条命令 |
| 变更追溯 | 无 | Git commit |
| 多环境部署 | 重复劳动 | 改变量即可 |
从手动到自动,不是一步到位的事。建议从一个小资源开始(比如先只管一个 ECS),熟悉了再逐步把 VPC、安全组、EIP 都纳入管理。
**基础设施不该是手动操作的产物,它应该是代码的产物。**
---
> 以上内容为原创实战经验分享,基于个人在华为云上的真实使用过程整理。如有问题欢迎评论区交流。
- 点赞
- 收藏
- 关注作者
评论(0)