🎆

手を動かしてメリットを実感するTerragrunt入門3 〜Terragruntを使ってみよう! その2 〜

2024/12/04に公開

はじめに

こんにちは!e-dashのSREグループ所属のkohekoheです。
今回はe-dashのインフラ管理のツールとして新規導入したTerragruntというツールに関して紹介したいと思います。

Terragrunt入門の記事として3本の記事を投稿します。次の構成で紹介したいと思います。

1.Terragruntの概要とどういったメリットがあるのかを解説します
2.Terragruntを使ったハンズオン①(導入〜単一モジュールのプロビジョニング)
3.Terragruntを使ったハンズオン②(複数モジュールのプロビジョニング)【★本記事】

こちらはe-dash advent calendar 2024の4日目の記事です。

注意点

  • Terragruntに関して知らない・詳しくない人が対象読者です
  • Terraformの知識は一定ある前提で話を進めます
  • 本記事ではAWSを用いて解説します
  • 筆者はMac book(M3 Pro)にて動作確認しています

現状の確認

Terragrunt入門2が完了した状態で話を進めます。

  • ソースコードがこちらの状態となっている。
  • terragrunt run-all applyが実行されている状態
    • State管理用のS3バケットが作成されている
    • s3.tfにて指定されたS3バケットが作成されている

この状態からモジュールを追加し、依存するモジュールの管理方法を学んでいきます。

新規モジュールの追加

まずは特に依存関係なくDynamoDBのモジュールを追加していきます。以下が新規追加になるディレクトリ・ファイルです。

environments/
  develop/
    dynamodb/
      terragrunt.hcl
modules/
  dynamodb/
    dynamodb.tf
    variables.tf
environments/develop/dynamodb/terragrunt.hcl
include {
  path = find_in_parent_folders()
}

terraform {
  source = "../../../modules/${path_relative_to_include()}"
}
modules/dynamodb/dynamodb.tf
resource "aws_dynamodb_table" "sample_table" {
  name           = "SampleTable"
  read_capacity  = 1
  write_capacity = 1
  hash_key       = "ID"

  attribute {
    name = "ID"
    type = "S"
  }
}
modules/dynamodb/variables.tf
variable "variables" {}
variable "s3_bucket_name" {
  default = "not_set"
}

locals {
  variables = yamldecode(var.variables)

  app_name    = local.variables.app_name
  environment = local.variables.environment
}

terragrunt apply

では早速プロビジョニングしていきましょう。前回はterragrunt run-all applyを使いましたが、今回は新規追加のモジュールのみを実行するようにします。cd environments/develop/dynamodb && terragrunt applyを実行してみてください。途中で確認が入りますが、Yesを入力して進めてみてください。

実行が完了後、AWSのDynamoDBのコンソールにアクセスしましょう。SampleTableというテーブルが作成されているはずです。

依存するAWSリソース

最後に依存するAWSリソースを作成していきます。現状、S3モジュールとDynamoDBモジュールという2つのモジュールが作成されていますが、これらのStateファイルをは分離されています。S3のバケットをのぞいてみるとわかりますが、同じバケット内に複数のStateファイルが作成されています。この状態から、Stateを跨いで依存するような修正を加えたいと思います。

S3側の出力

S3のバケット名をDynamoDB側に渡せるようにしたいと思います。modules/s3/s3.tfに以下の記述を追加します。

modules/s3/s3.tf
resource "aws_s3_bucket" "sample_bucket" {
  bucket = "${local.app_name}-sample-${local.environment}"
}

+++ output "s3_bucket_name" {
+++   value = aws_s3_bucket.sample_bucket.bucket
+++ }

DynamoDB側で出力を受け取る

S3の出力を受け取れるように、environments/develop/dynamodb/terragrunt.hclに以下の記述を追加します。
このようにすることで、S3側のoutputをDynamoDB側にvariableとしてインジェクションすることができます。

environments/develop/dynamodb/terragrunt.hcl
include {
  path = find_in_parent_folders()
}

terraform {
  source = "../../../modules/${path_relative_to_include()}"
}

+++ dependency "s3" {
+++   config_path = "../s3"
+++ }

+++ inputs = {
+++   s3_bucket_name = dependency.s3.outputs.s3_bucket_name
+++ }

DynamoDB側のモジュールで出力された値を利用します。aws_dynamodb_table_itemを追加して、S3のバケット名をDynamoDBのテーブルにインサートします。

modules/dynamodb/dynamodb.tf
resource "aws_dynamodb_table" "sample_table" {
  name           = "SampleTable"
  read_capacity  = 1
  write_capacity = 1
  hash_key       = "ID"

  attribute {
    name = "ID"
    type = "S"
  }
}

+++ resource "aws_dynamodb_table_item" "sample_table_item" {
+++   table_name = aws_dynamodb_table.sample_table.name
+++   hash_key   = aws_dynamodb_table.sample_table.hash_key
+++ 
+++   item = <<ITEM
+++ {
+++   "ID": {"S": "1"},
+++   "NAME": {"S": "${var.s3_bucket_name}"}
+++ }
+++ ITEM
+++ }

terragrunt run-all applyの実行

今回は二つのモジュールにまたがる修正なので、cd environments/develop && terragrunt run-all applyを再度実行していきたいと思います(terragrunt applyをそれぞれのモジュールに実行してもOKです)

実行が完了すると、DynamoDBのSampleTableにレコードが1つ追加されます。AWSのコンソールで確認してみてください。

依存するモジュールの注意点

S3 -> DynamoDBという形で依存するモジュールの構築を行うことができるようになりました。hclファイルにdependencyを記載することでStateを跨いだ情報提供が可能になります。

ただし、注意点は相互依存は不可能ということです。S3 -> DynamoDBという依存状態がある中で、DynamoDB -> S3というdependencyは追加することができません。 モジュールの分割は慎重に行う必要があります。

クリーンナップ

最後に今回作成したリソースを削除しておきましょう。Terraform同様にdestroyコマンドがあります。cd environments/develop && terragrunt run-all destroyを実行することで今回作成したリソースを全て削除することができます。

おわりに

Terragrunt入門ということで3回にわたって記事を作成しました。Terragruntは便利だと思う反面、情報が少なかったり、断片的だったりするので体系立てて入門できる記事があるとよいかな、、と思い執筆いたしました。

サンプルソースコードはこちらに格納されていますので、よろしければ参考にしてください。

Discussion