既存リソースをterraform importで取り込むか作り直すか――brownfield移行の設計判断

brownfield移行でterraform importを選ぶか、リソースを再作成するかは、停止リスクと移行工数を左右する設計判断の核心です。どちらかに統一しようとすると必ず行き詰まります。基盤リソースはimport優先、末端リソースは再作成優先というハイブリッド戦略を軸に、state肥大化対策・drift検出設計・CI/CD段階導入まで、実装層が判断を誤りやすい落とし穴を先出しで整理します。

importで取り込むべきリソースと作り直しが適切なリソースの判断軸

先出しすべき落とし穴として、「importすれば安全」という誤解があります。importは既存リソースを破壊しないだけであり、その後のapplyで意図しない変更が走るリスクは別問題です。

置換コストと影響範囲で判断する

リソースをimportするかどうかは、そのリソースを削除・再作成したときの影響範囲と停止コストで判断します。VPC・サブネット・セキュリティグループのような「他の多くのリソースが依存している基盤リソース」は、再作成によって連鎖的な変更が生じます。EC2インスタンスや特定のRDSクラスタは、再作成するとIPアドレスやエンドポイントが変わるため、アプリケーション側の設定変更を伴います。一方、S3バケットの静的ホスティング設定・Route53レコード・CloudFrontキャッシュポリシーなどは、再作成しても影響が局所的です。こうした「置換影響が小さいリソース」は再作成を選んだほうが、importによるstate汚染リスクを避けられます。

リソースの可変性と設定変動リスクで判断する

importした直後のplanで差分が多く出るリソースは、手動変更の蓄積量が多いことを示しています。こうしたリソースは、importしても初回applyで意図しない変更が走るリスクを抱えます。特に「手動でパラメータ調整が繰り返されてきたデータベースのパラメータグループ」や「セキュリティチームが随時ルールを追加してきたセキュリティグループ」は、Terraform側のコードがその変更を網羅していなければ、applyのたびに既存設定が上書きされます。棚卸し工数が再作成コストを超えるなら、再作成のほうが設計上の合理性があります。一般的には、環境内のリソース数が100台規模を超えると、全量importは管理の複雑さが著しく高まります。この規模では「コアインフラをimport、末端リソースは再作成」というハイブリッド戦略が現実的です。

ライフサイクルの一致度で判断する

Terraformのstate管理は、リソースのライフサイクルがコードの意図と一致しているときに機能します。「既存の本番環境を維持しながら新しい環境を並列で構築している」ケースでは、既存リソースをimportすると新規構築のコードと既存リソースのstateが混在します。これはstateの見通しを悪化させ、後工程のdestroy時に誤って本番リソースを削除するリスクを生みます。ライフサイクルが分岐するリソースは別のstateに分離するのが設計上の正道です。同一のtfstateにライフサイクルの異なるリソースを混在させないことは、brownfield移行の設計原則として最初に決めておくべき事項です。

import方式と再作成方式の比較表

方式ごとの特性比較

比較軸 terraform import方式 再作成方式
停止リスク 低(既存リソースを維持) 高(削除→再作成の停止窓が発生)
初期工数 高(コードとstateの差分棚卸しが必要) 低〜中(コードを書いてapplyするだけ)
設定精度 既存設定を引き継ぐが差分管理が複雑 コードが設定の唯一の真実源になる
移行後の保守性 初期差分を解消すれば高くなる 最初から高い
適したリソース 基盤インフラ・依存関係が深いもの 末端リソース・置換影響が局所的なもの
drift残存リスク 高(棚卸し漏れが起きやすい) 低(コードが正になる)

ハイブリッド戦略の位置付け

実際のbrownfield移行では、import方式と再作成方式を組み合わせるハイブリッド戦略が設計の中心になります。VPC・サブネット・ゲートウェイ・ルートテーブルなどのネットワーク基盤はimport優先、本番トラフィックを受けているEC2インスタンスもimport優先、対してS3バケット単体の設定・CloudFrontキャッシュポリシー・Lambda関数の設定は再作成優先と分類できます。環境全体でimport対象が全リソースの30〜50%程度に収まるようスコープを絞ると、移行プロジェクトの工数が制御しやすくなります。スコープを絞る判断は、移行プロジェクト初期のリソース棚卸しフェーズで決定しておき、後から追加しないことが設計の一貫性を保つうえで重要です。

大規模importにおけるstate肥大化の設計考慮点

stateファイルの分割単位の設計

