目次
30 章

災害復旧・バックアップ — バックアップ · リージョン間 DR · RTO/RPO

1つの AZ や1つのリージョンが崩れたときにデータとサービスを復旧する設計。RTO/RPO を先に定め、RDS PITR · S3 バージョン管理と Cross-Region Replication · AWS Backup でバックアップを Terraform で押さえる方法、Pilot Light · Warm Standby · Multi-Site のリージョン間 DR パターンと Route 53 フェイルオーバーを整理します。

第1章 で Multi-AZ は1つの AZ 障害に耐える運用の基本だと述べ、第11章 RDS で Multi-AZ オプションを扱いました。この章はそれより一段上の問いを扱います — バックアップは実際に復旧できるのか、そして1つのリージョン全体が崩れたらどうするのか です。

災害復旧(DR)は普段は見えないのに、事故が起きたときに会社の生死を分けます。要点は2つの数字を先に決めることです — どれだけ長く止まってよいか(RTO)、どれだけのデータを失ってよいか(RPO)。この章のバックアップ・DR 設計は、第29章 セキュリティガバナンス のアカウント分離、6部 キャップストーン の運用チェックリストと併せて見ます。

まず2つの数字 — RTO と RPO #

指標意味問い
RTO (Recovery Time Objective)復旧までの許容時間「何時間以内に再び立ち上がらなければならないか?」
RPO (Recovery Point Objective)許容するデータ損失「最後のバックアップ以降、どこまで失ってよいか?」

RTO 4時間 / RPO 1時間なら、4時間以内に復旧するが事故直前1時間分のデータは失いうる、という意味です。この2つの数字が小さいほどコストが急激に上がります。 だから DR 設計は「どれだけ頑丈に」ではなく「このサービスに RTO/RPO が実際にいくつであるべきか」から始めます。社内管理ツールと決済システムの答えはまったく異なります。

バックアップ — データを失わない #

DR の土台はバックアップです。サービスごとにツールが異なります。

RDS — 自動バックアップと PITR #

  • 自動バックアップ — 保持期間(最大35日)の中で毎日スナップショット + トランザクションログを残します。backup_retention_period で有効化します。
  • PITR(Point-in-Time Recovery) — 保持期間内の 任意の時点(秒単位)へ新しいインスタンスを復元します。誤ってテーブルを消した5分前に戻せます。
  • 手動 / 自動スナップショットのリージョン間コピー — 別のリージョンに複製を置いてリージョン障害に備えます。
RDS バックアップ保持 + リージョン間自動コピー
resource "aws_db_instance" "main" {
  identifier              = "myapp-prod"
  backup_retention_period = 14                  # 14日 PITR 可能
  backup_window           = "17:00-17:30"       # UTC (KST 02:00)
  copy_tags_to_snapshot   = true
}

# 自動バックアップを DR リージョンへレプリケーション (別リージョンの provider)
resource "aws_db_instance_automated_backups_replication" "dr" {
  provider               = aws.dr            # 例: us-west-2
  source_db_instance_arn = aws_db_instance.main.arn
  retention_period       = 14
}

復旧は上書きせず、時点を指定して新しいインスタンスを立ち上げます。元を上書きせず 新しいインスタンスとして復元 したあとアプリの接続を切り替えるのが安全です。

ミス直前の時点へ RDS を復元
aws rds restore-db-instance-to-point-in-time \
  --source-db-instance-identifier myapp-prod \
  --target-db-instance-identifier myapp-restored \
  --restore-time 2026-05-24T09:25:00Z

Aurora Serverless v2 は、非prod / アイドルな DB なら 最小容量 0 ACU(自動一時停止) に置いて、止まっている間のコンピューティングコストを 0 にできます(ストレージのみ課金)。ただし常に最新を保つ必要がある DR リージョンの読み取り複製は一時停止してはいけないので、低い最小 ACU で起動しておきます。

S3 — バージョン管理と Cross-Region Replication #

  • バージョン管理(Versioning) — オブジェクトを上書きしたり消したりしても以前のバージョンが残ります。誤削除とランサムウェア対策の基本です。
  • レプリケーション(CRR: Cross-Region Replication) — 別のリージョン / アカウントのバケットへ自動レプリケーションしてリージョン障害に備えます。バージョン管理が有効になっている必要があります。
  • オブジェクトロック(Object Lock) — 規制データを一定期間削除不可で固定します。
