terraform_data リソース — null_resourceの代替(1.4+)

1. 概要

  • terraform_dataリソースとは何か(Terraform 1.4以降)
  • null_resourceとの違い
  • inputtriggers_replaceの使い方
  • プロビジョナーとの組み合わせ
  • 実際のユースケース

terraform_dataはTerraform 1.4で導入された組み込みリソースです。null_resource(HashiCorp Null Providerが必要)の代替として、追加プロバイダー不要で任意のトリガーによるリソース更新を実現します。


2. terraform_data vs null_resource

比較terraform_datanull_resource
利用可能バージョンTerraform 1.4以降全バージョン
必要なプロバイダー不要(組み込み)hashicorp/nullが必要
input属性あり(stateに保存できる)なし
triggers_replaceありtriggers(同等)
推奨✅ 新規コードではこちら後方互換性のみ

3. 基本構文

resource "terraform_data" "名前" {
  # オプション: stateに保存する任意の値
  input = <任意の値>

  # オプション: 変化するとリソースが再作成される条件
  triggers_replace = <監視する値>
}

4. triggers_replace — 特定の変化で再実行する

triggers_replaceの値が変わるとterraform_dataリソースが再作成され、紐づくプロビジョナーが再実行されます。

terraform {
  required_version = ">= 1.9"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

variable "environment" {
  description = "環境名"
  type        = string
  default     = "dev"
}

variable "app_version" {
  description = "デプロイするアプリバージョン"
  type        = string
  default     = "1.0.0"
}

data "aws_ami" "amazon_linux_2023" {
  most_recent = true
  owners      = ["amazon"]
  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }
}

resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux_2023.id
  instance_type = "t3.micro"

  root_block_device {
    volume_size = 20
    volume_type = "gp3"
    encrypted   = true
  }

  tags = {
    Name        = "${var.environment}-web"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

# app_versionが変わるたびにデプロイスクリプトを再実行
resource "terraform_data" "deploy" {
  triggers_replace = {
    instance_id = aws_instance.web.id
    app_version = var.app_version
  }

  provisioner "remote-exec" {
    connection {
      type        = "ssh"
      host        = aws_instance.web.public_ip
      user        = "ec2-user"
      private_key = file("~/.ssh/id_rsa")
    }

    inline = [
      "cd /app && git pull",
      "systemctl restart app",
    ]
  }
}

5. input — 計算結果をstateに保存する

inputに値を設定すると、その値がoutput属性としてstateに保存され、他のリソースから参照できます。

locals {
  # 複雑な計算の結果
  server_config = {
    ami_id        = data.aws_ami.amazon_linux_2023.id
    instance_type = var.environment == "prd" ? "t3.medium" : "t3.micro"
    environment   = var.environment
  }
}

# 計算結果をstateに保存
resource "terraform_data" "server_config" {
  input = local.server_config
}

output "resolved_ami_id" {
  description = "使用するAMI ID"
  value       = terraform_data.server_config.output["ami_id"]
}

6. null_resourceからの移行

# 旧コード(null_resource)
# resource "null_resource" "deploy" {
#   triggers = {
#     version = var.app_version
#   }
#   provisioner "local-exec" {
#     command = "echo 'Deploying version ${var.app_version}'"
#   }
# }

# 新コード(terraform_data)
resource "terraform_data" "deploy" {
  triggers_replace = var.app_version

  provisioner "local-exec" {
    command = "echo 'Deploying version ${var.app_version}'"
  }
}

7. 関連記事


8. まとめ

  • terraform_dataはTerraform 1.4以降で使える組み込みリソース
  • null_resourceの代替として追加プロバイダー不要で利用できる
  • triggers_replaceの値が変わると再作成されプロビジョナーが再実行される
  • inputに値を保存すればoutput属性から他のリソースが参照できる
  • 新規コードではnull_resourceよりterraform_dataを使うことを推奨

動作確認バージョン: Terraform >= 1.4 公式ドキュメント: https://developer.hashicorp.com/terraform/language/resources/terraform-data