3. 基础设施即代码(IaC)入门:Terraform基础、Provider配置、资源声明、状态文件管理

在服务目录平台的环境晋级过程中,手动配置基础设施(服务器、网络、负载均衡、数据库)不仅效率低下,而且极易因人为操作导致配置漂移和环境不一致。基础设施即代码(IaC)正是解决这一痛点的核心方法论。本章将深入讲解 Terraform 这一业界主流的 IaC 工具,涵盖其核心概念、Provider 配置、资源声明语法以及至关重要的状态文件管理策略。

3.1 Terraform 核心概念与工作流

Terraform 由 HashiCorp 公司开发,采用声明式配置语言 HCL(HashiCorp Configuration Language)。用户只需描述“最终状态”,Terraform 会自动计算并执行达到该状态所需的操作步骤。其核心工作流遵循“写计划 -> 应用 -> 管理状态”的循环。

核心优势: 不可变基础设施、版本化环境、自动化编排、多云/混合云统一管理。
关键术语: 资源(Resource)是 Terraform 管理的最小单元(如一台云服务器、一个 DNS 记录);数据源(Data Source)用于查询外部已有资源的信息;模块(Module)是复用配置的容器。
Terraform 核心工作流 Terraform 核心工作流 编写 .tf 配置 声明资源与 Provider terraform init 初始化 Provider 插件 terraform plan 预览执行计划 terraform apply 执行变更并更新状态 terraform state / terraform.tfstate 状态文件管理、远程存储、锁定 核心循环 写 -> 初始化 -> 计划 -> 应用

3.2 Provider 配置:连接目标平台

Provider 是 Terraform 与目标基础设施(如 AWS、Azure、OpenStack、Kubernetes)交互的桥梁。每个 Provider 负责管理特定平台的 API 调用和资源生命周期。配置 Provider 时,需要指定版本、认证信息以及可选的区域/端点。

3.2.1 Provider 声明与版本约束

强烈建议在 required_providers 块中锁定 Provider 的版本范围,避免因 Provider 升级导致配置意外失效。

# versions.tf
terraform {
  required_version = ">= 1.5.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"   # 允许 5.x 版本内的更新
    }
    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = ">= 2.20.0, < 3.0.0"
    }
  }
}

# provider.tf
provider "aws" {
  region = "cn-north-1"
  # 认证信息通常通过环境变量 AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY 注入
}

provider "kubernetes" {
  config_path = "~/.kube/config"
}
安全警告: 切勿将 Access Key、Secret Key、密码等敏感信息硬编码在 .tf 文件中。应使用环境变量、Vault、AWS Secrets Manager 或 Terraform Cloud 的敏感变量功能。

3.2.2 多 Provider 与别名

在同一个配置中管理多个区域或多个集群时,需要使用 alias 创建 Provider 的多个实例。

# 定义两个 AWS Provider 实例
provider "aws" {
  region = "us-east-1"
  alias  = "east"
}

provider "aws" {
  region = "eu-west-1"
  alias  = "west"
}

# 在资源中通过 provider 参数指定使用哪个实例
resource "aws_instance" "web_east" {
  provider = aws.east
  ami      = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"
}

resource "aws_instance" "web_west" {
  provider = aws.west
  ami      = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"
}

3.3 资源声明:定义基础设施组件

资源是 Terraform 配置的核心。每个资源块定义一个基础设施对象及其期望的属性。资源之间可以通过 隐式依赖(通过引用属性)或 显式依赖(depends_on)建立关系。

3.3.1 资源语法与参数

# 声明一个 AWS EC2 实例
resource "aws_instance" "app_server" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.medium"

  tags = {
    Name        = "ServiceCatalog-AppServer"
    Environment = "production"
  }

  # 引用另一个资源的安全组 ID
  vpc_security_group_ids = [aws_security_group.app_sg.id]
}

