Terraform基础设施即代码实战:多云资源编排与状态管理

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/

赞 (0)
小编小编
上一篇 2026年9月14日
下一篇 2026年9月14日

相关推荐

Terraform基础设施即代码实战:多云资源编排与状态管理方案

Terraform基础设施即代码(IaC)是现代DevOps体系的核心组件。通过声明式配置文件定义云资源,Terraform自动计算差异并执行变更,使基础设施管理具备版本控制、代码审查和自动化部署能力。相比手动在控制台创建资源,IaC消除了雪花服务器问题——每台服务器配置都有细微差异,难以复现和回滚。Terraform支持AWS、阿里云、腾讯云等数十个Provider,是多云环境资源管理的首选工具。

Terraform核心概念与Provider配置

Terraform使用HCL(HashiCorp Configuration Language)编写配置文件。一个Terraform项目由main.tf、variables.tf、outputs.tf等文件组成。Provider是Terraform与云平台之间的适配层,每个Provider封装了特定云平台的API调用。

# main.tf - Provider配置
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
    alicloud = {
      source  = "aliyun/alicloud"
      version = "~> 1.220"
    }
  }
  required_version = ">= 1.5"
}

provider "aws" {
  region     = var.aws_region
  access_key = var.aws_access_key
  secret_key = var.aws_secret_key
}

provider "alicloud" {
  region     = var.ali_region
  access_key = var.ali_access_key
  secret_key = var.ali_secret_key
}

Provider版本锁定通过version约束实现,~> 5.0表示允许5.x但不允许6.0。生产环境中必须锁定Provider版本,避免Provider升级引入不兼容变更导致apply失败。Provider凭据不应硬编码在配置文件中,通过variables或环境变量注入。

资源声明与变量管理模块化设计

Terraform通过resource块声明资源。资源之间的依赖关系通过depends_on显式声明或通过引用自动推断。变量通过variable块定义,支持string、list、map等类型,配合validation规则确保输入合法性。

# variables.tf
variable "vpc_cidr" {
  type    = string
  default = "10.0.0.0/16"
  validation {
    condition     = can(cidrhost(var.vpc_cidr, 0))
    error_message = "VPC CIDR格式不正确。"
  }
}

variable "subnet_cidrs" {
  type    = list(string)
  default = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
}

variable "tags" {
  type    = map(string)
  default = {
    Project   = "web-platform"
    ManagedBy = "terraform"
  }
}
# 网络资源声明
resource "alicloud_vpc" "main" {
  vpc_name   = "prod-vpc"
  cidr_block = var.vpc_cidr
  tags       = var.tags
}

resource "alicloud_vswitch" "subnets" {
  count        = length(var.subnet_cidrs)
  vpc_id       = alicloud_vpc.main.id
  cidr_block   = var.subnet_cidrs[count.index]
  zone_id      = data.alicloud_zones.available.zones[count.index].id
  vswitch_name = "subnet-${count.index + 1}"
}

# ECS实例
resource "alicloud_instance" "web" {
  count           = 3
  instance_type   = "ecs.g7.large"
  image_id        = "ubuntu_22_04_x64"
  vswitch_id      = alicloud_vswitch.subnets[count.index].id
  security_groups = [alicloud_security_group.web.id]
  tags = merge(var.tags, {
    Name = "web-server-${count.index + 1}"
  })
}

count和for_each是Terraform实现资源批量创建的两种方式。count适用于同构资源(如3台相同规格的ECS),for_each适用于异构资源(如不同规格的数据库实例)。选择哪种取决于资源之间的差异程度。

State状态文件管理与远程后端配置

Terraform State文件(terraform.tfstate)记录了当前基础设施的实际状态。每次apply后,Terraform对比配置文件与State文件的差异,仅执行变更部分。State文件包含敏感信息(如数据库密码、私钥),不应提交到Git仓库。生产环境必须使用远程后端存储State。

# backend配置 - 使用阿里云OSS
terraform {
  backend "oss" {
    bucket     = "terraform-state-prod"
    prefix     = "web-platform"
    key        = "terraform.tfstate"
    region     = "cn-beijing"
    encrypt    = true
    access_key = var.ali_access_key
    secret_key = var.ali_secret_key
  }
}

