インフラストラクチャの状態はどこに保存すべきか?実践ガイド

あなたはちょうど、数台のサーバーとデータベースをプロビジョニングするTerraform構成を書き終えたところです。自分のラップトップで terraform apply を実行すると、すべてが正常に動作します。ロードバランサーを追加する必要がある同僚が、同じ構成を自分のマシンから実行します。すると突然、データベースが消えてしまいます。コードが間違っていたからではありません。同僚のローカル状態ファイルが、データベースがすでに存在することを知らなかったからです。

このシナリオは仮定の話ではありません。これは、インフラストラクチャの状態を各開発者のマシン上のローカルファイルとして保存しているチームで日常的に発生しています。問題は単純です。複数の人が同じインフラストラクチャを管理する場合、各人のローカル状態はすぐに古くなります。リソースが上書きされたり、重複したり、誤って破壊されたりします。修正方法も同様に単純です。状態を、チームの全員がアクセスできる共有の安全な場所に保存することです。

状態とは何か、なぜ重要なのか

状態とは、インフラストラクチャツールが作成したすべてのものの記録です。リソースID、IPアドレス、構成値、場合によってはプレーンテキストで保存されたパスワードやAPIキーも含まれます。terraform plan を実行すると、ツールは現在の状態を読み取り、何がすでに存在し、何を変更する必要があるかを把握します。正確な状態がなければ、ツールはリソースを作成すべきか、更新すべきか、そのままにしておくべきかを判断できません。

状態が失われたり破損したりすると、ツールはインフラストラクチャを見失います。結果として、コストはかかるが管理されていない孤立したリソースが発生したり、さらに悪いことに、すでに実行中のリソースを誤って再作成し、ダウンタイムを引き起こしたりします。

ローカルファイルの罠

状態を保存する最も簡単な方法は、自分のマシン上のファイルとして保存することです。学習用や個人プロジェクトでは、これで問題ありません。インフラストラクチャに触れるのは自分だけなので、競合は発生しません。

しかし、2人目が参加した瞬間に、ローカル状態は機能しなくなります。何が起こるかを見てみましょう。

  • あなたがサーバーを作成します。あなたの状態ファイルに記録されます。
  • 同僚が同じ構成を実行します。同僚の状態ファイルは空なので、ツールは同じ名前の別のサーバーを作成しようとします。
  • クラウドプロバイダーが重複を拒否するか、さらに悪いことに、ツールは既存のサーバーが存在することを知らないため、上書きしてしまいます。

たとえバージョン管理を通じて状態ファイルを共有しても、マージ競合が発生します。2人が同時に同じ状態ファイルを編集すると、お互いの変更を上書きしてしまいます。これが、インフラストラクチャを共同で管理するチームがリモートバックエンドを使用しなければならない理由です。

どのアプローチが自分の状況に適しているかを判断するために、以下の決定フローチャートを参考にしてください。

flowchart TD A[インフラ管理の人数は?] --> B[1人] A --> C[複数人] B --> D[ローカルファイルでOK] C --> E[リモートバックエンドが必要] E --> F[バックエンドの種類を選択] F --> G[S3 + DynamoDB] F --> H[GCS] F --> I[Azure Storage] F --> J[Terraform Cloud] F --> K[Consul] G --> L[ロックとバージョニングをサポート] H --> L I --> L J --> M[マネージド、運用負荷が少ない] K --> M L --> N[アクセス制御を設定] M --> N N --> O[チーム利用の準備完了]

リモートバックエンド:共有された信頼できる情報源

リモートバックエンドは、チームの全員がアクセスできる場所に状態を保存します。一般的な選択肢としては、AWSのS3バケット、Google CloudのGCSバケット、Azure Storageコンテナなどがあります。全員がインフラストラクチャツールを同じバックエンドに向けるため、状態は常に一貫性を保ちます。

以下は、状態ストレージにS3バケット、ロックにDynamoDBテーブルを使用する最小限のTerraformバックエンド構成です。

terraform {
  backend "s3" {
    bucket         = "my-company-terraform-state"
    key            = "production/network/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-state-locks"
    encrypt        = true
  }
}

この構成を使用する前に、バージョニングを有効にしたS3バケットと、プライマリキーが LockID(型はString)のDynamoDBテーブルを作成してください。encrypt = true 設定により、状態ファイルが保存時に暗号化されます。