S3 バージョン管理 + リージョン間レプリケーション
resource "aws_s3_bucket_versioning" "main" {
  bucket = aws_s3_bucket.main.id
  versioning_configuration { status = "Enabled" }
}

resource "aws_s3_bucket_replication_configuration" "crr" {
  bucket = aws_s3_bucket.main.id
  role   = aws_iam_role.replication.arn
  rule {
    id     = "to-dr"
    status = "Enabled"
    destination {
      bucket        = aws_s3_bucket.dr.arn   # DR リージョンのバケット
      storage_class = "STANDARD_IA"
    }
  }
}

AWS Backup — 一か所でまとめて管理 #

サービスごとに別々にバックアップを設定すると漏らしやすくなります。AWS Backup は RDS · EBS · EFS · DynamoDB · S3 などのバックアップポリシーを 一か所で 定め、保持期間 · リージョン間コピー · バックアップ検証を自動化します。

AWS Backup プラン — 日次バックアップ + DR リージョンコピー
resource "aws_backup_plan" "daily" {
  name = "daily-with-dr-copy"
  rule {
    rule_name         = "daily"
    target_vault_name = aws_backup_vault.main.name
    schedule          = "cron(0 17 * * ? *)"   # 毎日 UTC 17:00
    lifecycle { delete_after = 35 }
    copy_action {
      destination_vault_arn = aws_backup_vault.dr.arn   # DR リージョンの vault
      lifecycle { delete_after = 35 }
    }
  }
}

# タグでバックアップ対象を自動選択 (Backup=true タグが付いた全リソース)
resource "aws_backup_selection" "tagged" {
  name         = "tagged-resources"
  plan_id      = aws_backup_plan.daily.id
  iam_role_arn = aws_iam_role.backup.arn
  selection_tag {
    type  = "STRINGEQUALS"
    key   = "Backup"
    value = "true"
  }
}

第29章 の Organizations と束ねれば、バックアップポリシーを組織全体に一括適用 でき、新しいアカウントも自動でバックアップ対象になります。

バックアップは復旧してみて初めてバックアップです。 復元手順を実際に回して RTO を測ってみていないバックアップは「あると信じているバックアップ」にすぎません。四半期ごとの復元訓練を推奨します。

リージョン間 DR パターン #

1つのリージョン全体が崩れることはまれですが、起きれば Multi-AZ では防げません。別のリージョンにどれだけ準備しておくかで4つのパターンに分かれます。下へ行くほど RTO/RPO が小さくコストが大きくなります。

パターン普段の状態RTOコスト適合
Backup & Restoreバックアップだけ別リージョンに時間 ~ 日最低社内ツール、非中核
Pilot Light最小コア(DB レプリケーション)だけ起動数十分 ~ 時間一般サービス
Warm Standby縮小規模で常に起動数分 ~ 数十分売上影響の大きいサービス
Multi-Site (Active-Active)2つのリージョンが同時にトラフィック処理ほぼ 0最高無停止が必須のサービス

Pilot Light — 実戦の出発点 #

ほとんどのサービスに現実的な最初の DR は Pilot Light です。

  • DR リージョンに DB だけレプリケーション して常に最新に保ちます(RDS read replica または自動バックアップレプリケーション)。
  • アプリ(ECS / Lambda)とネットワークは Terraform コードで定義だけ しておき、普段は desired_count = 0 であるか、apply していない状態にしておきます。
  • 事故時には DR リージョンに Terraform でアプリを立ち上げ(または desired_count を上げ)、Route 53 でトラフィックを切り替えます。
  • 普段のコストは DB レプリケーション分くらいで低く、RTO は「アプリを立ち上げる時間 + DNS 伝播」です。

第32章 キャップストーン のインフラが Terraform でコード化されていれば、DR リージョンの復旧は「同じモジュールを DR リージョンの provider で apply」で単純になります。IaC が DR の前提 である理由です(第25章 Terraform 入門)。

Route 53 で切り替え #

