“AWS迁移工具是搬家公司。Terraform是房屋设计图。如果只是搬家,就请搬家公司。但如果搬家后还需要改造房屋并居住,那就另当别论了。”

##
🎯 本文涵盖内容
- AWS专用迁移服务(MGN、DMS等)的局限性
- 什么是Terraform,以及为何现在是学习它的时机
- 供应商锁定(Vendor Lock-in)问题及退出策略
- 通过实际Terraform代码示例声明AWS基础设施
- 从迁移后的运营角度看Terraform的价值
📌 导言 / 背景
面临AWS迁移的组织,首先会寻找AWS Migration Hub、Application Migration Service(MGN)、Database Migration Service(DMS)等AWS专用迁移服务。
这是一个完全可以理解的选择。因为这些工具是AWS亲自开发的,所以它们看起来最有效,官方文档也很丰富,并且似乎只需在AWS控制台中点击几下就能运行。
但是,请稍等,我们首先需要问一个问题:
“迁移完成后,您打算怎么做?”
迁移不是终点,而是起点。从本地环境迁移到AWS的那一刻并非结束,之后您还需要在AWS上运营、扩展基础设施多年,有时甚至可能需要再次迁移到其他云。
从这个角度来看,现在学习Terraform的原因就变得显而易见了。
🔍 仅靠AWS迁移服务不足的原因
AWS专用服务的优缺点
AWS提供的迁移工具就像“搬家卡车”。它们专门用于快速将物品搬到新家。
| 服务 | 作用 | 局限性 |
| MGN (Application Migration Service) | 原样复制服务器并转换为EC2 | 迁移完成后无作用 |
| DMS (Database Migration Service) | 将数据库迁移到AWS RDS/Aurora | 依赖于AWS数据库服务 |
| Migration Hub | 跟踪迁移进度 | 监控工具,无法管理基础设施 |
| SCT (Schema Conversion Tool) | 转换数据库模式 | 转换后的运营是另一个问题 |
这些工具的共同点是它们的“一次性”性质。它们仅针对从本地到AWS迁移这一特定事件进行了优化,不适用于迁移后的基础设施运营、变更管理或多环境(开发/测试/生产)配置。

