Terraformのremote_state分割で起こりがちなエラーをCIで検知できるようにした
Terraformのプラクティスの一つに、stateを分割するというものがある。分割の粒度についてもいろいろあるが、分割することでライフサイクルや責務を分けたり、planの時間を短縮できる効果がある。しかし、state分割には一つ困ることがある。それが data "terraform_remote_state" である。
data "terraform_remote_state" を使うと他stateのoutputを参照し、利用することができる。例えば、別stateでネットワーク系のリソースを管理している際にvpc idやsubnet idなどを参照することは比較的多いだろう。しかし、このような別stateを参照する変更において、state Aとstate Bを同時に変更しないといけないような場合、いくつかの問題が生じることがある。
新しくコンポーネントを作る際、stateも他とは分離して新規作成する。そして、別コンポーネントから新規作成するstateを参照することがある。これらの変更を1つのPullRequestで行おうとすると、コード上は問題ないように見えるがplanやapplyはうまく動かない。これは参照先のremote stateがplan時にはまだ存在しないためである。
remote stateは既にあるが、参照したい値がoutputとして存在しないこともあるだろう。outputの追加と参照を1つのPullRequestで行おうとすると、コード上は問題ないように見えるがplanやapplyがうまく動かないことがある。 outputがない場合ダミーの値を使うことでplanを通すことはできるが、apply時にエラーになるケースもある。これはapply時にplanファイルを利用する場合にのみ発生する(はず)。ダミーの値を使ったりした場合、planファイルではダミーの値が使われてCIが見た目上は通過する。しかしapply時には正しい値ではないため失敗してしまう、というわけだ。

このような問題を避けるにはPullRequestを分け、依存先PRを先にapplyする必要がある。とはいえルールとして設定しても覚えていられないし、うっかりマージすることもある。できればCIで検知してPullRequestの分割を強制したい。ということでチェック機構を作った。
Terraformの静的検査ツールとしてはtflintやcheckovなどいくつかのものが利用できる。もちろんこれらのツールも使っているが、今回検証したいのはクロスディレクトリの整合性である。また、S3上のstateを参照したりもするため、tflintなどとは相性が悪いだろうと判断し、単独ツールとして実装した。
ツールは https://github.com/takaishi/tfstateref-lint として公開してある。remote state関係で困っている人はぜひ試してみてほしい。
筆者が所属する株式会社フライルではソフトウェアエンジニアを募集しています。
ソフトウェアエンジニア
ソフトウェアエンジニア(SRE/インフラ/プラットフォーム)