リージョン切り替えのスイッチは 第12章 Route 53 です。ヘルスチェック + フェイルオーバールーティングで、主リージョンが死ぬと自動で DR リージョンの DNS へ渡します。

Route 53 フェイルオーバー — primary/secondary
resource "aws_route53_health_check" "primary" {
  fqdn              = "primary.example.com"
  type              = "HTTPS"
  resource_path     = "/health"
  failure_threshold = 3
  request_interval  = 30
}

resource "aws_route53_record" "primary" {
  zone_id        = data.aws_route53_zone.main.zone_id
  name           = "api.example.com"
  type           = "A"
  set_identifier = "primary"
  failover_routing_policy { type = "PRIMARY" }
  health_check_id = aws_route53_health_check.primary.id
  alias {
    name                   = aws_lb.primary.dns_name
    zone_id                = aws_lb.primary.zone_id
    evaluate_target_health = true
  }
}

resource "aws_route53_record" "secondary" {
  zone_id        = data.aws_route53_zone.main.zone_id
  name           = "api.example.com"
  type           = "A"
  set_identifier = "secondary"
  failover_routing_policy { type = "SECONDARY" }
  alias {
    name                   = aws_lb.dr.dns_name      # DR リージョンの ALB
    zone_id                = aws_lb.dr.zone_id
    evaluate_target_health = true
  }
}

Multi-Site ではフェイルオーバーの代わりに重み付け(weighted)または遅延(latency)ルーティングで、2つのリージョンに常にトラフィックを分配します。

1枚の判断フロー #

  1. サービスごとの RTO / RPO をまず書きます。全社一律の値はありません。
  2. バックアップ(RDS PITR + S3 バージョン管理 + AWS Backup、リージョン間コピー含む)をすべてのサービスに敷きます。ここまでが最低線です。
  3. RTO/RPO が時間単位で許容されるなら Backup & Restore で十分です。
  4. 分単位が必要なら Pilot Light → Warm Standby へ上げます。
  5. 無停止が売上に直結するなら Multi-Site を検討しますが、コストと運用の複雑さが最も大きいです。
  6. どのパターンでも 復元訓練で RTO を実測 します。

練習問題 #

  1. ご自身のサービス(または架空のサービス)の RTO と RPO を数字で書き、その根拠(止まったときの事業への影響)を1段落で書いてください。その数字に §「リージョン間 DR パターン」の4つのパターンのどれが合うかを選んでください。
  2. 運用者が誤って prod テーブルを DROP しました。RDS PITR と S3 バージョン管理のどちらがこの事故を復旧するのか、そして元を上書きせず新しいインスタンスとして復元したあとサービスを立て直す手順を §「バックアップ」の CLI を根拠に書いてみてください。
  3. Pilot Light が Warm Standby より安い理由を「普段に何が起動しているか」(DB だけ vs 縮小アプリまで)の観点で説明し、第25章 Terraform 入門 の IaC がなぜ Pilot Light の前提になるかを1段落で書いてみてください。

一行まとめ: DR は RTO(許容停止時間)と RPO(許容データ損失)の2つの数字をサービスごとに定めるところから始まり、この数字が小さいほどコストが急騰する。土台はバックアップ — RDS は backup_retention_period + PITR + 自動バックアップのリージョンレプリケーション、S3 はバージョン管理 + CRR、AWS Backup はタグ選択で RDS/EBS/S3 などを1つのプランに束ねて DR リージョン copy まで自動化する。復元訓練で RTO を実測する。リージョン間 DR は Backup & Restore → Pilot Light → Warm Standby → Multi-Site へ行くほど RTO が小さく高価で、ほとんどは DB だけレプリケーションしてアプリは Terraform で立ち上げる Pilot Light が現実的な出発点。切り替えのスイッチは Route 53 ヘルスチェック + フェイルオーバールーティングで、IaC が DR の前提。

次の章 #

次の 第31章 Lambda 深掘り では、第17章 Lambda 基礎 の上に production 運用の観点を加えます。コールドスタートと Provisioned Concurrency、Layers とコンテナイメージのパッケージング、Lambda Powertools ベースの可観測性、Step Functions との結合、そしてコストのトレードオフを扱います。

X