Terraform是HashiCorp开源的基础设施即代码(IaC)工具,通过声明式配置文件管理云资源生命周期。从资源创建、修改到销毁,全部通过代码版本化管理,解决了手动控制台操作不可追溯、不可复现的问题。以下是在AWS和阿里云双云环境下的Terraform实战配置,覆盖资源编排、状态管理和CI/CD集成的完整流程。
Terraform核心概念与工作流
Terraform的工作流分四步:init初始化项目→plan预览变更→apply执行变更→destroy销毁资源。配置文件使用HCL(HashiCorp Configuration Language)语法,通过provider插件对接不同云平台。
核心概念:
Provider - 云平台插件(aws, alicloud, azurerm等)
Resource - 具体云资源(ecs_instance, db_instance, vpc等)
Data Source - 读取已有资源数据(不创建新资源)
Module - 可复用的资源组封装
State - 资源状态文件,记录当前基础设施的实际状态
Variable - 输入变量,参数化配置
Output - 输出值,供其他模块或外部引用
多云Provider配置与认证
以AWS和阿里云双云部署为例,配置main.tf:
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
alicloud = {
source = "aliyun/alicloud"
version = "~> 1.220"
}
}
backend "s3" {
bucket = "terraform-state-prod"
key = "multi-cloud/terraform.tfstate"
region = "ap-northeast-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
# AWS Provider
provider "aws" {
region = var.aws_region
default_tags {
tags = {
Project = "multi-cloud-app"
ManagedBy = "terraform"
}
}
}
# 阿里云Provider
provider "alicloud" {
region = var.ali_region
access_key = var.ali_access_key
secret_key = var.ali_secret_key
}
认证信息通过变量文件管理,不硬编码在配置中:
# variables.tf
variable "aws_region" {
default = "ap-northeast-1"
}
variable "ali_region" {
default = "cn-hangzhou"
}
variable "ali_access_key" {
type = string
sensitive = true
}
variable "ali_secret_key" {
type = string
sensitive = true
}
# terraform.tfvars(gitignore排除)
ali_access_key = "LTAIxxxxxxxx"
ali_secret_key = "xxxxxxxxxxxx"
VPC与ECS资源编排
创建AWS VPC、子网和EC2实例:
# AWS VPC
resource "aws_vpc" "main" {
cidr_block = "10.10.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "prod-vpc"
}
}
# 公有子网
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.10.1.0/24"
map_public_ip_on_launch = true
availability_zone = "ap-northeast-1a"
tags = {
Name = "prod-public-subnet"
}
}
# 安全组
resource "aws_security_group" "web" {
vpc_id = aws_vpc.main.id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["10.10.0.0/16"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
# EC2实例
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = "t3.medium"
subnet_id = aws_subnet.public.id
vpc_security_group_ids = [aws_security_group.web.id]
key_name = var.ssh_key_name
user_data = <<-EOF
#!/bin/bash
apt-get update
apt-get install -y nginx
systemctl enable nginx
systemctl start nginx
EOF
tags = {
Name = "web-server-1"
}
}
阿里云ECS资源编排
同步在阿里云创建对应资源:
# 阿里云VPC
resource "alicloud_vpc" "main" {
vpc_name = "prod-vpc"
cidr_block = "10.20.0.0/16"
}
# 交换机
resource "alicloud_vswitch" "main" {
vpc_id = alicloud_vpc.main.id
cidr_block = "10.20.1.0/24"
zone_id = "cn-hangzhou-i"
}
# 安全组
resource "alicloud_security_group" "web" {
vpc_id = alicloud_vpc.main.id
}
resource "alicloud_security_group_rule" "allow_https" {
type = "ingress"
ip_protocol = "tcp"
port_range = "443/443"
security_group_id = alicloud_security_group.web.id
cidr_ip = "0.0.0.0/0"
}
# ECS实例
resource "alicloud_instance" "web" {
instance_type = "ecs.g6.large"
image_id = "ubuntu_20_04_x64_20G_alibase_20240115.vhd"
vswitch_id = alicloud_vswitch.main.id
security_groups = [alicloud_security_group.web.id]
system_disk_category = "cloud_essd"
system_disk_size = 40
tags = {
Name = "web-server-ali"
}
}
Module封装与复用
将通用资源组合封装为Module,实现跨项目复用。目录结构:
modules/
web-server/
main.tf # 资源定义
variables.tf # 输入变量
outputs.tf # 输出值
main.tf # 根配置,调用Module
Module定义:
# modules/web-server/main.tf
resource "aws_instance" "web" {
count = var.instance_count
ami = var.ami_id
instance_type = var.instance_type
subnet_id = var.subnet_id
tags = merge(var.tags, {
Name = "${var.name_prefix}-${count.index + 1}"
})
}
# modules/web-server/variables.tf
variable "instance_count" { default = 1 }
variable "instance_type" { default = "t3.medium" }
variable "ami_id" { type = string }
variable "subnet_id" { type = string }
variable "name_prefix" { default = "web" }
variable "tags" { default = {} }
# modules/web-server/outputs.tf
output "instance_ids" {
value = aws_instance.web[*].id
}
output "private_ips" {
value = aws_instance.web[*].private_ip
}
根配置调用Module:
module "web_servers" {
source = "./modules/web-server"
instance_count = 3
instance_type = "t3.large"
ami_id = data.aws_ami.ubuntu.id
subnet_id = aws_subnet.public.id
name_prefix = "prod-web"
tags = {
Environment = "production"
}
}
State状态管理与远程后端
State文件是Terraform的核心,记录了资源的实际状态与配置的映射关系。多人协作时必须使用远程后端并开启状态锁:
# 使用S3后端 + DynamoDB锁
terraform {
backend "s3" {
bucket = "terraform-state-prod"
key = "infra/terraform.tfstate"
region = "ap-northeast-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
# 环境隔离:通过workspace区分
# dev环境
terraform workspace new dev
terraform workspace select dev
terraform apply -var-file="dev.tfvars"
# prod环境
terraform workspace select prod
terraform apply -var-file="prod.tfvars"
State文件操作命令:
# 查看当前state中的资源列表
terraform state list
# 查看特定资源详情
terraform state show aws_instance.web
# 将资源从state中移除(不销毁实际资源)
terraform state rm aws_instance.web
# 将现有资源导入terraform管理
terraform import aws_instance.web i-1234567890abcdef0
# 强制刷新state(资源被手动修改后同步)
terraform apply -refresh-only
CI/CD流水线集成Terraform
将Terraform集成到GitLab CI流水线,实现变更审批后自动执行:
# .gitlab-ci.yml
stages:
- validate
- plan
- apply
- destroy
variables:
TF_VERSION: "1.5.7"
terraform_validate:
stage: validate
image: hashicorp/terraform:$TF_VERSION
script:
- terraform init -backend=false
- terraform fmt -check -recursive
- terraform validate
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
terraform_plan:
stage: plan
image: hashicorp/terraform:$TF_VERSION
script:
- terraform init
- terraform plan -out=tfplan
artifacts:
paths:
- tfplan
rules:
- if: $CI_COMMIT_BRANCH == "main"
terraform_apply:
stage: apply
image: hashicorp/terraform:$TF_VERSION
script:
- terraform init
- terraform apply -auto-approve tfplan
rules:
- if: $CI_COMMIT_BRANCH == "main"
when: manual
apply阶段设为when: manual,要求人工确认后执行。plan阶段产出tfplan文件作为artifact,apply阶段直接使用该文件,确保执行内容与预览完全一致。
常见问题与最佳实践
资源被手动修改导致drift:定期执行terraform plan检测配置漂移,配合-refresh-only更新state。生产环境建议每天跑一次plan检查。
State文件冲突:确保开启状态锁(DynamoDB或Consul),禁止多人同时apply。大型项目按环境拆分state文件,每个环境独立管理。
敏感信息泄露:variables中标记sensitive: true,secret值从Vault或Secrets Manager动态读取,不存入tfvars文件。state文件中可能包含明文密码,后端必须开启加密。
资源删除风险:生产环境在provider配置中添加prevent_destroy生命周期策略:
resource "aws_db_instance" "main" {
# ...
lifecycle {
prevent_destroy = true
}
}
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/terraform-ji-chu-she-shi-ji-dai-ma-shi-zhan-duo-yun-zi-yuan/