# 或使用S3后端(带State Locking)
terraform {
  backend "s3" {
    bucket         = "terraform-state-prod"
    key            = "web-platform/terraform.tfstate"
    region         = "us-east-1"
    encrypt        = true
    dynamodb_table = "terraform-locks"
  }
}

DynamoDB表用于实现State Locking,防止多人同时apply导致State冲突。表配置只需一个主键LockID(字符串类型)。远程后端的另一个优势是支持State隔离,不同环境(dev/staging/prod)使用不同的key或prefix,互不干扰。

# State操作常用命令
terraform state list                          # 列出所有资源
terraform state show alicloud_instance.web[0]  # 查看特定资源状态
terraform state pull                          # 拉取远程State到本地
terraform state mv alicloud_instance.web[0] alicloud_instance.web_server[0]  # 重命名资源
terraform state rm alicloud_instance.web[2]    # 从State中移除资源(不删除实际资源)
terraform import alicloud_instance.imported inst-xxx  # 导入已有资源到State

多环境工作区隔离与模块复用

Terraform Workspaces提供了一种轻量级环境隔离方案。同一套配置文件通过不同Workspace管理不同环境,State文件自动隔离。

# 创建并切换Workspace
terraform workspace new staging
terraform workspace new prod
terraform workspace select prod

# 在配置中引用当前Workspace
locals {
  env           = terraform.workspace
  instance_type = local.env == "prod" ? "ecs.g7.large" : "ecs.t6.medium"
}

resource "alicloud_instance" "app" {
  count         = local.env == "prod" ? 3 : 1
  instance_type = local.instance_type
}

对于复杂项目,推荐使用Module封装可复用的资源组合。Module是一个包含独立Terraform配置的目录,通过inputs/outputs接口与外部交互。

# modules/vpc/main.tf
variable "vpc_cidr"     { type = string }
variable "subnet_cidrs"  { type = list(string) }
variable "env"           { type = string }

resource "alicloud_vpc" "this" {
  cidr_block = var.vpc_cidr
  vpc_name   = "${var.env}-vpc"
}

output "vpc_id"     { value = alicloud_vpc.this.id }
output "subnet_ids" { value = alicloud_vswitch.this[*].id }

# 调用Module
module "prod_vpc" {
  source       = "./modules/vpc"
  vpc_cidr     = "10.1.0.0/16"
  subnet_cidrs = ["10.1.1.0/24", "10.1.2.0/24"]
  env          = "prod"
}

CI/CD流水线集成与变更审批流程

Terraform与CI/CD流水线集成实现基础设施自动化变更。标准流程分为plan和apply两个阶段,plan生成变更预览,apply执行实际变更。生产环境的apply需要人工审批。

# .github/workflows/terraform.yml
name: Terraform Pipeline

on:
  push:
    paths: ["terraform/**"]
    branches: [main]

jobs:
  plan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: "1.7.0"
      
      - name: Terraform Init
        run: terraform init
        working-directory: terraform/
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
      
      - name: Terraform Plan
        run: terraform plan -no-color -out=tfplan
        working-directory: terraform/
      
      - name: Upload Plan
        uses: actions/upload-artifact@v4
        with:
          name: tfplan
          path: terraform/tfplan

  apply:
    needs: plan
    runs-on: ubuntu-latest
    environment: production  # 需要审批者批准
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
      
      - name: Download Plan
        uses: actions/download-artifact@v4
        with:
          name: tfplan
          path: terraform/
      
      - name: Terraform Apply
        run: terraform apply -auto-approve tfplan
        working-directory: terraform/

GitHub Actions的environment: production配置会触发审批流程,只有指定的审批者批准后才会执行apply。terraform plan -out=tfplan将计划保存为二进制文件,apply时直接使用该文件,确保执行内容与预览内容完全一致,避免在plan和apply之间配置被篡改。对于敏感变量,通过GitHub Secrets注入,不写入代码仓库。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/terraform-ji-chu-she-shi-ji-dai-ma-shi-zhan-duo-yun-zi-yuan/

赞 (0)
小编小编
上一篇 2026年9月4日
下一篇 2026年9月4日

