Terraform
IaC 入门。
Terraform
这一课你将能做到
- 用 Terraform 描述并创建 AWS 上的 VPC + EC2 + 安全组,一键拉起环境
- 理解
terraform plan、apply、destroy、state的核心工作流 - 用变量和模块管理复用 Terraform 代码,避免「复制粘贴式」配置
为什么要学
你在 AWS 控制台点点点创建了一台 EC2,队友问你「这台机器怎么配出来的」,你只能回「我点出来的」。两周后服务器被误删,你想重新创建一台一模一样的——忘了安全组规则、忘了子网配置、忘了绑了哪个 IAM Role。手动操作不可回溯、不可复现、不可版本化。
Terraform 的解决思路:把基础设施(服务器、网络、数据库、DNS)写成代码文件,存进 Git,任何人 terraform apply 一键创建完全一致的环境。这就是 Infrastructure as Code(IaC)。
人话:以前盖房子靠师傅手艺(点控制台),现在用 CAD 图纸(Terraform 文件)直接打印房子。图纸就是代码,改了能 review,能回滚,能复用。
先建立图像
Terraform 工作流:
编写 .tf 文件(描述目标状态)
│
terraform init ← 下载 provider(如 AWS 插件)
│
terraform plan ← 对比「当前状态」和「目标状态」,输出变更预览
│
terraform apply ← 执行变更(创建/修改/删除资源)
│
terraform destroy ← 清理所有 managed 资源
状态文件(terraform.tfstate)是什么?
Terraform 并不实时扫描云厂商(太慢了),而是维护一个本地状态文件,
记录「上次 apply 后有哪些资源、ID 是什么」。下次 plan 时,Terraform 对比:
.tf 文件描述的目标状态
vs
.tfstate 里的实际状态
vs
云厂商的真实状态(用于检测 drift)
计划出的变更 = 让真实状态趋近目标状态所需的操作。
跟着做
步骤 1:安装 Terraform 并初始化
# macOS
brew install terraform
# Linux
curl -fsSL https://get.opentofu.org/install-opentofu.sh | sh
# 或用 HashiCorp 官方包
terraform -v # 确认安装
步骤 2:写第一个 Terraform 文件——创建 VPC + EC2
创建目录 terraform-aws-ec2/,在里面写 main.tf:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "cn-north-1"
}
# 创建 VPC
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
tags = {
Name = "myapp-vpc"
}
}
# 创建公有子网
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "cn-north-1a"
map_public_ip_on_launch = true
tags = {
Name = "myapp-public"
}
}
# 互联网网关(让公有子网能访问公网)
resource "aws_internet_gateway" "gw" {
vpc_id = aws_vpc.main.id
}
# 路由表:把 0.0.0.0/0 指向 IGW
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.gw.id
}
}
# 关联路由表到子网
resource "aws_route_table_association" "public" {
subnet_id = aws_subnet.public.id
route_table_id = aws_route_table.public.id
}
# 安全组:只放行 22、80、443
resource "aws_security_group" "web" {
name = "web-sg"
description = "Allow HTTP HTTPS SSH"
vpc_id = aws_vpc.main.id
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
# 创建 EC2 实例
resource "aws_instance" "web" {
ami = "ami-0c1234567890abcdef" # 换成你的 Region 的最新 Amazon Linux AMI
instance_type = "t3.micro"
subnet_id = aws_subnet.public.id
vpc_security_group_ids = [aws_security_group.web.id]
key_name = "myapp-key" # 提前在 AWS 控制台创建好
tags = {
Name = "myapp-web"
}
# 用户数据:实例启动时自动安装 Docker
user_data = <<-EOF
#!/bin/bash
yum update -y
yum install -y docker
systemctl enable --now docker
usermod -aG docker ec2-user
EOF
}
# 输出实例 IP
output "instance_public_ip" {
value = aws_instance.web.public_ip
}