しかし、リモートバックエンドは単なる共有フォルダではありません。選択する前に、いくつかの点を考慮する必要があります。

アクセス制御は必須

状態ファイルには機密情報が含まれています。リソースID、IPアドレス、場合によっては認証情報がプレーンテキストで保存されています。チーム外の誰かが状態への読み取りアクセスを取得すると、インフラストラクチャ全体の詳細を見ることができます。書き込みアクセスを取得すると、リソースを破損または削除する可能性があります。

状態を保存するバケットまたはコンテナをロックダウンしてください。IAMポリシーまたはロールベースのアクセスを使用して、許可された人とシステムのみが状態を読み書きできるようにします。状態バケットは、本番データベースと同じように扱ってください。

速度とコストのトレードオフ

ローカル状態は、ファイルが自分のマシンにあるため高速です。リモートバックエンドでは、planやapplyの前に状態をダウンロードし、その後アップロードする必要があります。数十のリソースを持つ小規模チームの場合、これにより1〜2秒追加されます。数千のリソースを持つ大規模インフラストラクチャの場合、ダウンロードとアップロードに数分かかることがあります。

一部のバックエンドは、操作ごとまたはストレージのギガバイトごとに課金されます。たとえばS3は、PUTリクエストとGETリクエストに対して課金されます。チームが1日に何十回も terraform plan を実行する場合、これらのコストは積み重なります。チームの使用パターンに合ったバックエンドを選択してください。

バージョニングがミスから救う

一部のリモートバックエンドはバージョニングをサポートしています。S3は、すべての状態ファイル変更の履歴を保持できます。誰かが変更を適用して問題が発生した場合、以前の状態バージョンにロールバックして復旧できます。

バージョニングはデフォルトでは有効になっていません。明示的に有効にする必要があります。バックエンドが自動的に履歴を保持するとは想定しないでください。ドキュメントを確認し、必要になる前にバージョニングを有効にしてください。

マネージドバックエンドは運用負荷を軽減する

バケット、アクセスポリシー、バージョニングを自分で管理したくない場合は、Terraform CloudやHashiCorp Consulのようなマネージドバックエンドを検討してください。これらのサービスは、状態管理専用に設計されています。バージョニング、履歴、ロック、CI/CDパイプラインとの統合が含まれています。

トレードオフは、コストとベンダーロックインです。マネージドバックエンドは、ユーザーごとまたはワークスペースごとに課金されます。また、プロバイダーの稼働時間とAPIの可用性に依存します。状態管理ではなくインフラストラクチャに集中したいチームにとって、このトレードオフはしばしば価値があります。

ロックは同時変更を防ぐ

リモートバックエンドを使用していても、2人が同時に terraform apply を実行する可能性があります。ロックがない場合、両方の操作が同じ状態を読み取り、変更を加え、書き戻します。2番目の書き込みが最初の書き込みを上書きし、最初の人の変更が失われます。

ほとんどのリモートバックエンドはロックをサポートしています。たとえば、S3とDynamoDBは、DynamoDBテーブルを使用してロックを保持します。誰かが操作を開始すると、ツールはロックを取得します。他の操作は、ロックが解放されるまで待機する必要があります。これにより、同時書き込みによる状態の破損を防ぎます。

ロックはチームにとってオプションではありません。バックエンドがロックをサポートしていない場合は、サポートしているものを見つけてください。

状態ストレージのための実践的なチェックリスト

状態をどこに保存するかを決定する前に、このチェックリストを確認してください。

  • バックエンドは、必要なすべての人がアクセス可能ですか?
  • アクセスは許可された人とシステムに制限されていますか?
  • バックエンドはバージョニングをサポートしていますか?
  • バックエンドはロックをサポートしていますか?
  • コストはチームの使用パターンに対して許容可能ですか?
  • レイテンシはワークフローに対して許容可能ですか?

6つすべてに「はい」と答えられれば、堅牢な状態バックエンドができています。

具体的な要点

インフラストラクチャの状態をラップトップに保存しないでください。アクセス制御、バージョニング、ロックをサポートするリモートバックエンドを使用してください。適切な状態バックエンドを設定するための数分が、誰かが誤ってリソースを削除したり、同僚の変更を上書きしたりしたときの何時間ものデバッグからあなたを救います。インフラストラクチャは、それを追跡する状態と同じくらい信頼性があります。状態が安全な場所に保存されていることを確認してください。