☁️ AWS迁移时,为何要学习Terraform而非仅使用AWS控制台?

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

##

🎯 本文涵盖内容

  • AWS专用迁移服务(MGN、DMS等)的局限性
  • 什么是Terraform,以及为何现在是学习它的时机
  • 供应商锁定(Vendor Lock-in)问题及退出策略
  • 通过实际Terraform代码示例声明AWS基础设施
  • 从迁移后的运营角度看Terraform的价值

📌 导言 / 背景

面临AWS迁移的组织,首先会寻找AWS Migration HubApplication 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"
}

执行此代码将:

  1. `terraform init` — 下载提供商插件
  2. `terraform plan` — 预先查看变更(实际应用前审查)
  3. `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)

Comments

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注