相关推荐

Terraform基础设施即代码实战:多云资源编排与状态管理方案

Terraform是HashiCorp开源的基础设施即代码工具,通过声明式配置文件管理云资源的生命周期。与传统手动控制台操作相比,Terraform支持版本控制、审计追踪和自动化流水线集成,在多云混合架构中保持一致的资源管理能力。本文从Terraform核心语法、状态文件管理到CI/CD集成,给出完整的生产环境部署方案。

Terraform核心配置语法与资源定义

Terraform使用HCL(HashiCorp Configuration Language)语法,以声明式方式描述目标基础设施状态。以下是一个包含VPC、子网和安全组的配置示例:

# main.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
  required_version = ">= 1.5"
}

provider "aws" {
  region = "ap-northeast-1"
}

resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  tags = {
    Name        = "production-vpc"
    Environment = "prod"
    ManagedBy   = "terraform"
  }
}

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]
  map_public_ip_on_launch = true
}

resource "aws_security_group" "web" {
  name        = "web-sg"
  description = "Allow HTTP and SSH"
  vpc_id      = aws_vpc.main.id

  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"]
  }
}

Terraform State状态管理与远程后端配置

State文件记录了Terraform管理的资源映射关系,是Terraform判断资源是否需要变更的依据。生产环境中必须将State存储在远程后端,避免本地文件丢失或多人操作冲突:

# backend.tf
terraform {
  backend "s3" {
    bucket         = "terraform-state-prod"
    key            = "infra/terraform.tfstate"
    region         = "ap-northeast-1"
    encrypt        = true
    dynamodb_table = "terraform-locks"
  }
}

S3后端配合DynamoDB实现状态锁定,防止多人同时执行Terraform导致状态冲突。对于团队协作场景,建议按环境分离State文件:

# 目录结构
# environments/
#   dev/     -> key = "dev/terraform.tfstate"
#   staging/ -> key = "staging/terraform.tfstate"
#   prod/    -> key = "prod/terraform.tfstate"
# modules/
#   vpc/  eks/  rds/

模块化配置与变量管理

# modules/eks/main.tf
variable "cluster_name" {
  type    = string
  default = "production-cluster"
}

variable "node_count" {
  type    = number
  default = 3
}

resource "aws_eks_cluster" "main" {
  name     = var.cluster_name
  role_arn = aws_iam_role.eks_cluster.arn
  version  = "1.28"
  vpc_config {
    subnet_ids = var.subnet_ids
  }
}

resource "aws_eks_node_group" "main" {
  cluster_name    = aws_eks_cluster.main.name
  node_group_name = "${var.cluster_name}-nodes"
  node_role_arn   = aws_iam_role.eks_nodes.arn
  subnet_ids      = var.subnet_ids
  scaling_config {
    desired_size = var.node_count
    max_size     = var.node_count + 2
    min_size     = 1
  }
}

output "cluster_endpoint" {
  value = aws_eks_cluster.main.endpoint
}

Terraform CI/CD流水线集成方案

# .gitlab-ci.yml
stages:
  - validate
  - plan
  - apply

terraform:validate:
  stage: validate
  image: hashicorp/terraform:1.5.7
  script:
    - terraform init -backend=false
    - terraform validate
    - terraform fmt -check -recursive

terraform:plan:
  stage: plan
  image: hashicorp/terraform:1.5.7
  script:
    - terraform init
    - terraform plan -out=tfplan -var-file="environments/$ENV/terraform.tfvars"
  artifacts:
    paths:
      - tfplan
    expire_in: 7 days

terraform:apply:
  stage: apply
  image: hashicorp/terraform:1.5.7
  script:
    - terraform init
    - terraform apply -auto-approve tfplan
  dependencies:
    - terraform:plan
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: manual

Terraform安全实践与资源漂移检测

资源漂移(Drift)是指基础设施被手动修改后与Terraform State不一致的情况。定期执行漂移检测可以发现未授权变更:

#!/bin/bash
# 漂移检测脚本
set -e
cd environments/$ENVIRONMENT
terraform init -input=false
terraform plan -detailed-exitcode -out=drift.tfplan
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
    echo "No drift detected"
