3. Provider 与资源管理:Provider 配置、资源与数据源、依赖关系
在 Terraform 工作流中,Provider 是连接 Terraform 与目标基础设施的桥梁,Resource 是声明式定义的具体云对象,Data Source 用于查询已有基础设施信息,而 depends_on 则显式控制资源创建顺序。本章将深入剖析这四者的配置方法与协作模式。
3.1 Provider 配置:声明与版本约束
Provider 是 Terraform 与云平台(AWS、Azure、阿里云等)或服务(Kubernetes、Helm、DNS 等)交互的插件。每个 Provider 都需要在 required_providers 块中声明,并指定来源与版本约束。
核心原则:始终锁定 Provider 主版本号,避免因 Provider 升级导致基础设施配置意外变更。
3.1.1 标准 Provider 声明模板
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0" # 允许 5.x 范围内的次版本升级
}
kubernetes = {
source = "hashicorp/kubernetes"
version = "~> 2.23"
}
}
}
# Provider 配置块
provider "aws" {
region = var.aws_region
# 认证信息通过环境变量 AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY 传入
}
provider "kubernetes" {
config_path = "~/.kube/config"
}
3.1.2 版本约束符号速查表
| 符号 | 含义 | 示例 | 允许版本范围 |
|---|---|---|---|
>= 1.0 |
大于等于 | version = ">= 1.0" |
1.0.0 及以上 |
~> 2.0 |
悲观约束(只允许最后一位增长) | version = "~> 2.0" |
2.0.0 ≤ x < 3.0.0 |
~> 2.3.0 |
悲观约束(锁定前两位) | version = "~> 2.3.0" |
2.3.0 ≤ x < 2.4.0 |
>= 1.0, < 2.0 |
范围组合 | version = ">= 1.0, < 2.0" |
1.0.0 ≤ x < 2.0.0 |
3.2 Resource(资源)与 Data Source(数据源)
Resource 是 Terraform 管理的核心对象——创建、更新、删除都由 Terraform 生命周期控制。Data Source 则用于读取外部已有资源的信息,不管理其生命周期。
3.2.1 资源定义与属性引用
# 创建 AWS EC2 实例(资源)
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
tags = {
Name = "web-server"
}
}
# 创建安全组(资源)
resource "aws_security_group" "web_sg" {
name = "web-sg"
description = "Allow HTTP/HTTPS traffic"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
3.2.2 数据源:查询已有基础设施
# 查询已有的 VPC(数据源)
data "aws_vpc" "default" {
default = true
}
# 查询可用区列表(数据源)
data "aws_availability_zones" "available" {
state = "available"
}
# 在资源中引用数据源属性
resource "aws_subnet" "main" {
vpc_id = data.aws_vpc.default.id
cidr_block = "10.0.1.0/24"
availability_zone = data.aws_availability_zones.available.names[0]
}
3.2.3 Resource 与 Data Source 对比
| 维度 | Resource(资源) | Data Source(数据源) |
|---|---|---|
| 生命周期管理 | 创建、更新、删除 | 只读查询,不管理生命周期 |
| 声明关键字 | resource |
data |
| 典型用途 | 创建 EC2、RDS、VPC 等 | 查询已有 VPC、AMI、可用区等 |
| 状态文件影响 | 写入状态文件 | 不写入状态文件(仅缓存结果) |
| 删除风险 | terraform destroy 会删除 |
不会删除任何资源 |
3.3 依赖关系与 depends_on
Terraform 通过分析资源之间的属性引用来自动推断隐式依赖。当资源 A 引用了资源 B 的某个属性(如 aws_instance.web.id)时,Terraform 会自动确保 B 先创建。但在某些场景下,隐式依赖无法覆盖所有顺序要求,此时需要 depends_on 显式声明。
3.3.1 隐式依赖 vs 显式依赖
# 隐式依赖:通过属性引用自动建立
resource "aws_eip" "web_eip" {
instance = aws_instance.web.id # 自动依赖 aws_instance.web
}
# 显式依赖:使用 depends_on 强制声明
resource "aws_s3_bucket" "logs" {
bucket = "app-logs-bucket"
}
resource "aws_s3_bucket_policy" "logs_policy" {
bucket = aws_s3_bucket.logs.id
policy = data.aws_iam_policy_document.logs_policy.json
# 显式依赖:确保 bucket 完全就绪后再应用策略
depends_on = [aws_s3_bucket.logs]
}
3.3.2 何时必须使用 depends_on
- 无属性引用的间接依赖:资源 A 需要资源 B 存在,但 A 的配置中不直接引用 B 的任何属性。
- 模块间的依赖:模块 A 的输出被模块 B 使用,但模块 B 内部资源未直接引用模块 A 的输出。
- Provisioner 执行顺序:本地执行(
local-exec)或远程执行(remote-exec)需要前置资源已就绪。 - 第三方 API 延迟:某些云服务创建后需要几秒才能被其他服务访问,
depends_on可配合time_sleep资源使用。
注意:过度使用
depends_on 会降低 Terraform 的并行执行效率。优先使用隐式依赖,仅在必要时添加显式依赖。
3.4 Provider、资源与数据源协作流程
下图展示了 Terraform 在执行 plan 和 apply 时,Provider、Resource、Data Source 与依赖关系的协作流程:
3.5 多 Provider 协作与别名
在同一个配置中使用多个同类型 Provider(如多个 AWS 区域)时,需要使用 alias 区分:
# 默认 Provider:us-east-1
provider "aws" {
region = "us-east-1"
}
# 别名 Provider:eu-west-1
provider "aws" {
alias = "west_eu"
region = "eu-west-1"
}
# 使用默认 Provider 创建资源
resource "aws_vpc" "primary" {
cidr_block = "10.0.0.0/16"
}
# 使用别名 Provider 创建资源
resource "aws_vpc" "secondary" {
provider = aws.west_eu
cidr_block = "10.1.0.0/16"
}
3.6 依赖关系最佳实践
- 优先隐式依赖:通过属性引用让 Terraform 自动推断,保持代码简洁。
- depends_on 用于模块边界:当模块 A 的输出被模块 B 使用时,在模块 B 的
depends_on中声明。 - 避免循环依赖:如果资源 A 依赖 B,B 又依赖 A,Terraform 会报错。此时需要重构资源设计。
- 使用
terraform graph可视化依赖:生成 DOT 格式的依赖图,便于调试复杂依赖关系。
调试技巧:执行
terraform graph | dot -Tpng > graph.png 可生成依赖关系图,直观查看资源创建顺序。
3.7 本章小结
| 概念 | 关键点 | 常用场景 |
|---|---|---|
| Provider | 声明来源、版本约束、认证配置 | 连接云平台、Kubernetes、DNS 等 |
| Resource | 管理基础设施对象的生命周期 | 创建 EC2、VPC、RDS、S3 等 |
| Data Source | 只读查询已有资源信息 | 获取 AMI ID、VPC ID、可用区列表 |
| depends_on | 显式声明无属性引用的依赖 | 模块间依赖、Provisioner 顺序、API 延迟 |