停止创建一切:Terraform 数据源的艺术
发布: (2025年12月8日 GMT+8 08:09)
6 min read
原文: Dev.to
Source: Dev.to
介绍
这是 AWS 挑战的第 13 天,今天我学到了一件彻底改变我对基础设施即代码(IaC)看法的事:你不必管理所有东西。
到目前为止,我所有的 Terraform 实践都是在创建资源——VPC、子网、安全组等。在真实的组织中,多个团队拥有不同的基础设施片段。网络团队负责构建 VPC,安全团队管理安全组,而你的工作是将应用部署到这些已有的基础设施上。
这就是 数据源(data sources)发挥作用的地方,它们简直是颠覆性的。
资源 vs. 数据源
资源块
resource "aws_vpc" "my_vpc" {
cidr_block = "10.0.0.0/16"
# Terraform 创建、更新并销毁它
}
数据块
data "aws_vpc" "existing_vpc" {
filter {
name = "tag:Name"
values = ["shared-network-vpc"]
}
# Terraform 只读取它,从不触碰
}
区别很简单:
- 资源 – “我拥有它。我管理它的整个生命周期。”
- 数据源 – “它已经存在。我只需要引用它。”
影响是巨大的。
为什么这很重要:多团队现实
你的公司有:
- 一个管理所有 VPC 和子网的网络团队
- 一个维护安全组和 IAM 策略的安全团队
- 一个(就是你)负责部署应用的基础设施团队
没有数据源时
- 你需要访问每个人的 Terraform 状态文件(祝你好运)
- 你会手动复制粘贴 ID
- 可能会创建重复资源,导致冲突
使用数据源时
只需查询你需要的内容:
# 找到云网络团队创建的 VPC
data "aws_vpc" "company_vpc" {
filter {
name = "tag:ManagedBy"
values = ["cloud-networking-team"]
}
}
# 找到安全团队管理的安全组
data "aws_security_group" "approved_sg" {
filter {
name = "tag:ManagedBy"
values = ["security-team"]
}
}
# 使用他们的基础设施部署你的应用
resource "aws_instance" "my_app" {
ami = data.aws_ami.latest_amazon_linux.id
subnet_id = data.aws_subnet.app_subnet.id
vpc_security_group_ids = [data.aws_security_group.approved_sg.id]
}
结果:干净、协作且无冲突。
我的实操演示:三个必备数据源
环境搭建:模拟已有基础设施
# 这模拟了网络团队已经部署的内容
resource "aws_vpc" "shared" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "shared-network-vpc"
}
}
resource "aws_subnet" "shared" {
vpc_id = aws_vpc.shared.id
cidr_block = "10.0.1.0/24"
tags = {
Name = "shared-primary-subnet"
}
}
应用后,想象你“忘记”它的存在——这在大型组织中很常见。
数据源 #1:查找 VPC
data "aws_vpc" "shared" {
filter {
name = "tag:Name"
values = ["shared-network-vpc"]
}
}
它的作用
- 根据指定标签查询 AWS 中的 VPC
- 返回 VPC ID、CIDR 块以及所有其他属性
- 每次
terraform apply时都会刷新
控制台测试
terraform console
> data.aws_vpc.shared.id
"vpc-0a1b2c3d4e5f6"
> data.aws_vpc.shared.cidr_block
"10.0.0.0/16"
数据源 #2:查找子网(链式!)
data "aws_subnet" "shared" {
filter {
name = "tag:Name"
values = ["shared-primary-subnet"]
}
vpc_id = data.aws_vpc.shared.id # 使用 VPC 数据源
}
关键要点
- 数据源可以链式使用;一个为另一个提供输入
vpc_id缩小搜索范围,防止在多个子网共享同一标签时误匹配
数据源 #3:最新 AMI(动态的)
data "aws_ami" "amazon_linux_2" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-gp2"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
为何它很棒
most_recent = true始终获取最新匹配的 AMI- 通配符 (
*) 提供灵活的模式匹配 - 多个过滤器确保你得到恰好需要的镜像,实例会自动保持最新
综合示例:最终资源
resource "aws_instance" "main" {
ami = data.aws_ami.amazon_linux_2.id
instance_type = "t2.micro"
subnet_id = data.aws_subnet.shared.id
private_ip = "10.0.1.50"
tags = {
Name = "day13-instance"
}
}
运行 terraform plan 会得到:
Plan: 1 to add, 0 to change, 0 to destroy.
只创建了 一个 资源——EC2 实例。VPC 和子网仅被引用,并未被管理。
高级技巧:Terraform Console 测试
terraform console
# 测试 VPC 数据源
> data.aws_vpc.shared.id
"vpc-0a1b2c3d4e5f6"
# 测试子网数据源
> data.aws_subnet.shared.cidr_block
"10.0.1.0/24"
# 测试 AMI 数据源
> data.aws_ami.amazon_linux_2.name
"amzn2-ami-hvm-2.0.20231218.0-x86_64-gp2"
在实际部署前使用控制台验证过滤条件和返回值。
常用数据源(你真的会用到的)
网络资源
# VPC 查询
data "aws_vpc" "main" { ... }
# 子网查询
data "aws_subnet" "main" { ... }
# 安全组查询
data "aws_security_group" "main" { ... }
# 当前区域所有可用可用区
data "aws_availability_zones" "available" {
state = "available"
}
计算资源
# 最新 AMI(超级常用)
data "aws_ami" "latest" { ... }
# 已存在的 EC2 实例
# data "aws_instance" "existing" { ... }
这些数据源构成了任何需要与已有云资源交互的 Terraform 配置的基石。