この記事はフューチャー Advent Calendar 2019(2)の5日目の記事です。4日目の記事はKhdbbleさんのEbitenでImage操作 ~キャラクターを動かす~でした。筆者もゲームエンジンで遊びたくなりました。
はじめに
業務内で、Terraformのコードやissueを見ていると、「案外、知られていないのでは?」と思うような設定項目いくつかあることに気づきました。また、resource
ごとにそれらが作成される際の個数や挙動を変えたいことがしばしばあり、ちょうどそのような内容のissueをいくつか担当しました。
本記事では、そんなTerraformのかゆい所に手が届く(かもしれない)resource
のmeta-argumentについてまとめてみます。
意外と知られていないmeta-argumentたち
resource
のmeta-argumentとは、どんなリソースタイプにも使えて、そのリソースの動作を変更できる設定のことです。
resource
で設定できるmeta-argument
は以下の通りです。
depends_on
count
for_each
provider
lifecycle
provisioner
connection
ここでは、depends_on
, count
, lifecycle
を紹介します。
その他のmeta-argumentについては、こちらを参照してください。
depends_on
depends_on
は、resource
の依存関係を解決するmeta-argumentです。すべてのresource
ブロック内で利用可能です。「Terraformって、依存関係を自動的に見てくれるのでは?」と疑問に思われるかもしれませんが、参照関係がないresource
間で依存関係を設定したい場合に、depends_onを利用します。
以下はAWSでの例です。リファレンスのコードを抜粋しました。
resource "aws_iam_role_policy" "example" {
name = "example"
role = aws_iam_role.example.name
policy = jsonencode({
"Statement" = [{
# EC2がS3にアクセスするためのポリシー
"Action" = "s3:*",
"Effect" = "Allow",
}],
})
}
resource "aws_instance" "example" {
ami = "ami-a1b2c3d4"
instance_type = "t2.micro"
# aws_iam_instance_profile.exampleは定義済み
# Terraformが参照から依存関係を推測します
iam_instance_profile = aws_iam_instance_profile.example
# S3へのアクセスが必要になるので、aws_iam_role_policy.exampleが作成されていて欲しい
depends_on = [
aws_iam_role_policy.example,
]
}
便利なdepends_on
ですが、リファレンスに「最終手段(last resort)」と、強気な書き方がされている1ように、利用する際は注意が必要です。
依存関係の管理はできるだけTerraformに任せるべきであり、、開発者が依存関係を考えながらコードを書くのは好ましくありません。
どうしてもdepends_on
を利用する場合は、他の編集者に設定の意図が伝わるようにドキュメントやコメントを残し、depends_on
に設定する依存関係は最小限なるように心掛けましょう。
count
count
は数値を設定することで、設定されたリソースの個数を指定することができます。これもresource
ブロックで利用可能です。例えば、GCPのリソースの場合は以下に使います。
variable "count_standard" {
default = {
"prod" = 1
"dev" = 2
}
}
resource "google_compute_instance" "standard" {
name = "sample"
count = var.count_standard["${terraform.workspace}"]
machine_type = "n1-standard-1"
zone = "asia-northeast1-b"
boot_disk {
initialize_params {
image = "debian-cloud/debian-9"
}
}
...(以下略)...
}
この場合、prod
環境2では1つ、dev
環境では2つのGCEインスタンスが作成されます。
variable
のブロックを別ファイルに書き出すことで、リソースの個数を別のファイルで管理することもできます。
lifecycle
lifecycle
ではTerraformのリソース操作を変更できます。こちらも全てのresource
ブロック内で利用可能です。項目としては以下のようなものがあります。
create_before_destroy
prevent_destroy
ignore_changes
例えば、リソースによっては設定に変更があった場合、そのリソースを一度削除して再作成します。このとき、リソースの削除が再作成に先行してしまうと、もしそのリソースのへの参照を持ったリソースがある場合に名前解決ができなくなってしまいます。
そこでcreate_before_destroy
を用います。先に新しい設定を取り込んだリソースを作成し、参照を切り替えた後に古いリソースを削除することで、参照元が名前解決できるようになります。
また、ignore_changes
は特定の設定を無視するためのmeta-argumentです。
再作成の生じるリソースにおいて、設定を変更するたびに削除・作成が行われるのは、時間がかかることもあり、好ましくありません。そこで、ignore_changes
で例えば、Terraform管理外のラベル(タグ)の変更を実体に反映させないことで、無駄な再作成を防ぐことができます。
終わりに
resource
のmeta-argumentについて紹介させていただきました。筆者もTerraform歴がまだまだ浅いので、これからもTerraformの利用方法についても考えていければと思います。
-
https://www.terraform.io/docs/configuration/resources.html#depends_on-explicit-resource-dependencies ↩
-
Workspace機能を利用すると、同じコードを環境ごとに使い分けることができます ↩