停止创建一切: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 配置的基石。

Back to Blog

相关文章

阅读更多 »

Terraform 数据源 (AWS)

Terraform 数据源是什么?Terraform 中的数据源是对现有资源的只读查找。Terraform 并不是创建新资源,而是查询…

第13天:Terraform 中的数据源

什么是 Data Sources?您可以使用 data sources 来获取现有 VPC、子网、AMI、security groups 等信息。hcl data 'data_source_type' 'dat...

第13天:Terraform 数据源

数据源 将数据源想象成一个电话簿,其中用户名和电话号码以键值对的形式通过 API 访问。不要将值硬编码……

AWS Terraform 生命周期规则

介绍 基础设施即代码(IaC)在您能够完全控制资源在更新、替换和删除过程中的行为时最为强大。Terr…