インフラ変更が本番環境を壊したとき:IaC障害からの復旧

あなたはすべてを正しく行いました。Terraformの計画は2人のシニアエンジニアにレビューされ、変更はパイプラインのポリシーチェックを通過し、ステージング環境で3日間問題なく動作しました。そして本番環境に適用したところ、10分も経たないうちにユーザーからエラー報告が相次ぎました。

これがインフラ変更の現実です。どれほど徹底したレビュープロセスを経ても、実際のトラフィックの下でしか顕在化しない問題があります。見落とした依存関係、ステージングと本番環境の間でなぜかすり抜けた設定の差異、変更と既存リソースの間の予期せぬ微妙な相互作用。

このような状況でチームに最も必要なのは、既知の正常な状態に迅速に戻る能力です。これがインフラのロールバックであり、アプリケーションコードのロールバックとは異なる仕組みで動作します。

なぜインフラのロールバックは異なるのか

アプリケーションのロールバックは通常、コードの以前のバージョンをデプロイすることを意味します。サーバー、ネットワーク、データベーススキーマはすべてそのままです。バイナリやコンテナイメージを入れ替えるだけです。

インフラのロールバックはそれほど単純ではありません。インフラには、サーバー、ロードバランサー、ネットワークルール、データベースインスタンス、ストレージボリューム、そして互いに依存し合う数十の他のリソースが含まれます。他のリソースを考慮せずに1つのリソースだけを古いバージョンにロールバックすると、状況が悪化する可能性があります。

セキュリティグループのルールを変更し、同時にロードバランサーの設定も更新したと想像してください。セキュリティグループだけをロールバックすると、ロードバランサーが古いセキュリティグループでブロックされるインスタンスを指すようになるかもしれません。復旧の試みが新たな障害を生み出したことになります。

安全なインフラロールバックの鍵は、ステート管理と設定バージョン管理の2つに集約されます。

ステート管理:何を持っているかを把握する

Terraform、Pulumi、OpenTofuなどのInfrastructure as Codeツールはステートファイルを管理します。このファイルには、ツールが管理するすべてのリソース、その現在の設定、リソース間の関係が記録されています。正確なステートがなければ、ツールは何が存在するかを知ることができず、ましてやそれをどう変更するかもわかりません。

ステートファイルは重要な資産です。安全に保存し、アクセス制御し、変更のたびにバージョン管理する必要があります。ステートファイルを失うと、IaCを通じてそのインフラを管理する能力を失います。手動での復旧に戻り、どのリソースが存在し、それらがどのように接続されているかを推測することになります。

ベストプラクティスは、ステートをリモート(クラウドストレージ、バックエンドサービス、専用のステート管理ツール)に保存することです。開発者のラップトップ上のローカルステートファイルは、いつ発生してもおかしくない災害です。パイプラインは常に同じ信頼できるステートソースを使用する必要があります。

設定バージョン管理:何を持っていたかを把握する

アプリケーションコードにはバージョンタグが付けられます。インフラ設定にも同じ処理が必要です。IaCテンプレート、モジュール、変数ファイルへのすべての変更は、明確なマーカーとともにバージョン管理にコミットされるべきです。

チームがロールバックを決定するとき、最後に動作していた設定がどれだったかを推測する必要があってはなりません。特定のコミットやタグを指して「これだ」と言えるべきです。パイプラインはその時点に対応するステートファイルを使用してそのバージョンを適用します。

これは明白に聞こえますが、多くのチームはインフラ設定を「とにかく最新をデプロイ」として扱い、リリースにタグを付けません。何かが壊れたとき、誰かが途中で未完成の変更をプッシュしていないか心配しながら、最後に正常だったコミットを必死に探すことになります。

適用前にロールバックを計画する

ロールバックを計画する最適なタイミングは、変更を適用する前です。パイプラインで、applyステップを実行する前に現在のステートのコピーを保存します。変更が問題を引き起こした場合、パイプラインは保存されたステートを使ってすぐにapplyを実行できます。検索も推測も手動ステップも不要です。

この事前計画されたロールバックは自動化できます。applyの完了後にヘルスチェックを実行します。ヘルスチェックが失敗した場合、自動的にロールバックをトリガーします。チームには通知が届きますが、復旧はすでに開始されています。

例えば、EC2インスタンスのような単一リソースへの変更が問題を引き起こした場合、そのリソースを特定してロールバックできます:

# 変更を適用する前に現在のステートを保存
terraform state pull > state-backup-$(date +%Y%m%d-%H%M%S).json

# 問題のあるリソースのみに以前の設定を適用
terraform apply -auto-approve -target=aws_instance.web