🚨 真正的问题:通过点击创建的基础设施没有记录
许多组织通过在AWS控制台中点击来配置基础设施。创建VPC、子网、启动EC2、连接RDS…
但六个月后,会出现这样的情况:
- 👨💼 “这个VPC为什么是这样配置的?”
- 😰 “嗯… 负责迁移的同事离职了。”
- 👨💼 “我们能在测试环境也创建一个完全相同的环境吗?”
- 😰 “…恐怕得看着控制台一个一个重新创建了。”
- 开发团队:“请再创建一个测试环境。”
- 安全团队:“昨天有人更改了安全组规则,但我们不知道是谁,也不知道为什么。”
- 管理层:“成本急剧增加,但我们无法查明是哪个资源出了问题。”
- 灾难恢复负责人:“如果首尔区域发生故障,我们能在其他区域多快地重现相同的环境?”
这就是基于点击的基础设施管理的现实:无法重现、无法追踪、无法协作…
🧩 什么是Terraform
Terraform是HashiCorp创建的基础设施即代码(IaC)工具。简单来说,它是一种通过代码声明基础设施的方法。
与其在控制台中点击“创建一个EC2实例”,不如这样编写:
# main.tf — EC2实例声明
provider "aws" {
region = "ap-northeast-2" # 首尔区域
}
resource "aws_instance" "web_server" {
ami = "ami-0c9c942bd7bf113a2" # Amazon Linux 2023
instance_type = "t3.medium"
tags = {
Name = "web-server"
Environment = "production"
ManagedBy = "terraform"
}
}
将此文件提交到Git,并运行`terraform apply`,即可在AWS中创建EC2实例。
核心在于此文件会保留下来。谁创建的、有哪些设置、何时更改的——所有这些都以代码形式记录。
💡 迁移时学习Terraform的5个理由
1️⃣ 迁移 = 从头设计基础设施的机会
从本地环境迁移到AWS不仅仅是复制服务器。这是一个从头设计新基础设施的机会:VPC、子网、安全组、IAM、负载均衡器、数据库…
如果在此时使用Terraform进行设计,您将从一开始就拥有通过代码管理的基础设施。这可以省去以后将旧的控制台配置转换为代码的麻烦。
2️⃣ 多环境配置变得像复制粘贴一样简单
大多数组织都会独立运行开发(dev)、测试(staging)和生产(production)环境。如果通过控制台分别配置这些环境,将需要三倍的工作量,并且容易导致环境之间出现配置差异。
Terraform通过变量(Variables)和工作区(Workspace)清晰地分离了不同环境的配置:
# variables.tf — 定义环境特定变量
variable "environment" {
description = "배포 환경 (dev, staging, prod)"
type = string
}
variable "instance_type" {
description = "EC2 인스턴스 타입"
type = string
default = "t3.micro"
}
# terraform.tfvars (用于生产环境)
environment = "prod"
instance_type = "t3.large"
开发环境和生产环境仅变量值不同,基础设施结构本身由相同的代码管理。一致性得到保障。
3️⃣ 从一开始就防止供应商锁定(Vendor Lock-in)
如果只学习AWS迁移服务,您的团队将获得AWS控制台操作能力。但如果三年后,由于成本问题需要引入Azure或GCP的部分服务,或者考虑多云战略呢?
Terraform以相同的语法管理AWS、Azure、GCP、NCP等数百种云/服务。声明AWS EC2实例的方式与声明Azure VM的方式结构相同。您学到的思维方式可以直接通用。
# AWS EC2
resource "aws_instance" "web" { ... }
# Azure VM — 语法结构相同
resource "azurerm_virtual_machine" "web" { ... }
# GCP Compute Engine
resource "google_compute_instance" "web" { ... }
您可以培养不依赖于AWS的云无关(Cloud Agnostic)能力。
4️⃣ 变更历史记录保留在Git中,实现审计和协作
对于关注安全合规性的组织而言,基础设施变更历史记录是必不可少的。必须能够追踪“谁、何时、何事、为何”进行了更改。
控制台点击会记录在CloudTrail日志中,但将其追踪为人类可读的形式很困难。通过Git管理Terraform代码,可以实现基于PR(Pull Request)的基础设施变更流程。
# 基础设施变更工作流
git checkout -b feature/add-rds-replica
# 修改terraform代码
git commit -m "feat: RDS 읽기 복제본 추가 (트래픽 분산 목적)"
git push origin feature/add-rds-replica
# 创建PR → 团队评审 → 批准 → 合并 → terraform apply
现在,基础设施变更也成为代码审查的对象。
5️⃣ 迁移后运营自动化的必要基础
迁移完成后,真正的运营才开始。添加新服务、扩容/缩容、构建灾难恢复(DR)环境、为优化成本更改实例类型…
在由Terraform管理的环境中,所有这些操作只需修改一行代码并执行apply即可完成。而在基于控制台的环境中,则需要数十次点击并伴随着出错的风险。
💻 实践示例 — 使用Terraform配置基本的AWS网络
让我们用Terraform编写迁移时最先需要的VPC基本配置。
# vpc.tf — 迁移目标环境的网络基础配置
# 创建VPC
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "migration-vpc"
}
}
# 公有子网 (用于Web服务器、ALB)
resource "aws_subnet" "public" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = "10.0.${count.index}.0/24"
availability_zone = data.aws_availability_zones.available.names[count.index]
map_public_ip_on_launch = true
tags = {
Name = "public-subnet-${count.index + 1}"
Tier = "public"
}
}
# 私有子网 (用于DB、后端服务器)
resource "aws_subnet" "private" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = "10.0.${count.index + 10}.0/24"
availability_zone = data.aws_availability_zones.available.names[count.index]
tags = {
Name = "private-subnet-${count.index + 1}"
Tier = "private"
}
}
# 可用区数据源
data "aws_availability_zones" "available" {
state = "available"
}
执行此代码将:
- `terraform init` — 下载提供商插件
- `terraform plan` — 预先查看变更(实际应用前审查)
- `terraform apply` — 实际在AWS中创建基础设施
# terraform plan 输出示例
Plan: 5 to add, 0 to change, 0 to destroy.
# + aws_vpc.main
# + aws_subnet.public[0]
# + aws_subnet.public[1]
# + aws_subnet.private[0]
# + aws_subnet.private[1]
Terraform的巨大优势在于它能在`plan`阶段预先显示将创建/更改/删除什么。在控制台中,您只有在点击后才能知道结果。
⚠️ 注意事项 / 常见错误
❌ “等迁移完成后再引入Terraform就行了”
这是最常见的错误。将通过控制台配置的基础设施逆向转换为Terraform代码(`terraform import`)的过程非常繁琐且容易出错。从一开始就使用Terraform进行配置效率会高得多。
❌ 将状态文件(terraform.tfstate)保存在本地
Terraform将当前基础设施状态记录在`.tfstate`文件中。将此文件保存在本地会使团队协作变得不可能,并且在丢失时会造成大问题。使用S3 + DynamoDB进行远程后端配置是必不可少的。
# backend.tf — 将状态文件存储在S3中
terraform {
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "migration/terraform.tfstate"
region = "ap-northeast-2"
dynamodb_table = "terraform-state-lock" # 防止并发修改的锁
encrypt = true
}
}
❌ 在Terraform代码中硬编码AWS凭证
# 绝不能做
provider "aws" {
access_key = "AKIAIOSFODNN7EXAMPLE" # ❌ 危险
secret_key = "wJalrXUtnFEMI/K7MDENG" # ❌ 危险
}
请通过AWS CLI配置文件、环境变量或IAM角色进行认证。
✅ 总结 / 结束语
AWS迁移服务(MGN、DMS等)是搬家卡车。它们在搬运物品方面很有用,但在新家中生活需要不同的能力。
Terraform是管理新家的方法。
| 比较项 | 仅使用AWS迁移服务 | 基于Terraform的方法 |
| 迁移速度 | 快 | 有初始学习成本 |
| 后续运营 | 依赖控制台点击 | 通过代码自动化 |
| 环境可重现性 | 不稳定 | 可完美重现 |
| 供应商锁定 | 高 | 低 |
| 审计/追踪 | 有限 | 通过Git历史记录完全追踪 |
| 团队协作 | 困难 | 基于PR的协作 |
不要让迁移这个机会仅仅止步于“搬家”。如果将其视为从一开始就以正确方式将基础设施代码化的起点,那么后续的运营、安全和成本优化都将变得更加顺畅。
下一步学习方向:
- Terraform官方教程 (registry.terraform.io)
- 熟悉AWS Provider文档
- 使用Terragrunt管理大规模模块
- 将`terraform plan/apply`集成到CI/CD管道中 (GitHub Actions, GitLab CI)
发表回复