ロールバック
デプロイやデータ変更を以前の状態に戻し、障害からの復旧を行う操作
ロールバックとは
ロールバック (Rollback) は、デプロイやデータ変更に問題が発生した際に、以前の正常な状態に戻す操作である。迅速なロールバックは MTTR (平均復旧時間) を短縮し、障害の影響を最小化する。
ロールバック戦略
戻す対象がコードだけなのか、データやスキーマを含むのかで難易度が一桁変わる。前者は成果物を差し替えれば済むが、後者は既に書き込まれたデータを巻き戻す必要があり、時間もリスクも大きくなる。
| 戦略 | 速度 | リスク |
|---|---|---|
| Blue/Green の向き先切り替え | 数秒〜数分 | 低い |
| 前バージョンの再デプロイ | 数分 | 低い |
| CloudFormation ロールバック | 数分〜数十分 | 中程度 |
| DB マイグレーションの巻き戻し | 数分〜数時間 | 高い |
向き先切り替えの速さは、どの層で切り替えるかで決まる。ALB のリスナーやターゲットグループを差し替える方式なら、切り替え後の新規リクエストはその時点から旧環境へ向かう。一方 DNS レコードを書き換える方式では、権威サーバー側を変えても TTL の間はリゾルバやクライアントのキャッシュが古い値を返し続けるため、新環境へのアクセスが残る。DNS で切り戻す設計にするなら TTL を短く保ち、切り替え後も一定時間は旧環境を残す前提で組む。
Lambda のロールバック
エイリアスが指すバージョン番号を戻すだけで完了する。公開済みのバージョンはコードも設定も変更できないため、番号を指し直せば当時と同じ内容が確実に復元される。前提は、切り替え前のバージョン番号を記録しておくことである。
# エイリアスを前のバージョンに戻す
aws lambda update-alias \
--function-name my-function \
--name prod \
--function-version 5 # 前のバージョン
CloudFormation のロールバック
CloudFormation は更新中にエラーが起きると、既定で最後の安定した状態へ自動的に戻す。人が操作するのは、その自動ロールバックを止めて失敗した状態を調べたいときと、自動ロールバック自体が失敗したときである。
# 新規作成が失敗したときの挙動 (既定は ROLLBACK)
sam deploy --on-failure ROLLBACK
# 失敗した状態を残して原因を調べる (更新時は --disable-rollback)
sam deploy --on-failure DO_NOTHING
# CREATE_FAILED / UPDATE_FAILED のスタックを最後の安定状態へ戻す
aws cloudformation rollback-stack --stack-name my-stack
--on-failure はスタックの新規作成が失敗したときの挙動を指定するオプションで、値は ROLLBACK (既定) / DELETE / DO_NOTHING の 3 つ。DO_NOTHING は --disable-rollback と同じ効果になり、両者を同時に指定することはできない (2026 年 8 月時点)。
rollback-stack は任意の時点に戻せる取り消しボタンではない。適用できるのは CREATE_FAILED または UPDATE_FAILED のスタックだけで、戻り先は直近の *_COMPLETE 状態 (CREATE_COMPLETE・UPDATE_COMPLETE・UPDATE_ROLLBACK_COMPLETE など) である。安定状態を一度も持たないスタック、つまり初回作成が失敗したままのスタックに実行すると、戻すのではなくスタックが削除される。自動ロールバックの途中で失敗して UPDATE_ROLLBACK_FAILED に落ちた場合は、原因のリソースを手当てしたうえで continue-update-rollback で再開させる。
ECS のロールバック
自動で戻す経路は 2 つある。ローリング更新ではデプロイサーキットブレーカーが、新しいタスクが起動できない状態やヘルスチェックを通らない状態を検知してデプロイを失敗と判定し、直前の正常なデプロイへ戻す (EC2 起動タイプと Fargate で利用可能。ECS Anywhere の外部インスタンスでは非対応)。ターゲットグループを切り替える構成では CodeDeploy 側の自動ロールバックを使う。
# ローリング更新 + デプロイサーキットブレーカー
1. 新しいタスク定義 (v2) でサービスを更新
2. 新タスクの起動失敗・ヘルスチェック失敗が続く
3. デプロイを失敗と判定し、直前の正常なデプロイへ戻す
# ターゲットグループ切り替え (CodeDeploy)
1. v2 のタスクセットを別のターゲットグループに用意
2. 切り替え後の監視期間にアラームが発火
3. リスナーを v1 のターゲットグループへ戻す
どちらの経路も、判定に使うヘルスチェックの厳しさで効き方が変わる。プロセスが起動したかどうかだけを見ていると、起動はするが依存先に繋がっていない版を正常と誤認し、自動ロールバックが働かないまま障害が続く。
DB のロールバック
データは一度書き込まれると、戻すだけでは済まない。書き込みを受け付けたまま巻き戻せば、その間に入った新しいデータを失う。そのため実務では、後方互換性を保ったまま前進する Expand-Contract が第一選択になる。
| 方法 | 速度 | データ損失 |
|---|---|---|
| Expand-Contract パターン | 即座 (旧カラムに戻す) | なし |
| ダウンマイグレーション | 数分 | なし (設計次第) |
| スナップショットからの復元 | 数十分 | スナップショット以降のデータ |
| DynamoDB PITR | 数分〜数十分 | 復元時点以降のデータ |
Expand-Contract は、①新しいカラムを追加して新旧両方に書く ②読み取りを新カラムへ移す ③古いカラムを削除する、の 3 段に分ける手法である。②の段階では旧版のコードも新版のコードも同じデータを読めるため、アプリケーションだけを前の版に戻せば実質的なロールバックが完了する。逆に③を実行した後は戻り先が消えているので、③はもう戻さないと決めてから行う。詳細は データベースマイグレーション戦略 で扱う。
スナップショットや PITR からの復元は最後の手段になる。DynamoDB の PITR は元のテーブルを書き換えるのではなく必ず新しいテーブルへ復元するため、復元後にアプリケーションの参照先を切り替える作業が伴う。復元できる範囲も設定した保持期間 (1〜35 日) の中に限られ、最も新しい復元可能時点は現在時刻の 5 分ほど前である (2026 年 8 月時点)。
ロールバックできない変更
戻せない操作を先に把握しておくことが、ロールバック計画の出発点になる。
| 変更 | 理由 | 対策 |
|---|---|---|
| DB カラムの削除 | データが消える | Expand-Contract で段階的に |
| 暗号化キーの削除 | データが復号不能 | キーの削除を遅延 |
| S3 オブジェクトの削除 | バージョニングなしだと復元不能 | バージョニングを有効化 |
ロールバック計画
ロールバックは障害の最中に初めて実行する手順になりがちで、そこで詰まると復旧時間がそのまま延びる。デプロイ前に条件と手順を決め、平時に一度通しておく。
1. トリガー条件を数値で定義 (エラー率 > 5 %, レイテンシ > 2 秒)
2. 誰が判断し誰が実行するかまで含めて手順を文書化
3. 本番相当の環境で実際に戻してみる
4. 検知から復旧完了までの所要時間を見積もる
判断を現場の裁量に委ねると、原因調査が優先されて切り戻しが遅れる。数値の条件を先に決めておけば、原因が分からない段階でも戻す判断ができる。調査は戻してから行えばよい。
この記事は役に立ちましたか?