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)
小编小编
上一篇 23小时前
下一篇 23小时前

相关推荐

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)
小编小编
上一篇 23小时前
下一篇 23小时前

相关推荐