ある火曜日の午後、あなたは(Terraform plan)を実行し、画面には「No changes」というクリーンな結果が表示されました。
前回のデプロイでの混乱を教訓に慎重に確認を重ねましたが、やはり変更の必要はないと判断し、Pull Requestをマージして席を立ちます。
しかし、そのわずか45分後、SlackにはAPIが特定のエンドポイントで「403 Forbidden」を返しているというアラートが鳴り響きます。
調査の結果、原因は3週間前の障害対応時にコンソールから直接手動で変更されたS3バケットポリシーにありました。
(Terraformのステートファイルは現実のインフラと乖離していた)のです。
IaC(Infrastructure as Code)を導入していればすべてが解決するという神話が、現実の運用の前で崩れ去る瞬間です。
ステートファイルは「真実」ではなく「過去の記憶」に過ぎない
Terraformを利用するエンジニアにとって、ステートファイル(terraform.tfstate)はインフラの構成を管理する唯一の羅針盤のように思えるかもしれません。
しかし、本質的にステートファイルは(「最後のapply実行時に、インフラがどう見えていたか」を記録したスナップショット)に過ぎません。
Terraformの実行プロセスにおいて、(terraform plan)は宣言された設定ファイル(.tf)とステートファイルを比較します。
デフォルトでは実行時にクラウドプロバイダーへ最新情報を問い合わせる「リフレッシュ」が行われますが、これには限界があります。
ステートファイルが追跡できない領域
Terraformが管理しているリソースについては、設定値の変更(ドリフト)を検知できますが、以下のパターンでは(Terraformは沈黙を守ります。)
- (未管理リソースの作成:) 誰かがAWSコンソールから手動で作成した新しいS3バケットやIAMロールは、ステートファイルに存在しないため、比較対象にすらなりません。
- (サービスによる自動変更:) AWS Auto Scalingによるインスタンス数の増減、RDSのストレージ自動拡張、ECSのタスク数調整など、クラウドサービス側が自律的に行った変更は、明示的に無視する設定をしない限り、次回の実行で「意図しない変更」として上書きされるリスクがあります。
- (不完全なリフレッシュ:) 大規模な環境ではAPIのレートリミットを回避するためにリフレッシュをスキップすることがあり、その場合、ステートファイルと現実の乖離はさらに深刻化します。
ステートファイル内の(serial)値は、Terraformを介した変更の回数を示していますが、コンソールで行われた手動操作はこのカウントを一切増やしません。
結果として、(「Terraformの視点では正常だが、現実のクラウドは壊れている」という不整合)が発生します。
「パイプラインの強制」だけでは解決できないスケールの壁
ドリフト対策として最も一般的なアドバイスは「手動変更を一切禁止し、すべてをCI/CDパイプラインを通すこと」です。
確かに、小規模なチームや単一のアカウントであれば、厳格な運用ルールで統制が取れるかもしれません。
しかし、組織が成長し、マルチアカウントやマルチクラウド環境へとスケールしたとき、この「運用によるカバー」は限界を迎えます。
| 規模 | 課題の詳細 |
|---|---|
| 小規模チーム | メンバー間のコミュニケーションで手動変更を把握可能だが、緊急時はルールが形骸化しやすい |
| 中規模組織 | 複数のAWSアカウントやGCPプロジェクトが混在し、誰がどこで何を変えたかの追跡が困難になる |
| エンタープライズ | 買収した企業の既存インフラや、IaC化される前のレガシーリソースが混在し、全容把握が不可能に近い |
コンソールを一つずつ開き、セキュリティグループの設定やIAMポリシーを「目視」で確認する作業は、もはや持続不可能です。
スクリプトを組んでリソースをリスト化しても、ページネーションの処理漏れやAPIの仕様変更により、(「見えているつもりの情報」が不完全である可能性)が常に付きまといます。
インフラを「データベース」としてクエリする新発想
この課題を根本から解決するためには、インフラの状態をスナップショット(静的なファイル)として捉えるのではなく、(「常に最新の状態が反映されるデータベース」として扱うアプローチ)が必要です。
近年注目されているのが、クラウド上のあらゆるリソース情報をSQLで検索可能な状態にする手法です。
例えば、CloudQueryのようなツールを使用すると、複数のクラウドプロバイダーやアカウントを横断して、現在の真の姿を問い合わせることができます。
以下は、全アカウントの全リージョンから「オーナー設定(tags)がされていないEC2インスタンス」を抽出するクエリの例です。
SELECT account_id, region, instance_id, tags
FROM aws_ec2_instances
WHERE tags->>'owner' IS NULL
ORDER BY account_id, region;
このようなアプローチの利点は、(「Terraformが管理しているかどうか」に関わらず、今そこにあるリソースを可視化できる)点にあります。
Terraformのステートファイルと、このSQLによるスキャン結果を突き合わせることで、初めて「真のドリフト」を特定することが可能になります。
ドリフト検知後の具体的な処置フロー
ドリフトを発見した際、エンジニアが取るべきアクションは、その変更が「正当な理由によるものか」によって異なります。
1. 手動変更が「正解」だった場合
緊急対応でセキュリティ設定を強化したなど、手動変更を正当なものとして恒久化する場合は、インフラコード側を現実に合わせる必要があります。
- (terraform importの使用:) Terraform 1.5以降で導入された
(import)ブロックを利用し、既存リソースをコード管理下に取り込みます。 - (コードの自動生成:)
(-generate-config-out)フラグを活用して、既存リソースに基づいたHCLの雛形を作成し、手動記述のミスを防ぎます。
2. 手動変更が「誤り」だった場合
不要なリソースの作成や、セキュリティを弱める変更がなされていた場合は、速やかにTerraformの設定で上書きし、元に戻します。
- (terraform applyによる強制同期:) 設定ファイルと乖離がある場合、Terraformはそれを修正しようと動きます。ただし、意図しない破壊的な変更が含まれていないか、プラン結果を慎重にレビューすることが不可欠です。
3. ガバナンスプラットフォームの導入
env0のようなクラウドガバナンスプラットフォームを導入することで、ドリフトの継続的な監視と自動通知、ポリシーの強制(Policy as Code)を実現できます。
これにより、(「火曜日の午後に沈黙の中で発生する障害」を、デプロイ前に未然に防ぐ体制)を構築できます。
まとめ
Terraformが「変更なし」と報告したとき、それはシステムが安全であることを保証するものではありません。
単に「あなたの書いたコードと、過去の記録が一致している」と言っているに過ぎないのです。
真のインフラ管理とは、IaCツールの中だけに閉じることではなく、(現実のクラウドの状態を常時モニタリングし、コードとの差異を迅速に解消し続けるサイクル)そのものを指します。
- ステートファイルはあくまで限定的なスナップショットであることを認識する。
- SQLベースのツールなどを活用し、マルチアカウント環境での「全容」を可視化する。
- ドリフトを検知・修正するフローを自動化し、ガバナンスを効かせる。
これらのステップを踏むことで、IaCの恩恵を最大限に享受しつつ、予期せぬ「403エラー」に怯えることのない、堅牢なプラットフォーム運用が可能になるでしょう。
インフラの「真実」は、常にステートファイルの外側に存在しているのです。
