Infrastructure as Codeの冪等性とプロジェクトの関係性

初めまして、New Business Sector (NBS), Advanced Tech Division所属の坂本です。プロジェクトではインフラエンジニアを担当しております。

現在、私が所属しているチームではヘルスケア領域におけるプロダクトを開発しており、その中で今回はバックエンド、特にインフラ領域に特化したIaCの管理手法をお話をさせていただければと思います。

はじめに

現在、AWSなどのクラウドサービスを使っているのであればTerraformなどの構成管理ツール≒IaCを導入するのがスタンダードになりつつあります。

しかし、プロジェクトが始まると様々な要因によりコードと実環境の乖離が大きくなっていきます。それにより最終的にはコードが全く使えなくなったり、コードのためのメンテナンスが発生してしまい何のためにIaC化しているか不明になってしまうこともあるかと思います。

では、何故IaCはもてはやされるのにも関わらず実際のプロジェクトでは維持に苦労するのか考えてみたいと思います。

エンジニアとしてIaCに求めること

まず初めに、何のためにIaCを導入するのかを個人的な視点でまとめると下記の観点が大きいと考えます。

※今回は各種ツール特性のお話しは致しません。汎用的なツールを使用する際の例として記載します。

冪等性(べきとうせい)が担保されること

冪等性とは何度実行しても結果が変わらないことを指します。インフラの構築は初回に初期化が必要なものもあり、実行の度に初期化されるわけにはいきません。その中でどのような状態から何度実行しても既存の設定に変更が加わることがなく結果は等しくなるというのは非常に重要な事となります。

クラウド化している以上簡単に構成変更できるのが強みとなるため、一度作ったIaCは何度も変更を加えつつ使用できるのが最低条件となります。

各環境に同じデータが入れられること

本番環境のみという環境は基本的にはあまり存在しないことと思います。しかし、各環境の構築までのタイムラインは差があり、その間に様々な事情による構成変更も多々入ってきます。

そのすべてを手順書に起こしたり、GUI上の証跡を残そうとしても抜け漏れを完全になくすのは難しいでしょう。

しかし、IaCの場合はコード化されているので各環境に流しなおせば基本的に同じものが再現できます。少なくとも全てIaCでしっかり管理していれば抜け漏れはおきません。

上記を実現するためにも環境ごとに変数を準備して、コード自体は各環境同一である必要があります。

環境とGitで管理しているコードに差分がないこと

IaCは文字通りコードになりますので、現在ではGitで管理するのが主流になっています。それを考慮するとmasterブランチは常に商用環境と同一であるのがの理想となります。

そうすることで、masterブランチを流しなおせば直ぐに現行の商用環境が再現できます。設定ミスや予期せぬ変更が行われた際にすぐ元の商用環境に戻せる=システム安定性を高めることができますし、バグ調査のために試験環境を合わせることもできます。

2つ目のメリットとしては設定変更の際にコードを正として考えられるので毎回本番環境の設定を確認したり、商用環境の再現に差分を考慮したりといったことが不要となります。本番リリースの際の手順書作成や事前確認まで考えると小規模リリースを繰り返す昨今では工数としてはかなりの削減となります。

上記のメリットを達成するためにも、できればCI/CDといったツールと組み合わせて、git-flowなどのGitのお作法に乗っ取り管理することが、工数を削減するためにも、安定性を高めるためにもベストとなります。

図1: Gitと各環境に対するツールの組み合わせ例。ツール自体は条件を達成できるのであれば種類は問いません。

 

プロジェクトからインフラに求められること

上記のIaCのメリットとしてはGoogle等で調べてもほぼ同様のメリットがでてくると思います。しかし、プロジェクトがインフラに求めていることと、IaCが実現していることは同じなのでしょうか。

構成変更しやすい環境であること

プロジェクトにおいてインフラは上にアプリが乗って初めて完成となります。現在はある程度SaaSサービスがそろってきたとはいえ、やはり最終的な部分は自分たちで構築することが多いです。

そのため、工数としてはどうしてもアプリ改修>インフラとなってしまうことが多く、アプリで問題が起きた時にインフラで吸収できることは吸収するというのがプロジェクトトータルで見た時に効率の良い方法かと思います。