100台以上のリソースを一つのstateファイルで管理すると、planの実行時間が増加し、state locking中の待機時間がチームの作業を阻害します。一般的には50〜80リソースを超えたあたりでstateファイルの分割を検討する目安になります。分割単位の設計として、「ネットワーク層(VPC/サブネット/ゲートウェイ)」「コンピューティング層(EC2/ECS/Lambda)」「データ層(RDS/ElastiCache/S3)」「監視・セキュリティ層(IAM/CloudWatch/SecurityGroup)」という責務別の分割が扱いやすい構成です。各stateをTerraformのremote_state datasourceで参照し合う設計にすれば、分割後も依存関係を保てます。ただし循環参照には注意が必要で、下位層が上位層を参照する一方向参照のみに留めることが設計の原則です。

バックエンド設計と並行アクセス対策

大規模importではS3+DynamoDBバックエンドのstate lockingが必須です。複数人が同時にimport作業を進める場合、locking機構がなければstateファイルの競合(複数書き込みによるstate破損)が発生します。バックエンドの設計では、stateファイルのバージョニング(S3のObject Versioning)を有効にしておくことが重要で、import中に何らかの理由でstateが破損した場合、バージョニングがあれば1世代前のstateに戻せます。また、DynamoDBのlockテーブルのスループット設定は並列作業人数に応じてOn-Demandにしておくと、スロットリングによる作業停止を避けられます。

importブロックの活用と管理方針

Terraform 1.5以降で使えるimportブロックは、コマンド実行ではなくコードでimport対象を宣言できるため、レビューとCI統合の観点で扱いやすくなります。import完了後にブロックを削除するかコード内に残すかでチームの方針を決めておく必要があります。残すとplanのたびにimport済みチェックが走り無駄なAPIコールが増えるため、import完了後にブロックを削除してコードをクリーンに保つほうが保守性は高くなります。大規模環境では、import完了済み・未完了のリソースを管理する軽量なトラッキングリストを用意してプロジェクト管理と連携させると、作業の抜け漏れを防げます。手を動かす手順の詳細はセミナーや公式ドキュメントに委ね、ここでは設計判断の枠組みに留めます。

手動変更が残存するリソースのdrift検出設計

driftが生まれる構造的原因

brownfield環境でdriftが生まれる原因のほとんどは、「Terraformが管理するようになる前から存在していた変更フロー」の残存です。AWSコンソールやCLIから直接変更を加える運用慣習、障害対応で一時的に加えた変更がそのまま残るケース、外部チーム(セキュリティ・コンプライアンス担当)が独自のツールでリソース変更を行うケースが典型例です。

よくあるつまずきとして、importした直後のplanでdiffがゼロになることを「drift解消完了」と判断してしまうことがあります。これは誤りで、importした時点のstate=現状のリソース状態なので差分はゼロになって当然です。問題はその後、コードを変更したplanを走らせたときに出る「コードが意図しない属性変更」です。この点を見逃すと、本番反映後に予期せぬリソース変更が発生します。

drift検出のためのplan定期実行設計

drift検出は、定期的にterraform planを実行してdiff出力をゼロに保つ設計で対応します。CI上で毎日夜間にplanを走らせ、差分が出たらSlackやメール通知を飛ばす仕組みが一般的です。注意すべきは「planの実行コンテキスト」で、大規模環境でstateファイルが複数に分割されている場合、全stateに対してplanを走らせる制御スクリプトが必要になります。環境規模によっては1回のplan実行で10〜30分程度かかることも想定し、実行タイムアウトとエラーハンドリングの設計を先行して決めておきます。

drift発生箇所の分類と対応方針

planで差分が検出されたとき、3分類しておくと対応の優先度が整理しやすくなります。「許容差分」はTerraformが管理するつもりのない属性(AWSが自動付与するタグやメタデータ)に関するもので、ignore_changesに追加します。「修正必要差分」はコードとリソースの不一致でコードを更新して整合させます。「緊急対応差分」は本番リソースを破壊・置換するforce new changeが含まれるもので、apply前に必ず人間のレビューを挟む設計にします。この3分類を移行開始前にチームで合意しておくと、差分検出後の対応スピードが上がります。

import後の初回planの読み方と差分許容設計

初回planで出やすい差分の種類

import直後のplanがゼロ差分になることは稀で、多くのリソースで何らかの差分が検出されます。よくある差分は4種類です。①タグの不一致:Terraformコードに定義していないタグがリソースに付いている、またはその逆。②デフォルト値の解釈違い:TerraformのデフォルトとAWSのデフォルト設定が異なる場合に起きる擬似差分。③computed属性:Terraformがapply後に確定させる属性(ARN・IDなど)はknown after applyで表示されるが、実際には変更を伴わないことが多い。④手動追加設定:importしたリソースにコードにない属性が存在する場合。これらを事前に把握しておくだけで、差分への対応判断が大幅に速くなります。

差分の許容基準を設計する