# ヘルスチェックでロールバックを検証
terraform output instance_health

すべてのインフラ変更がきれいにロールバックできるわけではありません。データベースボリュームの削除、他のリソースが依存するネットワークスキーマの変更、共有サービスの変更など、これらのアクションは元に戻すための明確な経路を残さない場合があります。このような変更には、追加の戦略が必要です。

ロールバックだけでは不十分な場合

一部のインフラ変更は本質的に破壊的です。変更でデータベースボリュームを削除した場合、IaC設定をロールバックしてもデータは戻ってきません。ボリュームはもう存在しません。設定ファイルには存在すべきと書かれていますが、実際のリソースはクラウドプロバイダーにもうありません。

以下のフローチャートは、変更が本番環境を壊した場合の判断プロセスを示しています:

flowchart TD A[変更が本番環境を壊す] --> B{変更を<br/>きれいにロールバックできるか?} B -->|はい| C[保存されたステートファイルから<br/>以前の状態を復元] B -->|いいえ| D{変更前に<br/>スナップショットを取得したか?} D -->|はい| E[スナップショットから復元し、<br/>古い設定を適用] D -->|いいえ| F{古い環境が<br/>まだ稼働しているか?} F -->|はい| G[トラフィックを<br/>古い環境に戻す] F -->|いいえ| H[最後に正常だった設定から<br/>新しいリソースをプロビジョニング] C --> I[ヘルスチェックを実行] E --> I G --> I H --> I I --> J{ヘルスチェック<br/>合格?} J -->|はい| K[復旧完了] J -->|いいえ| L[オンコールエンジニアに<br/>エスカレーション]

このようなケースでは、ロールバックを超えた復旧戦略が必要です:

  • 破壊的な変更を行う前にスナップショットを取得する。スキーママイグレーションの直前に取得したデータベーススナップショットは、フォールバックポイントとなります。
  • インフラにブルーグリーンまたはカナリアデプロイメントを使用する。新しい環境が機能することに確信が持てるまで、古い環境を稼働させ続けます。
  • インプレースで変更するのではなく、並行してインフラをプロビジョニングする。古いリソースと並行して新しいリソースを作成し、準備ができたらトラフィックを切り替えます。

これらの戦略はコストと複雑さを増加させますが、長時間の障害よりは安上がりです。

ロールバックをテストする

テストされたことのないロールバック計画は、計画ではなく願望です。

ステージング環境でロールバック訓練を実施してください。変更を適用し、意図的にロールバックをトリガーします。所要時間を測定し、ステートファイルが正しく復元されることを確認し、すべてのリソースが以前の設定に戻ることを検証し、ロールバック後にアプリケーションが正しく動作することを確認します。

これを定期的に行ってください。数ヶ月ごと、またはインフラ設定が大幅に変更されたときはいつでも。目標はメカニズムが機能することを確認するだけでなく、チームの自信を構築することです。午前2時に本番環境が壊れたとき、チームが初めてドキュメントを読むのではなく、何をすべきかを正確に知っている状態にしたいのです。

ロールバック後:学びと文書化

ロールバックが完了し、本番環境が安定したら、本当の作業が始まります。何が問題だったのかを突き止めてください。依存関係の欠落でしたか?環境間の設定ドリフトでしたか?適用順序の競合状態でしたか?

インシデントを文書化してください。どのような変更が適用されたか?何が壊れたか?どのように検出されたか?ロールバックにどれくらい時間がかかったか?何があればより速くなったか?この文書は、パイプライン、テスト、ロールバック手順を改善するための基礎となります。

インフラロールバック準備のための実践的チェックリスト

  • ステートファイルはアクセス制御とバージョン管理とともにリモートに保存されている
  • すべてのインフラ変更はバージョン管理でタグ付けされている
  • パイプラインは変更を適用する前に現在のステートを保存する
  • すべての適用後に自動ヘルスチェックが実行される
  • ヘルスチェック失敗時にロールバックが自動的にトリガーされる
  • 破壊的な変更にはスナップショットまたは並行デプロイメント戦略がある
  • ロールバックは少なくとも四半期に1回ステージングでテストされる
  • インシデント文書はロールバックのたびに作成されレビューされる

具体的な要点

インフラのロールバックは後から追加する機能ではありません。最初から行う設計上の決定です。ステート管理を計画し、設定をバージョン管理し、ロールバックパスを自動化し、退屈になるまでテストしてください。本番環境が壊れたとき、チームは復旧方法を考えているのではなく、以前に何度も実行した手順を実行し、どれくらいの時間がかかり、結果がどうなるかを正確に知っている状態であるべきです。