生産性のない時間 is プライスレス

スクラップ:Terraformの適切なモジュール分割についてのまとめ

公開日時:

あとがき

なぜあとがきが先なのか。それは私のこの思考はすべて先駆者の方たちが大体書いていてくれてたことを後から知ったからです。

というわけで以下の各種記事がとてもおすすめなのでぜひ読んでみてください!

概要

Terraformのモジュール分割をするときに、以下の5点を主に考えています。

SOLID原則などで例えようと思ったが、なんだか色々難しくてあえてやめました。

筆者のモジュール化に対する考え方

必要な差分を開放し、必要でない差分が本番環境・検証環境・開発環境などで発生しないことを技術的に保証する活動

環境によって差分が発生するものを変数とする。

こちらが基本になります。

原則筆者はマルチルート方式によるstate管理をしています。 マルチルート方式とは以下のような感じです。

├ modules
└ environments
  ├ production
  ├ staging
  └ base

というわけで必然的にモジュールはそれらから利用できるものでないといけません。

環境によって差分が発生するものとして、例えばEC2ならインスタンス名あたりでしょうか。 コスト面などでインスタンスタイプを検証環境では抑えたい場合などはインスタンスタイプも対象になります。

環境によって差分が発生しないものはモジュール内に隠ぺいする。

『環境によって差分が発生するものを変数とする。』と対応している内容です。

組織におけるプログラミングにおいて、可読性を高める・モジュールの利用者の負担を減らすというのが大事になってきます。

簡単に言うとモジュール内部は下手にいじるとインフラが壊れる可能性があるもの、 下手に触られると動作の保証ができないものをモジュール内に押し込めましょう。

カプセル化の話と似ているかもしれません。(というかそのものかも)

同時生成/破壊される単位でまとめる。

基本的にモジュールは同時に生成と破壊が行われるものでまとめておきましょう。

極論今後設計レベルでの変更が入る可能性が低ければ一つのモジュールにすべての生成内容を詰め込んでもいいです。

とはいうもののIaCはコードそのものが実在のインフラに対応しているので未来を考えたくなるのはわかります。

これに関して良い方法は思いついていないですが、 今のところは設計変更が入ったときは躊躇なくterraform stateコマンドを用いた リソースの対応関係の整備をするのがなんだかんだで真っ当だと考えています。

逆に言えば、変数でモジュール内部のリソースを生成するかしないかを設計するのは基本やめたほうがいいと思います。 無理に既存モジュール内で実現しようとせずにterraform stateを極めましょう。

FATモジュール正当化リスクへの対処

こちら、一部『同時生成/破壊される単位でまとめる。』と重複する内容になります。

初期構築では特にですが、今まで書いてきた設計方針に従うと『全部一モジュールにまとめる』となりがちです。 極論的には別に間違ってないのですが、流石になんというかアレ(うまく言語ができてない)ので、 適切な分割が必要にはなってきます。

具体的に言うとは比較的発生しやすい環境毎差分発生リスクに関しては標準的に対応しておきましょう。 ここが一番エンジニアの設計力が問われるところです。 過剰に分割すると「モジュール化しなくていいじゃん」となりかねません。

あいにく私はここに対する言語化を持ち合わせておりません。 というか唯一の正解があると考えていません。 おそらくインフラを管理する組織の形態などによっても変わってきます。

少し抽象的になるのですが、以下のような分離の判断基準があると考えています。

所有権の多様性

簡単に言うとそのモジュールに対して関与する組織のチームが2チーム以上になってきたら、 その部分は分割すべき箇所だと思います。

分かりやすい例としてはRDS周りを管理するチームが要るとして、FATなモジュールになっていると、 RDSを制御したいだけなのにEC2にも影響がないか気にしないといけない……みたいなことが起こります。

『コンウェイの法則』よろしく、組織の形態をそのままシステムの分割に反映してしまいましょう。 責任範囲の明確化ができます。

変更頻度の異質性

更新リズムが大きく違うものは分けておきましょう。

みたいな感じでしょうか。

RDSの変更(アップデート等)にEC2が影響を受けるのはよろしくないですし、逆もしかりです。

貧血モジュールへの対処

個人的に一番気にしているのはここかもしれません。

簡単に言うと一リソース一モジュールはやめといたほうがいいのでは、という話になります。 ドメイン貧血症に近い言葉が使えると考えています。

設計指針として分かりやすくはあるのですが、その結果として各環境ごとで定義するリソースが無限に増えていきますし、

個人的にモジュール化は『必要な差分を開放し、必要でない差分が本番環境・検証環境・開発環境などで発生しないことを技術的に保証する活動』だと考えています。

それに従うなら1リソース1モジュールはその保証が極端に難しくなります。 これは私がTerraformを利用し始めた時にも指摘されていて、 『本番環境と検証環境が同一であることをどう保証するの?』という会話を組織内でした記憶があります。

まとめ(というか今回のオチ)

はい。というわけで今のところの自身の考えを言語化してみました。 ところでこれ絶対にすでに言及されているよなと思って検索かけた結果普通に見つかりました。 書いた後に気づきましたが、まぁそちらの記事を普及させるためのスクラップということで気持ちの整理をつけます。

ここまで読んでくださった方、ご清聴ありがとうございました……。