※ただし、セキュリティや今後の拡張性などを考えた時、受け入れられない変更はあってしかるべきかと思います。

工数と安定性を天秤にかけること

システムには当たり前ですが安定稼働が求められます。しかし、全システムがSLA99.999%を求められているわけでもありません。また、ユーザ体感としても基本的にはメンテ時間がない代わりに機能が少ないアプリよりも、毎月1時間のメンテ時間がある代わりに様々な機能が追加され使い勝手の良いアプリの方が使用し続けてくれる可能性は高いかと思います。

そういった中でインフラの過剰な安定性に工数をかけるよりはその分の工数をアプリにかけた方がプロジェクトとしても継続しやすいかと思います。もちろん、そのために将来の工数を減らすべくIaCを導入するのはもちろんですが、逆に過剰な管理が足を引っぱらないかは考える必要があります。

プロジェクトとIaCの折り合い

では、過剰な管理にならないために。構成変更しやすい構築とはどのようなものでしょうか。実際にプロジェクトで管理している際に基準にしていること、実施していることをまとめてみました。

細かいケース、一時ケースは考慮しないこと

プロジェクトから求められる一時的な即時対応と、IaCは相性があまりよくありません。現場ではバグなどの関係で一時しのぎを本番のみ適応というケースも実情としてあるかと思います。

その中で特定の環境専用の特殊な処理を一々書いているとコードを直している時間の方が多いですし、せっかくの各環境の統一性を崩してしまいます。

複雑なコードはそれだけバグを生みやすくなってしまうので、そういったケースはIaCにこだわらず手で管理し、アプリの改修を待って元に戻した方が結果的に事故も少なく、工数の面でも優秀と言えるでしょう。実際にterraformのチュートリアルページでもエッジケース, 条件分岐は管理しないことが推奨されています。参考URL

デプロイ粒度を調整できるようにすること。

本来、一括で管理できるのがIaCの魅力でもありますが、上記の一時対応などにより、全体でリリースするとIaCの特性により一時変更部分が戻ってしまうことが考えられます。

対策としては2案考えられ、1つは恒久的なエッジケースとなってしまうのであればIaCのデプロイ範囲から外すこと、2つ目はデプロイ事態を全体と個別に行えるようにすることです。

1つ目はそのまま上記にもあるように恒久的なエッジケースになるのであればIaCからは外すべきです。

2つ目は柔軟なリリース手段を持っておくようにするのが良いかと思います。一時的な変更であればIaCから外すよりも一旦別リリースできるようにしておけば元に戻すときもIaCの力を借りれますのでこちらが便利かと思います。

図2:GitHub Actionsによるパイプライン例。moduleを小分けにすることでデプロイ単位を調整可能としています。

工数と労力を比較すること

では一時的な変更は全てデプロイから外すべきかというとそんなことは有りません。

もちろん、改修の優先度が低く数か月かかる案件であったり、IaCの変数の変更程度で済むのであれば改修を行うべきかと思います。小さな改修に手間がかかってしまうようであればそれはgitのフローやCI/CD側を見直す必要があるかと思います。

改修までの時間、直すべきコードの量、IaCから外した際の管理コストをトータルで見て管理するかしないかを決めるべきでしょう。IaCはインフラを管理しやすく、安定性を高めるためのツールなのでIaCに固執しすぎることで工数の増大の促してしまったり、コードを複雑化させて安定性が犠牲になってしまうことを避けられればと思います。

終わりに

今回はIaC周りとプロジェクトについてお話しさせていただきました。

結論としてはIaCに固執しすぎても身動きが取れなくなりますし、IaCから管理を外しすぎてしまうとIaCの恩恵を受けられなくなってしまいます。

先ほどのterraformの公式でもmoduleは8割で動くものという記載があり、逆に言えば残りの2割はIaCで管理しなくともいいとも取れます。理想は全て管理しきることですが、それを実施することでIaCとしてのデメリットが多く出てしまう場合、または管理しきれなくなって設計書代わりにしかなっていない場合は管理部分を見直してみるのはいかがでしょうか。私自身もこれがベストだ!というものを試行錯誤していますので汎用的にできるメソッドを整理していきたいと思います。

関連記事