📒

terraform stateのちょうどいい単位は?

2021/12/08に公開

これは「「はじめに」の Advent Calendar 2021」8日目の記事です。

TL;DR

  • tfstateファイルは意味のある単位、モジュール化できそうかも、という単位で分割する。
  • ファイル数、リソース数を分割の基準にしない。
  • 正解はない

前提

Terraform はAWS等の主にクラウド上のリソースをコード管理できるツールです。
https://www.terraform.io/

AWS以外では、GCPやDataDog、GithubなどProviderとしてHashicorpや3rd partyから提供されているリソースをコードで管理できます。

リソースの状態は tfstateファイル として管理されます。(※tfstateファイルはリモートバックエンドとして S3terraform cloud で安全に履歴管理することができます)

しかし、リソース数が大きくなると1ファイルでは都合が悪くなる場面が出てきます。

例として以下のような問題があります。

  • 単純にリソースが多くてplan、applyに時間がかかる
  • 想定外の差分があったときに差分をなくすための調査や作業に時間がかかる
  • リソースが多いと比例的に扱うチーム数が多くなる傾向があるので、自チーム外のリソースも一緒に管理することになる。

分割単位

分割する場合、ぱっと考えると以下のような手法が思いつきます。

A.リソースの種別ごとに分ける

AWSの場合、S3、EC2、RDSなどそれぞれのリソースごとに分ける方法です。
リソースの変化が少ない場合は管理できますが、リソース間の依存が多くなり特にSecurityGroupをどこにおいてもState間の依存が発生してしまい、 remote_state を駆使する必要が出てきてしまいます。

B.チームで管理しているリソースの単位で分ける

  • あんこうチームは、〇〇APIと関係するRDS、S3。
  • アヒルさんチームは、△△API、□□API、DynamoDB、S3。
    というようにチームごとにstateを分ける方法です。

触るリソースがチーム単位で独立するので、わからなくなるリソースがないメリットがあります。
反面、Route53などの共通リソースを別途管理するStateはどうするのか、チーム編成が代わり担当APIが変わるたびにStateの移動を行うのか、1つのシステムを複数のチームが触っている場合はどうするのか、など別の課題が多く生まれることがあります。

C.システム的に結び付きが強い単位で分ける

C向けサービスとB向けサービスなど、サービス単位やAPIとそれに必要RDBなどの単位で分ける方法です。
B案のチームで管理している単位よりも細かい単位となりますが、システムへの変更=stateの変更となることが多くなります。
共通リソースも共通部分として独立した単位で管理し、複数チームの共同所有物とします。

D.リソース数で分ける

100リソースごととか。
絶対やってはいけません。

どうするか

個人的にはC案が一番良さそうだと考えています。
経験上、A案はstate間の依存が強くなりがちでメンテナンスしづらかったです。
B案はチームに縛られすぎており、コンウェイの法則に縛られる可能性も出てくるので直感的には避けたほうが良い気がしています。
D案は論外なので、消去法としてC案が良いのではないかという次第です。

当然C案でもstate間の依存は完全になくせないので、outputremote_state を使うか命名規則を統一して data source を利用して必要な情報を取得する形になります。

マイクロサービスアーキテクチャで作っていけば、内部APIの接続に必要なSecurtyGroupや共通インフラのVPCのidなど、state間で受け渡す情報が限られてくるはずです。
この依存が多い場合は、システムの境界が歪になっている可能性が出てくるので、そういったチェックに利用する事もできます。

ただ、分割基準の正解は自分でも完全に決定できているわけではないので、方針としてC案が良いだろう、という程度です。事実、今のプロジェクトでもC案の考え方をベースに管理しています。

今後もっと良い方針が見つかるかもしれませんが、それまではこのまま運用していこうと思います。

Discussion