TerraformのData Sourceは、既に存在するリソースを読み取り、計画時に値を解決して他のリソース定義へ安全に渡すための仕組みです。新規作成(resource)と混同しがちですが、役割は明確に異なります。
本稿では、既存リソースの参照に絞って、使いどころ、落とし穴、設計上の注意を具体例とともに解説します。HashiCorp公式ドキュメントの安定機能を前提に、Associateレベルの出題傾向にも触れます。
Data Sourceはクラウド等の既存リソースを検索・取得するための読み取り専用ブロックです。計画時にプロバイダのAPIへ問い合わせ、取得したIDや属性値を他のresourceやmoduleへ渡せます。Data Source自体は何も作成・変更しません。
典型例として、既存VPCを探索して、そのIDを使い新規セキュリティグループを作成する流れがあります。これにより既存ネットワークを壊さず、追加リソースだけを管理下に置けます。
既存リソース参照の流れ(Data Source)
例:既存VPCを参照して新規セキュリティグループを作成(AWS)
provider "aws" {
region = "ap-northeast-1"
}
data "aws_vpc" "main" {
filter {
name = "tag:Name"
values = ["prod-main-vpc"]
}
}
resource "aws_security_group" "web" {
name = "web-sg"
description = "Web tier SG"
vpc_id = data.aws_vpc.main.id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
output "web_sg_id" {
value = aws_security_group.web.id
}既存リソースをTerraformで扱うには大きく3つのアプローチがあります。動的に探索する(data)、状態に取り込む(import)、固定値を変数で渡す(vars)。状況に応じて最適解は異なります。
運用上の安定性、誤参照リスク、将来的な保守容易性を観点に選びましょう。曖昧なフィルタでdataを使うくらいなら、厳密IDを変数で渡す方が安全なこともあります。
| アプローチ | 主目的 | 典型ユースケース | 注意点 |
|---|---|---|---|
| Data Source | 計画時に探索・参照 | タグからVPC/サブネット特定、最新AMIの取得 | フィルタが曖昧だと誤参照や計画エラー。結果の順序にも注意 |
| terraform import | 既存を状態管理に取り込む | 手作成RDSを管理下へ、古いSGを移管 | HCL定義は自分で用意。差分が大きいと初回planが重くなる |
| 変数にIDを渡す | 固定IDを明示指定 | 共有VPCのIDをplatformチームから配布 | 人手ミス検知が遅れる。ID変更時の追随が手作業になりやすい |
例:固定IDを変数で受け取り、新規リソースに適用
variable "vpc_id" {
type = string
}
resource "aws_security_group" "web" {
name = "web-sg"
vpc_id = var.vpc_id
}Data Sourceはplan段階で解決されます。参照が成立しない場合、apply前に計画自体が失敗します。これにより、誤った前提での作成を防げます。
依存は参照関係から暗黙的に導かれます。dataの結果をresourceが参照すれば、そのresourceはdataの後に評価されます。循環参照は構築できません。dataは既存を読むものなので、同じapplyで新規作成するresourceをdata経由で“再参照”する設計は避けてください。
例:data結果をfor_eachに渡す際の安定化
data "aws_subnets" "private" {
filter {
name = "tag:Tier"
values = ["private"]
}
}
locals {
private_ids_sorted = sort(data.aws_subnets.private.ids)
}
resource "aws_route_table_association" "private" {
for_each = toset(local.private_ids_sorted)
subnet_id = each.value
route_table_id = aws_route_table.private.id
}既存インフラが別ワークスペースや別リポジトリでTerraform管理されている場合は、data "terraform_remote_state"で公開されたoutputsを参照できます。これも新規作成せず“既存を読む”アプローチの一種です。
remote_stateは相手機のapply後に安定した出力があることが前提です。循環依存を避け、参照方向を一方向に保つのが設計のコツです。
例:VPCスタックの出力を参照してサブネットにタグ追加
data "terraform_remote_state" "vpc" {
backend = "s3"
config = {
bucket = "org-tfstate"
key = "network/prod-vpc.tfstate"
region = "ap-northeast-1"
}
}
resource "aws_ec2_tag" "extra" {
resource_id = data.terraform_remote_state.vpc.outputs.app_subnet_id
key = "ManagedBy"
value = "app-stack"
}Data Sourceでの誤参照は重大事故につながります。フィルタは一意になるように設計し、タグ命名規約をチームで統一してください。複数候補が返る可能性がある場合は、期待件数の検証や並び順の安定化を組み込みます。
一部のData Sourceは結果の配列順序がAPI依存で不安定です。sort関数で明示的に順序を固定すると、毎回のplan差分を抑えられます。
例:タグで一意に絞り込み、順序を固定して関連付け
data "aws_subnets" "app" {
filter {
name = "tag:App"
values = ["billing"]
}
filter {
name = "tag:Env"
values = ["prod"]
}
}
locals {
app_subnet_ids = sort(data.aws_subnets.app.ids)
}
resource "aws_security_group_rule" "egress_to_app" {
for_each = toset(local.app_subnet_ids)
security_group_id = aws_security_group.web.id
type = "egress"
from_port = 5432
to_port = 5432
protocol = "tcp"
cidr_blocks = [cidrsubnet("10.0.0.0/16", 8, index(local.app_subnet_ids, each.value))]
}Associateでは、dataとresourceの役割差、いつimportやremote_stateを使うか、といった設計選択が問われます。dataは作成しない、planで解決、参照で依存が決まる——この3点を短文で説明できるようにしておきましょう。
手元演習として、最新の公式AMIを参照してIDを出力するだけの構成を作ると、計画時解決やフィルタ記述の感覚が掴めます。
練習:最新のAmazon Linux 2 AMIを参照して出力
data "aws_ami" "al2" {
owners = ["137112412989"]
most_recent = true
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-gp2"]
}
}
output "al2_ami_id" {
value = data.aws_ami.al2.id
}Associate
問題 1
既存のVPCに新しいセキュリティグループを追加したい。既存VPCは別チームが管理しており、IDは環境によって異なる。最も安全で保守しやすいアプローチはどれか。
正解: A
既存VPCを壊さずに参照し、環境ごとの差異に追随するにはData Sourceで一意に探索するのが適切。importは管理責務を奪うため前提と異なる。ハードコードや手作業更新はミスと保守コストが高い。
Data Sourceはリソースを作成できますか?
いいえ。Data Sourceは読み取り専用で、既存リソースの属性を計画時に取得するだけです。作成・変更はresourceブロックが担います。
Data Sourceで参照が見つからない場合はどうなりますか?
plan段階でエラーになり、applyまで進みません。フィルタを一意にし、タグ命名規約や期待件数の検証を整備してください。
remote_stateと通常のData Sourceはどう使い分けますか?
既存がTerraformで管理され、そのoutputsが公開されているならremote_stateが堅牢です。そうでなければ、プロバイダ固有のData Sourceで直接API検索を行います。循環依存を避けるため、remote_stateの参照方向は一方向に保ちます。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
Terraform HCL 構文の基礎:Block / Attribute / Expression を正しく使い分ける
Terraform Associate で頻出の HCL 構文を、ブロック・属性・式の3視点で整理。実務で迷いがちな書き...
Terraform Authoring & Ops Pro: 上位資格の範囲と対策
上位レベルを想定したTerraformの設計・運用ドメインを整理し、実務で通用する対策を提示。モジュール設計、ステート運...
Terraform Providers の基本: プラグイン型アーキテクチャを正しく使いこなす
Associate レベルで押さえるべき Provider の基礎、インストール、バージョニング、認証、エイリアス運用を...
Terraform Resourceブロック徹底ガイド: 最小単位のリソース定義
Associateレベルで押さえるべきResourceブロックの構造、依存関係、メタ引数、ライフサイクル制御を実務目線で...
Terraform Data Source徹底理解:既存リソースの参照で壊さず足す
Terraform Associate向けに、Data Sourceを用いた既存リソース参照の基本、選択基準、評価順序、...