Infrastructure As Codeにおいて、コードのモジュール化により再利用性を高めることが難しいと言われている。それはなぜなのかを考察する。
Infrastructure as Codeで痛い目あった人ってだいたいやりすぎてる気がする(偏見)。過度な抽象化とか共通化、公開されているrecipeを無闇に使っちゃうみたいな。特に抽象化まわり、普通のプログラミングのつもりできれいに整理しようとするとやり過ぎになりがち
— fujiwara (@fujiwara) 2020年3月30日
自分が経験したIaCアンチパターンは、例えばnginxのchefコードを再利用しようとしてnginxのパラメータを全部外部注入できるようなモジュールを作るやつですね。コストが上がり過ぎる #InfraStudy
— そのっつ (Naotoshi Seo) (@sonots) 2020年4月24日
1つ目の理由は、サーバ上のファイルシステムやクラウドサービスの設定などのインフラはグローバルの共有空間に状態をもつことから、状態管理をモジュール内に留められない(カプセル化ができない)ことだ。複数の異なるモジュールが共有空間を操作してしまい、操作が競合することがあり得る。
この問題によって、モジュール単位で単体テストを書いても、複数のモジュール間が混在する環境では動作を保証できない。Serverspecは最後に状態が収束した結果をテストすることにより、サーバ構成管理の範囲でこの問題を解決している。
現在では、サーバ構成管理については、コードをモジュール化するのではなく、コンテナのようにより小さい粒度で状態空間を作成して、空間を局所化することにより、操作の競合を防ぐことが一般的である。
2つ目の理由は、モジュールを作成するときに、モジュールへの入力パラメータが多いほど、入力パラメータ数に比例してコードを書かなければならないため、モジュールを作成・メンテナンスするためのコストが高くなることだ。例えば、nginxやMySQLなど一部のミドルウェア、非常に多くの設定パラメータをもつ。
したがって、特定の組織やシステムに必要なパラメータのみを入力として受け付けるようにして、それ以外はデフォルト値や推奨値でパラメータを固定するといった解決をすることがある。
3つ目の理由は、昨今のクラウドサービスでは、非常に多くのコンポーネントを利用することがあるため、単純にそれらのコンポーネントの設定を逐一コード化するための手間が大きいことだ。
したがって、検証のために試行錯誤したいときや、ほとんど変更しないと分かっているコンポーネントはコード化しないといった判断をすることがある。
3つ目の理由はコード化が疲れる理由であって、モジュール化が難しい理由ではなかったので、削除した。
他にも理由はあるかもしれないが、思いついたのは一旦ここまで。
追記
NWスイッチの制御など環境ごとの差異が大きい場合,全てに対応できるようなモジュール(インタフェース)を作ると抽象度が高すぎて役に立たないというケースもあると思います。
— id (@ido_kara_deru) 2020年4月24日
またモジュール化の難しさでは無いですが,頑張ってIaC化してもすぐに使われなくなり,割に合わなかったケースがありました
3つ目の理由として、モジュールの作成時に、OSやネットワークスイッチなどインフラの環境の差異をモジュールが吸収しようとすると、環境ごとの分岐処理が追加されるため、理由2と同様に、モジュールを作成・メンテナンスするためのコストが高くなることがある。