この記事について
記載しているのはすべてTerragruntの公式にある内容です。(役に立つか知りませんが、githubでsandboxを作りました。)
どう使うかではなく、どのように使えるのかに焦点を当てています。
Terragruntって何?
概要
Terragruntとは、Terraformのラッパーツールで公式にも出てきますがDRY(Don't Repeat Yourself)
を謳っています。
要するにterraformのめんどくさいことをこいつにやらせよう!
terragrunt.hcl
というファイルを扱います。terraformを触ったことある人なら大丈夫です。
terraformとのバージョン対応表なんかも公開されています。
Supported Terraform Versions.
terraformのようにコマンドを実行できる。terragrunt (apply | plan ....)
導入への不安
- Considerations for CI/CD Pipelinesで触れられているように一般的なケースに現在対応できていない。回避策はあるが、余計なトイルが発生する気が。
- Terraform Registryをモジュールとして利用する場合には問題ないが、プライベートGitリポジトリを利用する場合のガバナンスコストが未知。
- 既存のプロダクトに導入するにはメリットが少なすぎる。新規プロジェクトの方が導入する価値がある。
-
run-all ...
コマンドというのがあるがCI/CDの際にそれぞれの出力を取得したい場合、一工夫必要。
何ができる?
一例にすぎませんがTerragruntで実現できるDRYをいくつか記載します。
Backend
真っ先に紹介されています。terraformでバックエンドを構成するのは結構めんどくさいですよね。
ルートのterragrunt.hcl
に定義を加えるだけで子のバックエンドを構成する設定ができます。
バックエンドの実態がない場合(初回作成時)には自らそのバックエンドリソースを作成します。
以下のようなディレクトリ構造だとします。
stage
├── terragrunt.hcl <- こいつ
├── frontend-app
│ ├── main.tf
│ └── terragrunt.hcl
└── mysql
├── main.tf
└── terragrunt.hcl
ルートのterragrunt.hcl
が以下のように構成されていると、子にbackend.tf
を生成し、ディレクトリ構造と同じようにtfstateのパスを作ります。
(今回の例ではfrontend-app/terraform.tfstate
, mysql/terraform.tfstate
が生成されます。)
# stage/terragrunt.hcl
remote_state {
backend = "s3"
generate = {
path = "backend.tf"
if_exists = "overwrite_terragrunt"
}
config = {
bucket = "my-terraform-state"
key = "${path_relative_to_include()}/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "my-lock-table"
}
}
最終的なディレクトリ構造はこのようになります。
stage
├── terragrunt.hcl
├── frontend-app
│ ├── main.tf
│ ├── backend.tf
│ └── terragrunt.hcl
└── mysql
├── main.tf
├── backend.tf
└── terragrunt.hcl
Provider
terraformってプロバイダーの指定も面倒ですよね。
以下のように構成して、子にprovider.tf
を生成します。generate
ブロックは直感的なので特に説明はいらないですね。
# stage/terragrunt.hcl
generate "provider" {
path = "provider.tf"
if_exists = "overwrite_terragrunt"
contents = <<EOF
provider "aws" {
assume_role {
role_arn = "arn:aws:iam::0123456789:role/terragrunt"
}
}
EOF
}
CLI Arguments
varfile(.tfvars
)などいちいちコマンドに-var-file=path
と打つのは面倒です!
そこでTerragruntに自動でくっつけてもらいましょう。
指定のコマンド実行時に自動で引数を指定してくれます。
# terragrunt.hcl
terraform {
extra_arguments "common_vars" {
commands = ["plan", "apply"]
arguments = [
"-var-file=../../common.tfvars",
"-var-file=../region.tfvars"
]
}
}
個人的に紹介したい機能・コマンド
Before and After Hooks
実行前後にトリガーされるコマンドを指定できます。使い方によっては便利かも。
terraform {
before_hook "before_hook" {
commands = ["apply", "plan"]
execute = ["echo", "Running Terraform"]
}
after_hook "after_hook" {
commands = ["apply", "plan"]
execute = ["echo", "Finished running Terraform"]
run_on_error = true
}
}
graph-dependenciesコマンド
terragrunt graph-dependencies
を実行してモジュールの依存関係を表せます。
(terraform graph
やinframapのような感じ)
terragrunt graph-dependencies |dot -Tpng > graph.png
のようにできます。
サンプル:
dependencyブロック
概念的にはterraformのmoduleと同じ。
dependency "vpc" {
config_path = "../vpc"
}
inputs = {
vpc_id = dependency.vpc.outputs.vpc_id
}