Terraformのstate分割設計を比較する|モノリシックstateとサービス別・レイヤー別の選択基準

運営:リナックスマスター.JP(代表 宮崎智広)
HOME > Linux技術 リナックスマスター.JP(Linuxマスター.JP) > Terraform > Terraformのstate分割設計を比較する|モノリシックstateとサービス別・レイヤー別の選択基準
「TerraformでAWSのリソースを管理し始めたら、いつの間にか1つのtfstateに100個以上のリソースが積み重なっている。terraform planに1分以上かかり、チームで同時にapplyするとlockが競合してしまう」

TerraformのS3バックエンド設定をした後、次に直面する設計課題の1つが「stateをどのように分割するか」という問題です。stateを1つにまとめ続けると、terraform planの実行時間が伸び、複数人が同時にapplyするとDynamoDBのlockが競合します。一方で分割しすぎると、state間の参照(remote_state)が増えてHCLが複雑になります。

この記事では、Terraformのstateをどのようなポリシーで分割するかという設計判断を、モノリシック・サービス別・レイヤー別の3つのアプローチを比較しながら解説します。Terraform 1.5以降を想定環境として、各アプローチの特徴・適した規模・移行コストまで整理します。

この記事のポイント

・1つのstateに集約すると変更の影響範囲が大きく、大規模になると分割が必要になる
・サービス別分割は独立デプロイしやすいが、共通インフラのremote_state参照設計が必要
・レイヤー別分割はlock競合を防ぎやすいが、レイヤー間のremote_state依存が増える
・「planの実行60秒超・lock競合が頻発」が分割に踏み切る目安の1つ


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Terraformのstateをなぜ分割するのかとプロジェクト規模ごとの目安

Terraformのstateは、Terraformが管理するリソースの「現在の状態」を記録するファイルです。1つのstateに含まれるリソースが増えると、次のような問題が起きやすくなります。

・terraform planが遅くなる:すべてのリソースをAWS APIで差分確認するため、リソース数に比例して時間がかかる
・lockの競合が起きる:複数人が同時にterraform planやapplyを実行すると、DynamoDBのstateロックが競合してブロックされる
・変更の影響範囲が広がる:ネットワーク設定だけを変更したのに、アプリサービスの全リソースがplan差分として表示される

stateの分割を検討するタイミングの目安はこちらです。

・terraform planの実行が60秒を超え始めた
・チームの開発者が3名以上でlock競合が頻発している
・共通インフラ(VPC・DNS)とアプリサービスの変更を独立させたい

逆に、小規模なプロジェクトや1人で管理している場合はモノリシックstateのシンプルさを活かすほうが管理コストを低く保てます。

モノリシックstate(全リソースを1つのstateで管理)の特徴と限界

最もシンプルなアプローチは全リソースを1つのtfstateで管理することです。

メリット デメリット
リソース間の参照がシンプル(ARNやIDを直接参照できる) リソース数が増えるとplanが遅くなる
terraform planで全体の差分が一画面で確認できる lockの競合でチームの開発速度が落ちる
初期設定が少なく始めやすい ネットワーク変更がアプリ層のplan差分に影響する
モノリシックstateが適しているのは、リソースが50個以下のプロジェクトか、1~2人でメンテナンスする小規模システムです。分割するよりもシンプルさを優先するほうがオペレーションコストを低く保てます。

サービス別state分割の設計パターン

「サービス別分割」は、デプロイの単位(マイクロサービス・アプリケーション)ごとにstateを分ける設計です。共通インフラ(VPC・サブネット・DNS)は専用のstateで管理し、アプリサービスA・BはそれぞれのstateでECS・ALB・RDSを管理します。

# ディレクトリ構成例(サービス別分割) environments/ └── production/ ├── shared-infra/ # VPC・サブネット・Route53 │ ├── main.tf │ └── backend.tf # key: prod/shared-infra/terraform.tfstate ├── service-a/ # ECS・ALB・RDS for service-a │ ├── main.tf │ └── backend.tf # key: prod/service-a/terraform.tfstate └── service-b/ ├── main.tf └── backend.tf # key: prod/service-b/terraform.tfstate

1. remote_stateで共通インフラのIDを参照する

service-a側からshared-infraのVPC IDやサブネットIDを参照する場合、terraform_remote_stateデータソースを使います。

# service-a/main.tf data "terraform_remote_state" "shared" { backend = "s3" config = { bucket = "my-terraform-state" key = "prod/shared-infra/terraform.tfstate" region = "ap-northeast-1" } } # 参照例(サービスAのサブネット指定) locals { private_subnet_ids = data.terraform_remote_state.shared.outputs.private_subnet_ids }

2. shared-infra側でoutputを公開する

参照される側のstateは、参照されるリソースをoutputとして公開しておく必要があります。

# shared-infra/outputs.tf output "private_subnet_ids" { value = aws_subnet.private[*].id } output "vpc_id" { value = aws_vpc.main.id }

サービス別分割が適するのは、複数チームが独立してデプロイする必要があるときです。チームAのデプロイがチームBのstateをlockすることがなくなります。ただし、shared-infraのoutput定義が「stateのAPI」になるため、互換性を破壊するoutputの削除・型変更には注意が必要です。

TerraformでLinuxサーバーインフラの設計を体系的に学びたい場合は、Terraform実践講座の詳細ページでも確認できます。