elif [ $EXIT_CODE -eq 2 ]; then
    echo "Drift detected! Sending alert..."
    curl -X POST $WEBHOOK_URL       -H "Content-Type: application/json"       -d "{"text":"Terraform drift detected in $ENVIRONMENT"}"
else
    echo "Error during plan execution"
    exit 1
fi

Terraform通过声明式配置和状态管理,将基础设施变更纳入版本控制流程。在多云架构和合规审计场景中,Terraform的Plan-Apply工作流提供了变更预览和安全审批能力。配合CI/CD流水线,基础设施变更可以像代码提交一样经过Code Review和自动化测试,大幅降低人为操作风险。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/terraform-ji-chu-she-shi-ji-dai-ma-shi-zhan-duo-yun-zi-yuan/

赞 (0)
小编小编
上一篇 2026年9月4日
下一篇 2026年9月4日

相关推荐

Terraform基础设施即代码实战:多云资源编排与状态管理配置

Terraform是HashiCorp推出的基础设施即代码(IaC)工具,通过声明式配置文件定义云资源,实现基础设施的版本化管理和自动化部署。相比手动在控制台创建资源,Terraform支持多云环境统一编排、资源变更可审计、环境可复现,已成为DevOps和SRE实践中的标准工具。

Terraform核心概念与工作流程

Terraform的工作流程包含四个阶段:编写(Write)→ 计划(Plan)→ 应用(Apply)→ 销毁(Destroy)。核心概念包括Provider(云平台接口)、Resource(资源定义)、State(状态文件)、Module(可复用模块)。

# main.tf - 基础结构示例
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
  required_version = ">= 1.5"
}

provider "aws" {
  region = "ap-northeast-1"
}

# 定义一个EC2实例
resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"
  
  tags = {
    Name        = "web-server"
    Environment = "production"
  }
}

变量管理与多环境配置实践

生产实践中需要区分开发、测试、生产等不同环境。Terraform通过变量文件(terraform.tfvars)和workspace两种方式实现多环境管理。推荐使用独立的目录配合变量文件的方式,环境之间完全隔离:

# variables.tf - 变量声明
variable "environment" {
  type    = string
  default = "dev"
}

variable "instance_type" {
  type = map(string)
  default = {
    dev     = "t3.micro"
    staging = "t3.small"
    prod    = "t3.medium"
  }
}

variable "instance_count" {
  type = map(number)
  default = {
    dev     = 1
    staging = 2
    prod    = 3
  }
}

# dev.tfvars
environment = "dev"

# prod.tfvars
environment = "prod"

使用不同环境配置执行:

# 初始化
terraform init

# 开发环境
terraform plan -var-file="dev.tfvars"
terraform apply -var-file="dev.tfvars"

# 生产环境
terraform plan -var-file="prod.tfvars"
terraform apply -var-file="prod.tfvars"

远程状态后端配置与状态锁定

Terraform状态文件记录了当前基础设施的实际状态。本地状态文件存在安全风险和协作冲突,生产环境必须使用远程后端存储状态。S3+DynamoDB是AWS上的标准方案,S3存储状态文件,DynamoDB提供状态锁定防止并发操作冲突:

# backend.tf - 远程状态配置
terraform {
  backend "s3" {
    bucket         = "terraform-state-yunthe"
    key            = "infra/prod/terraform.tfstate"
    region         = "ap-northeast-1"
    encrypt        = true
    dynamodb_table = "terraform-locks"
  }
}

# 需要先手动创建S3桶和DynamoDB表
# S3桶开启版本控制,便于状态回滚
# DynamoDB表设置LockID主键

状态锁定机制确保同一时间只有一个Terraform进程能修改基础设施。当terraform apply执行时,先在DynamoDB中写入锁记录,操作完成后释放锁。如果多个工程师同时操作,后执行者会收到锁定错误并等待。

Module模块化设计与资源复用

当基础设施规模增长后,将资源配置封装为Module可以大幅提升复用性和可维护性。一个典型的VPC模块包含子网、路由表、Internet Gateway等资源:

# modules/vpc/main.tf

variable "cidr_block" {
  type    = string
  default = "10.0.0.0/16"
}

