3. 基础设施即代码(IaC)入门:Terraform基础、Provider配置、资源声明、状态文件管理
在服务目录平台的环境晋级过程中,手动配置基础设施(服务器、网络、负载均衡、数据库)不仅效率低下,而且极易因人为操作导致配置漂移和环境不一致。基础设施即代码(IaC)正是解决这一痛点的核心方法论。本章将深入讲解 Terraform 这一业界主流的 IaC 工具,涵盖其核心概念、Provider 配置、资源声明语法以及至关重要的状态文件管理策略。
3.1 Terraform 核心概念与工作流
Terraform 由 HashiCorp 公司开发,采用声明式配置语言 HCL(HashiCorp Configuration Language)。用户只需描述“最终状态”,Terraform 会自动计算并执行达到该状态所需的操作步骤。其核心工作流遵循“写计划 -> 应用 -> 管理状态”的循环。
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"
}
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
3.5 本章小结
- IaC 核心: 用代码定义和管理基础设施,实现版本化、可审计、可复用的环境交付。
- Provider 配置: 是 Terraform 与目标平台交互的驱动,必须指定来源、版本和认证方式;多环境多区域时使用
alias。 - 资源声明: 使用 HCL 语法声明期望的基础设施对象;Terraform 自动处理依赖关系,必要时使用
depends_on显式控制。 - 状态文件管理: 状态文件是基础设施的“真相源”,必须使用远程后端存储并启用锁定;禁止手动编辑,通过
terraform state子命令进行安全操作。
service-catalog/{environment}/terraform.tfstate),并使用不同的 DynamoDB 锁定表或前缀来隔离环境。