レイヤー別state分割(ネットワーク・コンピュート・データ)の設計

「レイヤー別分割」は、インフラのレイヤー(ネットワーク層・コンピュート層・データ層)でstateを分ける設計です。変更頻度の低いネットワーク層と高いコンピュート層を分離することで、変更の影響範囲を小さくします。

# ディレクトリ構成例(レイヤー別分割) environments/production/ ├── 01-network/ # VPC・サブネット・NAT Gateway(変更頻度: 低) ├── 02-security/ # SG・IAMポリシー・KMS(変更頻度: 低~中) ├── 03-data/ # RDS・ElastiCache・S3(変更頻度: 中) └── 04-compute/ # ECS・ALB・Lambda(変更頻度: 高)

変更頻度が高い04-computeだけが頻繁にapplyされ、01-networkはほとんど変更されないため、各レイヤーのplanが小さく速くなります。

比較項目 サービス別分割 レイヤー別分割
チームの分担方法 サービス(機能)ごとに担当を分けやすい インフラ専門チームが全レイヤーを管理しやすい
デプロイの独立性 サービス単位で独立してリリース可能 レイヤー間の依存順序を守る必要がある
remote_state参照の数 shared-infra→各サービスで1~2参照 上位レイヤー→下位レイヤーへの複数参照
適した組織 マイクロサービス型の開発組織 インフラ専門チームがある組織

remote_stateを使ったstate間のデータ参照設計

どの分割パターンでも、state間でデータを参照するためにremote_stateを使います。設計上の注意点を整理します。

循環参照を作らない:state Aがstate Bを参照し、state BもAを参照する循環は禁止です。参照は常に一方向(例:04-computeが01-networkを参照)にします。

outputの後方互換を守る:state Aのoutputを削除すると、それを参照しているstate Bのterraform planが失敗します。outputは「API」として扱い、削除前にすべての参照元から外します。

terraform_remote_stateはstateファイルに直アクセスする:remote_stateはS3のstateファイルをそのまま読むため、backend設定(bucket・key・region)が正しく指定されていないと「object has no attribute」エラーが出ます。stateファイルのパスはコードレビューで確認する習慣が重要です。

state分割設計の選択基準

どのアプローチを選ぶかの判断フローをまとめます。

1. リソース数が50個以下かつ1~2人管理:モノリシックstateのまま維持する
2. 複数チームが独立してデプロイする必要がある:サービス別分割
3. 1つのインフラチームが全体を管理しつつplanを高速化したい:レイヤー別分割
4. 大規模でTerraformのDRY化も課題:Terragruntのdependencyブロックを使ったstate管理も検討する

初期設計でレイヤー別かサービス別かに迷ったときは、将来のチーム構成から逆算するのが有効です。1つのインフラチームで管理するならレイヤー別、開発チームごとにインフラを持つなら早期からサービス別を採用します。

state分割後のよくある失敗とトラブルシュート

1. terraform planで「Error: Invalid data source argument」が出る

remote_stateを参照しているときに、参照先stateのoutputが存在しない場合に発生します。参照先stateのディレクトリでterraform outputコマンドを実行してoutputが公開されているか確認します。

# 参照先stateのoutputを確認(出力例(環境により異なります)) $ cd environments/production/01-network $ terraform output private_subnet_ids = [ "subnet-0a1b2c3d", "subnet-0e4f5a6b", ] vpc_id = "vpc-0123456789abcdef0"

2. terraform planが「Error acquiring the state lock」で止まる

前のapplyが途中で失敗してDynamoDBのlockが残った場合です。terraform force-unlock LOCK_IDでlockを手動解除します。LOCK_IDはエラーメッセージ内に表示されます。force-unlockは他のapplyが実際に動いていないことを確認してから実行します。

3. 分割後に既存リソースが「deleted and recreated」としてplanに出る

state分割の際にリソースを別stateへ移動させるとき、正しくstate mvしないと旧stateでの「delete」と新stateでの「create」として計画されてしまいます。既存リソースを壊さずに移動するにはterraform state mv(コマンド)かmovedブロック(HCL宣言)を正しく使います。

本記事のまとめ

Terraformのstateをどのポリシーで分割するかは、チームの規模・組織構造・デプロイ頻度によって変わります。

分割方針 適した場面 主な注意点
モノリシック 小規模・1人管理・50リソース以下 規模が大きくなると管理限界が来る
サービス別分割 マイクロサービス・複数デプロイチーム shared-infraのoutput互換を守る必要がある
レイヤー別分割 インフラ専門チームがある・planの高速化 レイヤー間参照が増えると複雑になる
分割設計は最初から完璧に決める必要はありません。モノリシックからスタートして、terraform planが遅くなりlock競合が起きるようになったタイミングでサービス別・レイヤー別へ段階的に移行するアプローチが現実的です。移行時はmovedブロックを活用してリソースを再作成せずにstate間を移動させます。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、TerraformとLinuxサーバー実践講座の詳細はこちら>>

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録

運営

リナックスマスター.JP(代表 宮崎智広)

株式会社イーネットマーキュリーが運営するLinux教育サイトです。代表の宮崎智広は現役のLinuxサーバー管理者として20年以上の実務経験を持ち、累計3,100名以上のエンジニアを指導してきました。実践型のLinuxセミナーや無料マニュアルの配布を通じてLinux人材の育成に取り組んでいます。