結論
去年はじめてTerraformを使ってからあまり違いを理解せずにいましたが、現在は
resourceはあるリソースを作成する、moduleは複数のresourceを組み合わせてテンプレート化したものという感じで理解しました。moduleを使うと複数のリソースを簡単に作れるイメージです。
以降では、30日後にglacier deep archiveへオブジェクトを移行するライフサイクルルールを持つS3バケットをTerraformで作る例をあげながら、moduleとresourceの違いについて説明していこうと思います。
resourceとは
resourceを使う場合、ライフサイクルルールを適用したS3を作成するには以下のようなコードになります。
# S3バケット作成
resource "aws_s3_bucket" "example_bucket" {
bucket = "example-bucket-123"
}
# ライフサイクルルールの設定 (30日後にglacier deep archiveに移行)
resource "aws_s3_bucket_lifecycle_configuration" "example_lifecycle" {
bucket = aws_s3_bucket.example_bucket.id
rule {
id = "move-to-deep-archive"
status = "Enabled"
transition {
days = 30
storage_class = "DEEP_ARCHIVE"
}
}
}
まずはaws_s3_bucketでバケット名を指定し、S3を作成します。
その後、aws_s3_bucket_lifecycle_configurationにてライフサイクルルールを作成し、それをどのS3バケットに適用するかどうかを最初のbucketで指定しています。
このように、S3バケット本体やそれに適用する設定をそれぞれ記述する必要があります。そのため、ライフサイクルルール以外にもバケットポリシーやイベント通知など、作成したいものが増えれば増えるほど書かなければいけないresourceの数が増えていきます。
一方で、どのリソースをどのように作成し、どれに適用したかを自分で考えながら書くことができるので間違いは起きにくい印象があります。
設定値のデフォルト値などを確認したい場合はresourceのドキュメントを見る必要があります。
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket
moduleとは
moduleを使う場合、ライフサイクルルールを適用したS3を作成するには以下のようなコードになります。
# S3バケットのモジュールの呼び出し
module "s3_bucket" {
source = "terraform-aws-modules/s3-bucket/aws"
version = "4.1.2"
bucket = "example-bucket-123"
lifecycle_rules = [{
id = "move-to-deep-archive"
enabled = true
transition = [{
days = 30
storage_class = "DEEP_ARCHIVE"
}]
}]
}
ここではterraform-aws-modules/s3-bucket/awsというモジュールを使ってS3バケットを作成しています。
https://registry.terraform.io/modules/terraform-aws-modules/s3-bucket/aws/latest
resourceを使った時と比べて、1つのmodule内でS3バケットの作成もライフサイクルルールの作成も完結しています。
実はmoduleは複数のresourceをまとめたものであり、moduleを呼び出す際に関数と同じように引数を渡してあげれば包括しているresourceを一気に作ってくれるようになっています。
例として、今回使ったモジュールのコードを見てみるとライフサイクルルールの作成は内部でresourceのaws_s3_bucket_lifecycle_configurationを呼び出しています。
https://github.com/terraform-aws-modules/terraform-aws-s3-bucket/blob/master/main.tf#L240
moduleはresourceと違いシンプルにリソースを作成することができるというメリットがある一方、module側が自動的にいくつかのresourceを作成するため、
-
module内部での設定が原因でエラーが発生した場合、どのresourceで問題が起きたか特定するのに時間がかかる -
moduleが内部でどのresourceを作成するかを完全に把握するのが難しい場合がある
といったデメリットがある印象です。
まとめ
resource, moduleそれぞれメリット/デメリットがあるので場合によって上手に使い分けていきたいなと思いました。
最初にTerraformを触った時、このresourceとmoduleの違いがよくわからず、プロパティの調べ方に困った過去があるのでどなたかのご助力になるといいなと思います。