variable "environment" {
  type    = string
}

variable "availability_zones" {
  type    = list(string)
  default = ["ap-northeast-1a", "ap-northeast-1c"]
}

resource "aws_vpc" "main" {
  cidr_block           = var.cidr_block
  enable_dns_support   = true
  enable_dns_hostnames  = true
  
  tags = {
    Name        = "vpc-${var.environment}"
    Environment = var.environment
  }
}

resource "aws_subnet" "public" {
  count             = length(var.availability_zones)
  vpc_id            = aws_vpc.main.id
  cidr_block        = cidrsubnet(var.cidr_block, 8, count.index)
  availability_zone = var.availability_zones[count.index]
  
  tags = {
    Name = "subnet-public-${count.index}-${var.environment}"
  }
}

output "vpc_id" {
  value = aws_vpc.main.id
}

output "subnet_ids" {
  value = aws_subnet.public[*].id
}

在根配置中引用模块:

# main.tf - 引用模块
module "vpc_prod" {
  source             = "./modules/vpc"
  cidr_block          = "10.1.0.0/16"
  environment         = "prod"
  availability_zones  = ["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d"]
}

module "vpc_dev" {
  source     = "./modules/vpc"
  environment = "dev"
}

# 模块输出可以在其他资源中引用
resource "aws_instance" "app" {
  subnet_id  = module.vpc_prod.subnet_ids[0]
  # ...
}

资源导入与漂移检测

当存量基础设施需要纳入Terraform管理时,使用import命令将已有资源导入状态文件。Terraform 1.5+支持在配置文件中声明导入,替代命令行方式:

# 在配置文件中声明导入
import {
  to = aws_instance.existing
  id = "i-0123456789abcdef0"
}

resource "aws_instance.existing" {
  # 配置需要与实际资源匹配
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"
}

# 执行导入
terraform plan   # 检查配置与实际资源的差异
terraform apply  # 将资源纳入状态管理

漂移检测是Terraform的重要能力。当有人手动修改了云资源(如通过控制台改了安全组规则),运行terraform plan会显示配置与实际状态的差异。定期执行plan检查漂移并修复,是保障基础设施一致性的关键实践:

# CI/CD中的漂移检测脚本
#!/bin/bash
terraform init -input=false
PLAN_FILE=$(mktemp)
terraform plan -detailed-exitcode -out=$PLAN_FILE
EXIT_CODE=$?

if [ $EXIT_CODE -eq 0 ]; then
    echo "No drift detected"
elif [ $EXIT_CODE -eq 2 ]; then
    echo "Drift detected! Review the plan:"
    terraform show $PLAN_FILE
    # 发送告警通知
    exit 1
else
    echo "Plan failed"
    exit 1
fi

CI/CD集成与自动化流水线配置

将Terraform集成到CI/CD流水线中实现基础设施变更的自动化审批和部署。以GitHub Actions为例:

# .github/workflows/terraform.yml
name: Terraform Pipeline
on:
  push:
    paths: ["terraform/**"]
  pull_request:
    paths: ["terraform/**"]

jobs:
  terraform:
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: terraform
    steps:
      - uses: actions/checkout@v4
      
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-1
      
      - uses: hashicorp/setup-terraform@v3
      
      - name: Terraform Init
        run: terraform init -input=false
      
      - name: Terraform Format Check
        run: terraform fmt -check -recursive
      
      - name: Terraform Plan
        run: terraform plan -input=false -out=tfplan
        # PR中会自动显示plan结果
      
      - name: Terraform Apply
        if: github.ref == 'refs/heads/main'
        run: terraform apply -auto-approve tfplan

流水线中plan阶段自动执行并输出变更计划,apply阶段仅在合并到主分支时触发,确保所有变更经过Code Review后才会应用到生产环境。配合Terraform Cloud或Atlantis等工具,还可以在PR评论中直接执行plan和apply,进一步提升协作效率。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/terraform-ji-chu-she-shi-ji-dai-ma-shi-zhan-duo-yun-zi-yuan/

赞 (0)
小编小编
上一篇 2026年8月24日
下一篇 2026年8月24日

相关推荐

