yamlencode / yamldecode 応用 — YAMLで設定管理する

1. 概要

  • yamlencode — TerraformのデータをYAML文字列に変換
  • yamldecode — YAML文字列をTerraformのデータに変換
  • YAMLファイルから設定を読み込む応用パターン
  • Kubernetesマニフェスト・ECSタスク定義での活用

2. yamlencode — TerraformデータをYAMLに変換

yamlencode(value)はTerraformのmap・list・スカラー値をYAML文字列に変換します。

# terraform consoleで確認
> yamlencode({"name" = "Alice", "age" = 30})
"age: 30\nname: Alice\n"

> yamlencode(["a", "b", "c"])
"- a\n- b\n- c\n"

> yamlencode({"servers" = [{"name" = "web", "port" = 80}]})
"servers:\n- name: web\n  port: 80\n"

3. yamldecode — YAML文字列をTerraformデータに変換

yamldecode(string)はYAML文字列をTerraformのmapやlistに変換します。

# terraform consoleで確認
> yamldecode("name: Alice\nage: 30\n")
{"age" = 30, "name" = "Alice"}

> yamldecode("- a\n- b\n- c\n")
["a", "b", "c"]

4. YAMLファイルから設定を読み込む

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"
}

設定ファイル(config.yaml):

services:
  - name: web
    instance_type: t3.micro
    disk_size: 20
    count: 2
  - name: api
    instance_type: t3.small
    disk_size: 30
    count: 3
  - name: worker
    instance_type: t3.medium
    disk_size: 50
    count: 1
locals {
  # YAMLファイルを読み込んでパース
  config   = yamldecode(file("${path.module}/config.yaml"))
  services = local.config.services
  # → [
  #   {name="web", instance_type="t3.micro", disk_size=20, count=2},
  #   {name="api", instance_type="t3.small", disk_size=30, count=3},
  #   {name="worker", instance_type="t3.medium", disk_size=50, count=1},
  # ]

  # サービス名→設定のmapに変換
  service_map = {
    for svc in local.services :
    svc.name => svc
  }
}

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

resource "aws_instance" "services" {
  for_each      = local.service_map
  count         = each.value.count  # ← 注意: for_eachとcountは同時使用不可
  ami           = data.aws_ami.amazon_linux_2023.id
  instance_type = each.value.instance_type

  root_block_device {
    volume_size = each.value.disk_size
    volume_type = "gp3"
    encrypted   = true
  }

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

注意: for_eachcountは同時に使用できません。countを使う場合はflattenfor_eachを組み合わせて展開するか、count単独でインデックス管理します。


5. yamlencode でKubernetesマニフェストを生成

locals {
  k8s_manifest = yamlencode({
    apiVersion = "apps/v1"
    kind       = "Deployment"
    metadata = {
      name      = "${var.environment}-web"
      namespace = var.environment
    }
    spec = {
      replicas = var.environment == "prd" ? 3 : 1
      selector = {
        matchLabels = {
          app = "web"
        }
      }
      template = {
        metadata = {
          labels = {
            app = "web"
          }
        }
        spec = {
          containers = [{
            name  = "web"
            image = "nginx:latest"
            ports = [{ containerPort = 80 }]
          }]
        }
      }
    }
  })
}

# AWS S3にマニフェストを保存する例
resource "aws_s3_object" "k8s_manifest" {
  bucket  = "${var.environment}-manifests"
  key     = "web-deployment.yaml"
  content = local.k8s_manifest

  tags = {
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

6. csvdecodeとの使い分け

比較csvdecodeyamldecode
フォーマットCSV(表形式)YAML(階層構造)
ネスト不可可能
型情報すべて文字列型保持(数値・bool・nullなど)
向いているデータフラットな一覧階層構造の設定

7. 関連記事


8. まとめ

  • yamlencode(value) — TerraformデータをYAML文字列に変換。Kubernetesマニフェスト生成に便利
  • yamldecode(str) — YAML文字列をTerraformデータに変換。型情報が保持される
  • file()と組み合わせてYAMLファイルから設定を読み込める
  • YAMLは階層構造が表現できる点でCSVより高機能

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