こんにちは、最近Terraformデビューしました。 社内の人々がTerraformに苦しんでいたのをみてなんとなく敬遠していたのだけど、そうも言ってられなくデビューしたところうひょーーー!楽しい!!!ってなっている今日この頃。
lifecycleを動的に変更したい
そんなわけでTerraformを使い始め、すでに稼働しているサービスをテラフォーミングしはじめた。 サーバごとにresourceを定義するのだけど、同じような定義が多いのでモジュール化すると思う。 例えば以下のような感じ(説明に必要な最低限のものだけを書いている)。
❯ tree . ├── a.tf ├── b.tf └── modules └── base └── main.tf ❯ cat a.tf module "a" { source = "modules/base" -- snip -- } ❯ cat b.tf module "b" { source = "modules/base" -- snip -- } ❯ cat modules/base/main.tf resource "openstack_compute_instance_v2" "base" { -- snip -- lifecycle { ignore_changes = [key_pairs] } }
しかし、困ったことが起こった。 新たにc.tfを追加したいのだけど、このcサーバではSecurity Group(SG)をTerraformで管理したくない。 具体的には関門海峡を利用していて、SGが頻繁に変更される。 関門海峡でSGを追加しているときにTerraformを適用すると差分になってしまうのでこれをなんとかしたい。
dynamicを使う?
Terraformで差分として扱わないようにするためにlifecycleのignore_changesを指定すればよいのだけど、modules/base/main.tfにこの記述を追加するとa.tfやb.tfもSGが管理されなくなってしまう。 困った。
こういうときのためにdynamicが使えるのだが、なんとこのlifecycleにはdynamicは使えないのであった。
どうしたものか
overrideを使ってみた
解決策として、module/base/main.tfをコピーしてmodule/base_ignore_sg/main.tf を作れば良いと最初に考えた。 しかし、これだとbaseとbase_ignore_sgの2重管理になってめんどうだなっと思った。
そこでこれを解決するためにOverride Filesを使うことを考えた。 具体的には以下のような感じ
❯ tree . ├── c.tf └── modules ├── base │ └── main.tf └── base_ignore_sg ├── main.tf -> ../base/main.tf 👈 シンボリックリンク └── override.tf 👈 ❯ cat c.tf module "c" { source = "modules/base_ignore_sg" 👈 } ❯ cat modules/base_ignore_sg/override.tf resource "openstack_compute_instance_v2" "base" { lifecycle { ignore_changes = [key_pairs, security_groups] 👈 } }
override.tfを追加して、この中にlifecycle/ignore_changesを追加してこの中でsecurity_groupsを追加している。 main.tfはbaseのシンボリックリンクなので二重管理にならない。 めでたしめでたし。
おわりに
これでやりたかったことはできた。
のだけど、tflintを流すとなぜかterraform_deprecated_interpolationでエラーになってしまう。
何が原因か調べていないけど、terraform validateでエラーにならないのでtflintで --disable-rule=terraform_deprecated_interpolation
を指定することにした。
こんな感じで工夫してみたけど、もっといいやり方はあるのかな?