Terraform基础设施即代码实战:多云资源编排与状态管理

云原生架构下,基础设施配置从手动控制台操作转向代码化管理。Terraform 通过 HCL(HashiCorp Configuration Language)声明式语法描述云资源拓扑,支持 AWS、阿里云、腾讯云等数十家云厂商,配合状态文件实现资源 drift 检测和增量变更。本文从基础语法到生产级状态管理,给出 Terraform 多云编排完整实践。

Terraform HCL语法与Provider配置

Terraform 配置文件以 .tf 为后缀,核心结构包括 provider 声明、resource 定义和 variable 变量。以下是一个同时管理阿里云 ECS 和 AWS EC2 的多 Provider 配置:

# versions.tf - 版本约束
terraform {
  required_version = ">= 1.5.0"
  required_providers {
    alicloud = {
      source  = "aliyun/alicloud"
      version = "~> 1.220"
    }
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

# providers.tf - Provider 认证配置
provider "alicloud" {
  region     = "cn-hangzhou"
  access_key = var.aliyun_access_key
  secret_key = var.aliyun_secret_key
}

provider "aws" {
  region = "us-east-1"
  access_key = var.aws_access_key
  secret_key = var.aws_secret_key
}

# variables.tf - 变量定义
variable "aliyun_access_key" {
  type      = string
  sensitive = true
}

variable "aliyun_secret_key" {
  type      = string
  sensitive = true
}

variable "aws_access_key" {
  type      = string
  sensitive = true
}

variable "aws_secret_key" {
  type      = string
  sensitive = true
}

sensitive = true 标记敏感变量,在 plan 和 apply 输出中以明文掩码显示。生产环境中,密钥应通过环境变量或密钥管理服务(如 HashiCorp Vault、阿里云 KMS)注入,不应硬编码在配置文件中。

Resource资源定义与依赖管理

Terraform 通过 resource 块定义云资源,资源间的引用关系自动推导依赖图:

# main.tf - 阿里云资源
resource "alicloud_vpc" "main" {
  vpc_name   = "prod-vpc"
  cidr_block = "10.0.0.0/16"
}

resource "alicloud_vswitch" "web" {
  vpc_id     = alicloud_vpc.main.id
  cidr_block = "10.0.1.0/24"
  zone_id    = "cn-hangzhou-h"
}

resource "alicloud_security_group" "web" {
  name   = "web-sg"
  vpc_id = alicloud_vpc.main.id
}

resource "alicloud_security_group_rule" "allow_http" {
  type              = "ingress"
  ip_protocol       = "tcp"
  port_range        = "80/80"
  source_cidr_ip    = "0.0.0.0/0"
  security_group_id = alicloud_security_group.web.id
}

resource "alicloud_instance" "web" {
  instance_type   = "ecs.g6.large"
  image_id        = "aliyun_3_x64_20G_alibase_20240520.vhd"
  vswitch_id      = alicloud_vswitch.web.id
  security_groups = [alicloud_security_group.web.id]
  system_disk_size = 40
  system_disk_category = "cloud_essd"
  tags = {
    Environment = "production"
    Service     = "web"
  }
}

# AWS 资源 - 跨可用区高可用
resource "aws_instance" "bastion" {
  ami           = "ami-0c7217cdde57093c9"
  instance_type = "t3.micro"
  subnet_id     = aws_subnet.public.id

  tags = {
    Environment = "production"
    Role        = "bastion"
  }
}

Terraform 根据资源引用自动构建 DAG(有向无环图)确定创建顺序:VPC -> VSwitch -> Security Group -> Instance。depends_on 可显式声明依赖,用于无直接引用但有逻辑先后关系的场景:

resource "alicloud_instance" "web" {
  # ... 其他配置
  depends_on = [
    alicloud_security_group_rule.allow_http,
    alicloud_oss_bucket.app_data
  ]
}

Terraform State状态文件管理

状态文件(terraform.tfstate)记录当前基础设施的实际状态,Terraform 通过对比配置文件与状态文件计算变更计划。本地状态文件存在团队协作冲突和安全性问题,生产环境应使用远程后端存储:

# backend.tf - 远程状态存储
terraform {
  backend "oss" {
    bucket   = "terraform-state-prod"
    prefix   = "infra/"
    key      = "terraform.tfstate"
    region   = "cn-hangzhou"
    access_key = "LTAI5t..."
    secret_key = "..."
    encrypt  = true
  }
}

OSS 后端自动启用服务端加密,状态文件中的敏感数据(如数据库密码、私钥)在传输和存储时均加密。多团队协作时,使用 terraform workspace 隔离不同环境的状态:

# 创建并切换到 staging 工作空间
terraform workspace new staging
terraform workspace select staging

# 查看当前工作空间
terraform workspace show

# 在配置中引用工作空间名称
resource "alicloud_instance" "web" {
  instance_type = terraform.workspace == "production" ? "ecs.g6.large" : "ecs.g6.small"
  tags = {
    Environment = terraform.workspace
  }
}

状态锁定机制防止并发修改:当 terraform apply 执行时,后端自动在 OSS 中创建锁文件,其他尝试执行 apply 的操作会等待锁释放。若 apply 异常中断导致锁未释放,使用 terraform force-unlock 手动清除。

Module模块化与代码复用

将通用资源组合封装为 Module,提高配置复用性。以下是一个 Web 服务模块的结构:

# modules/web-server/variables.tf
variable "instance_count" {
  type    = number
  default = 2
}

variable "instance_type" {
  type    = string
  default = "ecs.g6.large"
}

variable "vswitch_id" {
  type = string
}

variable "security_group_id" {
  type = string
}

# modules/web-server/main.tf
resource "alicloud_instance" "web" {
  count           = var.instance_count
  instance_type   = var.instance_type
  image_id        = "aliyun_3_x64_20G_alibase_20240520.vhd"
  vswitch_id      = var.vswitch_id
  security_groups = [var.security_group_id]
  system_disk_size = 40
  tags = {
    Service = "web"
    Index   = count.index
  }
}

# modules/web-server/outputs.tf
output "instance_ids" {
  value = alicloud_instance.web[*].id
}

output "private_ips" {
  value = alicloud_instance.web[*].private_ip
}

在根配置中引用模块:

# 调用模块
module "web_prod" {
  source             = "./modules/web-server"
  instance_count     = 3
  instance_type      = "ecs.g6.xlarge"
  vswitch_id         = alicloud_vswitch.web.id
  security_group_id  = alicloud_security_group.web.id
}

# 引用模块输出
output "web_instance_ids" {
  value = module.web_prod.instance_ids
}

Terraform Plan审查与CI/CD集成

生产环境变更必须经过 plan 审查后再 apply。CI/CD 流水线集成示例:

# .gitlab-ci.yml
stages:
  - plan
  - apply

terraform_plan:
  stage: plan
  image: hashicorp/terraform:1.5
  script:
    - terraform init -backend-config="access_key=$ALIYUN_AK" -backend-config="secret_key=$ALIYUN_SK"
    - terraform plan -out=tfplan -var "aliyun_access_key=$ALIYUN_AK" -var "aliyun_secret_key=$ALIYUN_SK"
  artifacts:
    paths:
      - tfplan
    expire_in: 1 day

terraform_apply:
  stage: apply
  image: hashicorp/terraform:1.5
  script:
    - terraform init -backend-config="access_key=$ALIYUN_AK" -backend-config="secret_key=$ALIYUN_SK"
    - terraform apply -auto-approve tfplan
  only:
    - main
  when: manual

when: manual 要求人工触发 apply,确保 plan 结果审查通过后才执行变更。terraform plan -out=tfplan 将计划保存为二进制文件,apply 时直接使用该文件,避免配置在 plan 和 apply 之间被修改导致不一致。

状态漂移检测可通过定时执行 terraform plan -detailed-exitcode 实现:退出码 0 表示无变更,2 表示有漂移需修复,1 表示执行错误。结合告警系统,当退出码为 2 时通知运维团队介入处理。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/terraform-ji-chu-she-shi-ji-dai-ma-shi-zhan-duo-yun-zi-yuan/

赞 (0)
小编小编
上一篇 2026年8月24日
下一篇 2026年8月24日

相关推荐