# 声明一个安全组,app_server 隐式依赖于此资源
resource "aws_security_group" "app_sg" {
  name        = "app-server-sg"
  description = "Security group for app server"

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

3.3.2 资源依赖与执行顺序

Terraform 会自动分析资源间的引用关系来构建依赖图。当需要强制指定顺序时,使用 depends_on。

依赖类型 触发方式 示例 推荐场景
隐式依赖 通过 资源类型.名称.属性 引用 vpc_id = aws_vpc.main.id 绝大多数场景,Terraform 自动推导
显式依赖 使用 depends_on 参数 depends_on = [aws_iam_role_policy_attachment.example] 资源间无直接属性引用,但存在逻辑顺序
数据源依赖 通过 data.资源类型.名称.属性 引用 data.aws_subnet_ids.selected.ids 查询已有资源信息,不影响创建顺序

3.4 状态文件管理:基础设施的“真相源”

terraform.tfstate 文件是 Terraform 的核心资产。它记录了当前基础设施中所有被管理资源的元数据、属性值和依赖关系。Terraform 通过对比状态文件与配置文件的差异来决定执行哪些操作。

3.4.1 状态文件的重要性与风险

  • 映射关系: 将配置中的逻辑资源 ID(如 aws_instance.app_server)映射到云平台的实际资源 ID(如 i-0abcd1234efgh5678)。
  • 性能优化: 避免每次 plan 或 apply 都调用 API 列举所有资源。
  • 敏感数据: 状态文件可能包含密码、密钥、连接字符串等明文信息,必须严格保护。
  • 团队协作风险: 本地状态文件无法共享,多人同时操作会导致状态冲突和资源损坏。
黄金法则: 永远不要手动编辑 terraform.tfstate 文件。必须使用 terraform state 子命令进行状态操作。

3.4.2 远程状态存储与锁定

生产环境必须使用远程后端(Backend)存储状态文件,并启用状态锁定以防止并发操作。

# backend.tf - 使用 AWS S3 + DynamoDB 作为远程后端
terraform {
  backend "s3" {
    bucket         = "my-company-terraform-state"
    key            = "service-catalog/production/terraform.tfstate"
    region         = "cn-north-1"
    encrypt        = true
    dynamodb_table = "terraform-state-lock"  # 用于状态锁定
  }
}
后端类型 存储位置 锁定机制 适用场景
local 本地文件系统 无 个人学习、单机测试
s3 AWS S3 DynamoDB AWS 原生环境,团队协作
azurerm Azure Storage Account Azure Blob Lease Azure 原生环境
gcs Google Cloud Storage Cloud Storage Object Lock GCP 原生环境
consul HashiCorp Consul Consul Session 多数据中心、服务网格集成
terraform cloud Terraform Cloud/Enterprise 内置锁定 企业级协作、策略即代码

3.4.3 状态文件常用操作命令

# 列出当前状态中的所有资源
terraform state list

# 查看某个资源的详细状态
terraform state show aws_instance.app_server

# 将现有资源导入 Terraform 管理(避免重建)
terraform import aws_instance.app_server i-0abcd1234efgh5678

# 从状态中移除资源(不销毁实际资源)
terraform state rm aws_instance.app_server

# 移动资源在状态中的地址(重构配置时使用)
terraform state mv aws_instance.old_name aws_instance.new_name
远程状态文件架构 远程状态文件架构与协作 开发者 A terraform apply 开发者 B terraform plan CI/CD 流水线 自动 apply 远程状态后端 S3 / Azure Storage / GCS terraform.tfstate + 状态锁定表 (DynamoDB / Lease) 协作要点 1. 所有操作读写同一状态 2. 锁定防止并发冲突 3. 加密存储敏感数据

3.5 本章小结

  • IaC 核心: 用代码定义和管理基础设施,实现版本化、可审计、可复用的环境交付。
  • Provider 配置: 是 Terraform 与目标平台交互的驱动,必须指定来源、版本和认证方式;多环境多区域时使用 alias。
  • 资源声明: 使用 HCL 语法声明期望的基础设施对象;Terraform 自动处理依赖关系,必要时使用 depends_on 显式控制。
  • 状态文件管理: 状态文件是基础设施的“真相源”,必须使用远程后端存储并启用锁定;禁止手动编辑,通过 terraform state 子命令进行安全操作。
实践建议: 在服务目录平台项目中,建议将每个环境(dev/staging/prod)的状态文件放在独立的路径下(如 service-catalog/{environment}/terraform.tfstate),并使用不同的 DynamoDB 锁定表或前缀来隔离环境。