差分をすべてゼロにしようとすると工数が青天井になります。許容基準を事前に設計しておくことが現実的な移行を可能にします。以下のチェックリストを使い、該当する差分は許容・後回しにする判断ができます。

  • force new changeが含まれていないか(削除・再作成を伴う差分は許容しない)
  • セキュリティ属性(暗号化・TLSポリシー・ACL)の変更が含まれていないか
  • 外部公開設定(パブリックIP・publicアクセス設定)の変更が含まれていないか
  • タグ差分のみか(ignore_changesで処理可能な差分か)
  • 差分があるリソースに他リソースの依存がないか

このチェックを通過した差分は一旦許容し、後フェーズで段階的に解消していく方針が工数を適切にコントロールします。チェックリストはチーム共有のドキュメントに残しておき、担当者が変わっても判断基準がぶれない設計にすることが重要です。

チーム内でimport作業を分担する際のstate競合防止

作業分担の設計単位

importを複数人で並行して進める際の最大のリスクはstate競合です。state競合は最悪の場合stateの破損やリソースの重複管理を引き起こします。分担の最小安全単位は「stateファイル単位」です。前述の分割設計(ネットワーク層・コンピューティング層・データ層)でstateが分かれていれば、担当者ごとに独立したstateを割り当てることで競合を構造的に防げます。stateが分割されていない状態で分担する場合は、「同一stateへの同時アクセスを1人に制限するシフト制」か「作業ブロックを時間的に直列化する」かのどちらかを採用する必要があります。

state lockingと作業調整の仕組み

DynamoDBによるstate lockingは同一stateへの同時書き込みを防ぎますが、lock取得待ちが長時間化すると作業効率が落ちます。チームでの分担作業では、lockの取得状況をリアルタイムで把握できる軽量な調整方法が有効です。作業開始前にSlackチャンネルへ「○○stateのimport開始」と宣言し、完了後に「完了・push済み」と通知するルールを設けるだけで、lock競合の多くを防げます。ツールに頼らなくても、コミュニケーション設計でstate競合を実質的に解消できます。

pull request戦略とstateファイルの整合

import作業をgit branchで管理する場合、stateファイルの変更とコードの変更を同一コミットに含めないと、CI上でplanを走らせたときに「stateに存在するがコードに未定義のリソース」が検出され、誤ったplan差分が生じます。推奨設計は「importブロックでコードに宣言→PRをマージ→ローカルまたはCI上でapplyしてstateを更新→更新後のstateをバックエンドに反映」という一方向フローです。stateファイルをgit管理下に置く設計はこの規模では避け、リモートバックエンドで一元管理するほうが整合性を保てます。

brownfield環境でのCI/CD有効化の段階的手順

CI/CD導入の3フェーズ設計

brownfield環境にCI/CDを段階的に導入するフェーズ設計は、3段階に分けて考えると整理しやすくなります。

第1フェーズはplanのみ自動化です。PRがマージされるたびにterraform planを実行し、差分を確認できる状態にします。この段階ではapplyは手動で行い、CI/CDがterraformのstate変更に影響を与えないよう設計します。全リソースに対するplanがエラーなく通り、差分が許容範囲内に収まることを確認することが次フェーズ移行の条件です。

第2フェーズは末端リソースへのauto apply導入です。リスクが低い末端リソース(タグ管理・監視設定・アラート設定など)に限定した設計ディレクトリをCI上でapply自動化します。このフェーズで3〜4週間程度運用し、auto applyが意図しない変更を本番に適用していないことを確認してから次フェーズへ進みます。

第3フェーズは本番コアインフラへのauto apply拡張です。ネットワーク基盤・データベース層は手動承認ゲートを設けてからapplyするよう設計し、完全自動化しないことが安全設計の基本方針です。手動承認ゲートを撤廃するかどうかは移行後の安定期に改めて判断すれば十分で、移行プロジェクト中に無理に自動化を進める必要はありません。

plan結果のゲート設計

CI/CD上でplanを自動実行する場合、plan結果に基づいてpipelineをブロックするゲート設計が重要です。ゲートで検出すべき条件として、force new changeが1件以上含まれる場合、削除対象リソースが含まれる場合、変更対象リソースが想定件数を超える場合(想定例として変更1件のPRで10件以上のリソース変更が出ているケース)が挙げられます。こうした条件のいずれかに該当する場合はpipelineを停止し、人間の承認を必須とする設計にします。この仕組みはbrownfield移行期だけでなく、greenfield環境でも有効な設計パターンとして継続活用できます。

▶ 手を動かして本番まで到達する

設計の型は掴めても、本番でTerraformを通しきる経験は別物です

ここまでの設計判断は、読めば腹に落ちます。ですが「自分の手で本番まで通しきる自信」は、それとは別の話になります。

2日間の集中ハンズオンで、AWS上にIaCで構築しきる経験を持ち帰れます。設計判断を、動くコードと本番環境の手応えに変える場です。

既存インフラのTerraform取り込み設計を実践するTerraformコースへ →

Terraformマスターセミナー|2日間ハンズオンでAWS上にIaCで本番構築