Terraform
特点
Terraform 是 HashiCorp 出品的 IaC 工具,支持多云平台(AWS、阿里云、GCP、Azure),通过 HCL(HashiCorp Configuration Language)声明式定义基础设施。
| 特性 | 说明 |
|---|---|
| 声明式 | 描述期望状态,Terraform 计算差异并执行 |
| 多云支持 | 3000+ Provider,覆盖主流云平台和 SaaS |
| 状态管理 | 通过 State 文件跟踪资源状态 |
| 执行计划 | plan 预览变更,确认后再 apply |
| 模块化 | Module 封装可复用的资源组合 |
核心工作流
基础配置
main.tf
# Provider 配置
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
# 远程状态存储
backend "s3" {
bucket = "my-terraform-state"
key = "production/terraform.tfstate"
region = "ap-southeast-1"
# 状态锁(防止并发修改)
dynamodb_table = "terraform-locks"
encrypt = true
}
}
provider "aws" {
region = var.region
}
资源定义
ec2.tf
# VPC
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
tags = { Name = "${var.project}-vpc" }
}
# 子网
resource "aws_subnet" "public" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = "10.0.${count.index + 1}.0/24"
availability_zone = data.aws_availability_zones.available.names[count.index]
tags = { Name = "${var.project}-public-${count.index + 1}" }
}
# 安全组
resource "aws_security_group" "web" {
name = "${var.project}-web-sg"
vpc_id = aws_vpc.main.id
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" {
count = var.instance_count
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_type
subnet_id = aws_subnet.public[count.index % 2].id
vpc_security_group_ids = [aws_security_group.web.id]
key_name = var.key_name
tags = {
Name = "${var.project}-web-${count.index + 1}"
Env = var.environment
}
}
变量和输出
variables.tf
variable "region" {
type = string
default = "ap-southeast-1"
}
variable "project" {
type = string
}
variable "environment" {
type = string
default = "production"
}
variable "instance_count" {
type = number
default = 2
}
variable "instance_type" {
type = string
default = "t3.medium"
}
outputs.tf
output "instance_ips" {
value = aws_instance.web[*].public_ip
}
output "vpc_id" {
value = aws_vpc.main.id
}
Module
modules/vpc/main.tf
variable "cidr" { type = string }
variable "name" { type = string }
resource "aws_vpc" "this" {
cidr_block = var.cidr
enable_dns_hostnames = true
tags = { Name = var.name }
}
output "vpc_id" { value = aws_vpc.this.id }
main.tf(调用 Module)
module "vpc" {
source = "./modules/vpc"
cidr = "10.0.0.0/16"
name = "production-vpc"
}
module "vpc_staging" {
source = "./modules/vpc"
cidr = "10.1.0.0/16"
name = "staging-vpc"
}
State 管理
State 文件安全
State 文件包含所有资源的敏感信息(密码、密钥等),不能提交到 Git。必须使用远程 Backend(S3 + DynamoDB 锁)存储,并开启加密。
# 查看资源状态
terraform state list
# 移除资源(不删除真实资源)
terraform state rm aws_instance.web[0]
# 导入已有资源到 State
terraform import aws_instance.web[0] i-1234567890abcdef0
常见面试问题
Q1: Terraform 和 Ansible 的区别?
答案:
| Terraform | Ansible | |
|---|---|---|
| 定位 | 基础设施编排(创建云资源) | 配置管理(安装软件/配置) |
| 模型 | 声明式 | 命令式 + 声明式 |
| 状态 | 有 State 文件 | 无状态 |
| 典型场景 | 创建 VPC、EC2、RDS | 安装 Nginx、部署应用 |
实践中经常组合使用:Terraform 创建基础设施 → Ansible 配置软件。
Q2: 如何管理多环境(dev/staging/production)?
答案:
推荐两种方式:
- Workspace:
terraform workspace new staging,同一套代码不同 State - 目录分离(推荐):
terraform/
├── modules/ # 共享模块
├── environments/
│ ├── dev/ # dev 环境配置
│ │ ├── main.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ └── production/