1. 概要
この記事では、以下の内容を解説します。
dataブロックの役割とresourceブロックとの違いdataブロックの基本構文と値の参照方法(data.<TYPE>.<NAME>.<ATTR>)- よく使うdataソースのパターン(AMI・SSM Parameter Store・IAMポリシー)
depends_onが必要なケース- よくある間違いと対処法
dataブロック(データソース)は、Terraformが管理していない既存リソースや外部データを参照するための仕組みです。resourceがリソースを「作る」のに対し、dataはリソースを「参照する」だけで、何も作成・変更しません。
2. resourceとの違い
| 比較項目 | resource | data |
|---|---|---|
| AWSへの影響 | 作成・変更・削除する | 読み取るだけ(変更しない) |
| Stateへの記録 | ✅ 記録される | ❌ 記録されない |
| 参照方法 | <TYPE>.<NAME>.<ATTR> | data.<TYPE>.<NAME>.<ATTR> |
| 用途 | インフラを定義する | 既存リソースの情報を取得する |
# resourceブロック: 新しいS3バケットを作成する
resource "aws_s3_bucket" "my_bucket" {
bucket = "my-new-bucket"
}
# dataブロック: 既存のS3バケットを参照する(作成しない)
data "aws_s3_bucket" "existing" {
bucket = "already-existing-bucket"
}
3. 基本構文
data "<データソースタイプ>" "<名前>" {
# フィルター条件(タイプによって異なる)
<引数> = <値>
}
取得した値の参照方法:
data.<TYPE>.<NAME>.<ATTRIBUTE>
4. よく使うdataソースのパターン
AMI IDを動的に取得する(最重要パターン)
AMI IDは頻繁に更新されるため、ハードコードせずにdataブロックで動的に取得するのがベストプラクティスです。
terraform {
required_version = ">= 1.9"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
# Amazon Linux 2023の最新AMIを動的に取得
data "aws_ami" "amazon_linux_2023" {
most_recent = true
owners = ["amazon"] # Amazonが公開したAMIのみ
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux_2023.id # ← 動的に取得したID
instance_type = "t3.micro"
root_block_device {
volume_size = 20
volume_type = "gp3"
encrypted = true
}
tags = {
Name = "web"
Environment = "dev"
ManagedBy = "terraform"
}
}
SSM Parameter Storeから値を取得する
機密情報や共有設定をSSMパラメータストアに保存し、dataブロックで取得するパターンです。
# SSM Parameter Store からデータベースのエンドポイントを取得
data "aws_ssm_parameter" "db_endpoint" {
name = "/myapp/prod/db/endpoint"
}
data "aws_ssm_parameter" "db_password" {
name = "/myapp/prod/db/password"
with_decryption = true # SecureStringタイプのパラメータを復号して取得
}
resource "aws_instance" "app" {
ami = data.aws_ami.amazon_linux_2023.id
instance_type = "t3.micro"
user_data = <<-EOF
#!/bin/bash
echo "DB_ENDPOINT=${data.aws_ssm_parameter.db_endpoint.value}" >> /etc/app.conf
EOF
tags = {
Name = "app"
ManagedBy = "terraform"
}
}
IAMポリシードキュメントを生成する
aws_iam_policy_documentは、JSONを直接書かずにHCLでIAMポリシーを定義できるデータソースです。
# IAMポリシードキュメントをHCLで定義
data "aws_iam_policy_document" "s3_read" {
statement {
effect = "Allow"
actions = ["s3:GetObject", "s3:ListBucket"]
resources = [
"arn:aws:s3:::myapp-bucket",
"arn:aws:s3:::myapp-bucket/*"
]
}
statement {
effect = "Deny"
actions = ["s3:DeleteObject"]
resources = ["arn:aws:s3:::myapp-bucket/*"]
}
}
resource "aws_iam_policy" "s3_read" {
name = "s3-read-policy"
policy = data.aws_iam_policy_document.s3_read.json # JSON文字列として取得
}
既存のVPCとサブネットを参照する
Terraform管理外のVPCを使用するケースや、既存の共有VPCを参照するパターン。
# 既存のVPCをタグで検索
data "aws_vpc" "shared" {
filter {
name = "tag:Name"
values = ["shared-vpc"]
}
}
# 共有VPC内の特定のサブネットを取得
data "aws_subnets" "private" {
filter {
name = "vpc-id"
values = [data.aws_vpc.shared.id]
}
filter {
name = "tag:Tier"
values = ["private"]
}
}
resource "aws_instance" "app" {
ami = data.aws_ami.amazon_linux_2023.id
instance_type = "t3.micro"
subnet_id = data.aws_subnets.private.ids[0] # 取得したサブネットを使用
tags = {
Name = "app"
ManagedBy = "terraform"
}
}
5. depends_onが必要なケース
通常、dataブロックはplanフェーズで評価されます。しかし、同じapplyで作成したリソースに依存するdataブロックは、そのリソースが作成された後でないと正しく評価できません。
# ❌ apply直後のリソースをdataで参照するとplanで失敗する可能性がある
resource "aws_iam_role" "lambda" {
name = "lambda-role"
# ...
}
data "aws_iam_role" "lambda" {
name = "lambda-role"
# → planフェーズでlambda-roleがまだ存在しないとエラーになる
}
# ✅ 解決策1: 同じapplyで作ったリソースはresourceで直接参照する(dataは不要)
resource "aws_lambda_function" "main" {
role = aws_iam_role.lambda.arn # ← dataではなくresourceを参照
}
# ✅ 解決策2: 別applyで先にリソースを作成してからdataで参照する
# ✅ 解決策3: どうしてもdataが必要なら depends_on を設定する
data "aws_iam_role" "lambda" {
name = "lambda-role"
depends_on = [aws_iam_role.lambda] # リソース作成後に評価
}
6. よくある間違い
dataで取得した値の参照方法を間違える
# ❌ data. プレフィックスを忘れる
resource "aws_instance" "web" {
ami = aws_ami.amazon_linux_2023.id # Error: resourceとして探してしまう
}
# ✅ data. プレフィックスが必要
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux_2023.id
}
filterの条件が複数ヒットして失敗する
│ Error: Your query returned more than one result. Please try a more
│ specific search criteria, or use data.aws_amis to retrieve all AMIs.
# ❌ フィルターが広すぎて複数ヒット
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
# filterが足りない
}
# ✅ filterを絞り込む
data "aws_ami" "amazon_linux_2023" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"] # 具体的なパターンを指定
}
}
7. 関連記事
- resourceブロックの使い方 — dataの対となる「作成」のブロック
- depends_on — 明示的な依存関係の設定 — dataにdepends_onが必要なケース
- jsonencode / jsondecodeの使い方 — IAMポリシードキュメントのJSON変換
- data vs resource — 参照と作成の使い分け
- required_providers と provider — 設定方法
- locals(ローカル値)— DRYなコードを書く
8. まとめ
dataブロックは既存リソース・外部データを「参照するだけ」。Stateには記録されない- 参照方法は
data.<TYPE>.<NAME>.<ATTR>(resourceと違いdata.プレフィックスが必要) - 最重要パターン: AMI IDを
most_recent = trueで動的に取得する - SSM Parameter Storeからシークレットを取得、IAMポリシードキュメントをHCLで定義する用途に使う
- 同じapplyで作成するリソースを
dataで参照するのは避ける(直接resourceを参照する) - 「dataを使うべきかresourceを使うべきか」迷ったら → data vs resource — 参照と作成の使い分け
動作確認バージョン: Terraform >= 1.9 / AWS Provider ~> 5.0 対象リージョン: ap-northeast-1(東京) 公式ドキュメント: https://developer.hashicorp.com/terraform/language/data-sources