災害復旧と RTO/RPO ガイド
このドキュメントでは、EKB AWS/EKS インフラストラクチャの災害復旧 (DR) 戦略、目標復旧時間 (RTO)、および目標復旧時点 (RPO) について説明します。組み込みの HA 機能、アクティブなバックアップ システム、リカバリ手順、既知のギャップについて説明します。
デプロイ手順については、Terragrunt デプロイ ガイド を参照してください。
アーキテクチャと高可用性の概要
インフラストラクチャコンポーネント
| コンポーネント | 実装 | HA モデル |
|---|---|---|
| Compute | EKS (Kubernetes 1.33) + Karpenter | Multi-AZ nodes, Spot + On-Demand |
| Pod autoscaling | KEDA | CPU/Memory-based, min 2 replicas |
| Ingress / SSL | ALB + ACM | Multi-AZ, health-check routing |
| Cache | ElastiCache Redis (conditional) | Multi-AZ with automatic failover |
| Message queue | Amazon MQ / RabbitMQ (conditional) | Single-instance or active/standby |
| Database (self-hosted) | CloudNativePG HA cluster + PgBouncer | Primary + replicas, auto-failover |
| Database (cloud) | Supabase Cloud | Managed, cross-region by provider |
| Observability | SigNoz + k8s-infra (conditional) | In-cluster, no single point of failure |
| IaC state | S3 (versioned) + DynamoDB lock | Encrypted, versioned |
| Persistent volumes | EBS (via EBS CSI Driver) | Snapshots via AWS Data Lifecycle Manager |
現在の HA 機能
| 機能 | 回復時間 | データ損失 | ステータス |
|---|---|---|---|
| AZ 障害 (pods) | 0–5 分 | なし | Active |
| Pod 障害 / クラッシュ | 0–2 分 | なし | Active |
| ALB ヘルスチェック再ルーティング | 0–1 分 | なし | Active |
| Redis Multi-AZ フェイルオーバー | < 1 分 | なし | Active (when enabled) |
| Karpenter ノード置換 | 0–10 分 | なし | Active |
| EBS スナップショット復元 | 15–30 分 | 最大 24 時間 | Active |
| CloudNativePG PITR 復元 | 15–60 分 | WAL ラグまで | Active (when enabled) |
| 完全なインフラストラクチャ再作成 | 30–60 分 | なし (IaC) | Via Terragrunt |
RTO / RPO ターゲット
| シナリオ | RTO ターゲット | RPO ターゲット | 現在の機能 |
|---|---|---|---|
| 単一 Pod 障害 | < 2 分 | 0 | 達成 (KEDA min replicas) |
| 単一ノード障害 | < 10 分 | 0 | 達成 (Karpenter 置換) |
| AZ 障害 | < 5 分 | 0 | 達成 (Multi-AZ スプレッド) |
| Redis 障害 | < 1 分 | 0 | 達成 (Multi-AZ フェイルオーバー) |
| Postgres プライマリ障害 | < 5 分 | 0–数秒 WAL ラグ | 達成 (CNPG 自動フェイルオーバー) |
| EBS ボリューム消失 | 15–30 分 | < 24 時間 | 部分的 — DLM スナップショットは毎日 |
| 完全なリージョン障害 | > 60 分 | バックアップ頻度に依存 | 現在自動化されていません |
バックアップ システム
1. Terraform / Terragrunt 状態 — S3
バックアップの内容: すべてのインフラストラクチャの状態 (EKS、ネットワーキング、IAM、Helm リリース)。
実装:
- 環境ごとの S3 バケット:
ekb-terraform-state-<env-name>(terragrunt/environments/<env-name>/state/経由でブートストラップ) - バージョニングが有効 — 以前の状態のバージョンを復元できます
- サーバー側暗号化 (AES-256)
- 状態ロック用の DynamoDB テーブル
リカバリ: S3 内の以前の状態バージョンにロールバックしてから、terragrunt apply を再実行します。
RPO: terragrunt apply コミットごと — 継続的。
2. EBS 永続ボリューム — AWS Data Lifecycle Manager
バックアップの内容: ポッドに接続された EBS ボリューム (Automator PostgreSQL、Supabase MinIO、ステートフル ワークロード)。
実装: 環境タグを対象とした AWS Data Lifecycle Manager (DLM) ポリシー。
# Tag EBS volumes with your environment name, then create a DLM policy:
# - Resource: EBS volumes
# - Target tag: Environment=<your-env-name>
# - Schedule: Daily at 02:00 UTC
# - Retention: 7 snapshots
回復:
# 1. Identify the snapshot to restore
aws ec2 describe-snapshots --filters "Name=tag:Environment,Values=<your-env-name>"
# 2. Create a volume from the snapshot
aws ec2 create-volume \
--snapshot-id snap-xxxxxxxxxxxxxxxxx \
--availability-zone <your-az> \
--volume-type gp3
# 3. Update the PersistentVolume in Kubernetes to reference the new volume ID
kubectl patch pv <pv-name> -p '{"spec":{"awsElasticBlockStore":{"volumeID":"<new-vol-id>"}}}'
RPO: 最大 24 時間 (毎日のスナップショット)。 DLM スケジュールの頻度を増やすことで削減します。
3. CloudNativePG (HA Supabase DB) — Barman クラウド バックアップ
適用対象: ENABLE_CNPG=true および ENABLE_HA_SUPABASE_DB=true を含む環境。
バックアップの内容: CloudNativePG Postgres クラスター (ha-supabase-db)。これには、S3 または MinIO への継続的な WAL (先行書き込みログ) ストリーミングと、CNPG ScheduledBackup CRD を介したスケジュールされた完全なベース バックアップが含まれます。
実装 (values/ha-supabase-db.yaml で構成):
postgres:
backup:
enabled: true # toggle barman-cloud backups
# barmanObjectStore points to S3 bucket or MinIO endpoint
# IRSA / service account must have s3:PutObject, s3:GetObject, s3:ListBucket
retentionPolicy: "30d" # keep backups for 30 days
compression: gzip
バックアップ ステータスを確認:
# List all backups for the cluster
kubectl get backup -n ha-supabase-db
# Check a specific backup
kubectl describe backup <backup-name> -n ha-supabase-db
# Trigger an on-demand backup
kubectl cnpg backup ha-supabase-db -n ha-supabase-db
ポイントインタイムリカバリ (PITR):
# Create a new CNPG Cluster restoring from a backup
# (in a new namespace or after removing the original)
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: ha-supabase-db-restored
namespace: ha-supabase-db-restore
spec:
instances: 3
bootstrap:
recovery:
source: ha-supabase-db
recoveryTarget:
targetTime: "2026-03-19T03:00:00.000000+00:00" # target point in time
externalClusters:
- name: ha-supabase-db
barmanObjectStore:
# same S3/MinIO config as the source cluster
serverName: ha-supabase-db
RPO: WAL 対応クラスターではほぼゼロ (WAL アップロード間隔によって制限される数秒の遅れ)。
4. ElastiCache Redis — マルチ AZ レプリケーション
適用対象: ENABLE_AWS_SERVICES=true のある環境。
Redis はプライマリ データ ストアではなく、一時的なキャッシュ データとセッション データを保持します。 DR では、バックアップ/リストアではなく、高速フェイルオーバーに焦点を当てています。
実装:
- 自動フェイルオーバーによるマルチ AZ の有効化
- 保存時および転送中の暗号化
- プライマリ ノードの障害により、レプリカが自動的に昇格されます (< 1 分)
RPO: Redis データは設計上一時的です。フェイルオーバー後のキャッシュミスが予想されます。アプリケーションはデータベースから再入力されます。
5. Amazon MQ (RabbitMQ) — メッセージキュー
適用対象: ENABLE_AWS_SERVICES=true のある環境。
実装:
- 単一インスタンス (デフォルト) またはアクティブ/スタンバイ展開
- ブローカーの再起動中に、送信中のメッセージが失われる可能性があります。消費者が冪等になるように設計してください
- 管理 UI はポート 15671 (SSL) で利用可能
RPO: 単一インスタンス — 障害時に送信中のメッセージが失われる可能性があります。このリスクを軽減するには、アクティブ/スタンバイ展開モードを使用してください。
自動回復メカニズム
Karpenter — ノードのプロビジョニングとリカバリ
- 統合:
WhenEmptyOrUnderutilized— アイドル状態のノードは自動的に終了します - スポット割り込み処理: SQS 割り込みイベントをリッスンします。終了前にスポットノードをドレインして置き換えます
- ノード ドリフト: 古い AMI または構成を使用しているノードは、
enable_drift = trueの場合に自動的に置き換えられます - 回復時間: 新しいノードが 0 ~ 10 分でプロビジョニングされます
KEDA — ポッドの自動スケーリング
- 最小レプリカ数: すべてのサービス (Web、API、Celery、Automator) で 2 — 単一障害点を防止します
- CPU しきい値: 60 ~ 70% でスケールアウトがトリガーされます
- メモリしきい値: 80% でスケールアウトがトリガーされます
- スケールダウン安定化: 30 秒 — バタつきを回避します
- 回復時間: 失敗したポッドは 0 ~ 2 分以内に再スケジュールされます
Kubernetes ポッドのアンチアフィニティ
すべてのステートレス サービスは、kubernetes.io/hostname の preferredDuringSchedulingIgnoredDuringExecution アンチアフィニティを使用して、ノードと AZ にポッドを分散します。
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values: ["web", "fastapi-backend", "celery-worker", "automator"]
topologyKey: kubernetes.io/hostname
回復手順
シナリオ 1: AZ の障害
予想される動作: Karpenter は残りの AZ に交換ノードをプロビジョニングします。 KEDA はポッドを再スケジュールします。 ALB は、異常なターゲットへのルーティングを停止します。
検証:
kubectl get nodes -o wide # confirm nodes are in healthy AZs
kubectl get pods -A -o wide # confirm pods are running
kubectl get ingress # confirm ALB is routing correctly
通常の状況では、手動介入は不要です。
シナリオ 2: Postgres プライマリ ノードの障害 (CloudNativePG)
CloudNativePG は、レプリカを自動的にプライマリに昇格させます。
# Monitor failover
kubectl get cluster ha-supabase-db -n ha-supabase-db -w
# Confirm new primary
kubectl cnpg status ha-supabase-db -n ha-supabase-db
# Check PgBouncer pooler is pointing to new primary
kubectl get svc -n ha-supabase-db | grep pooler
アプリケーションは PgBouncer 経由で再接続します。接続文字列を変更する必要はありません。
シナリオ 3: スナップショットから EBS ボリュームを復元する
# 1. Find snapshots for the environment
aws ec2 describe-snapshots \
--filters "Name=tag:Environment,Values=<your-env-name>" \
--query 'Snapshots[*].[SnapshotId,StartTime,VolumeSize]' \
--output table
# 2. Create a new volume from the chosen snapshot
aws ec2 create-volume \
--snapshot-id snap-xxxxxxxxxxxxxxxxx \
--availability-zone <target-az> \
--volume-type gp3 \
--tag-specifications 'ResourceType=volume,Tags=[{Key=Environment,Value=<your-env-name>}]'
# 3. Scale down the affected workload
kubectl scale deployment <workload> --replicas=0
# 4. Update the PV to reference the new EBS volume, then scale back up
kubectl patch pv <pv-name> -p '{"spec":{"csi":{"volumeHandle":"<new-volume-id>"}}}'
kubectl scale deployment <workload> --replicas=2
シナリオ 4: インフラストラクチャの完全な再構築
致命的な障害が発生した後、またはリージョンを再構築するときに使用されます。
# 1. Bootstrap state bucket (if it doesn't exist)
cd terragrunt/environments/<your-env-name>/state
terragrunt apply
# 2. Recreate the EKS cluster and core infrastructure
cd terragrunt/environments/<your-env-name>
terragrunt apply
# 3. Deploy services in order (see Terragrunt Deployment Guide § Phase 6)
ENABLE_CNPG=true terragrunt apply --target='helm_release.local["cloudnative-pg"]'
ENABLE_HA_SUPABASE_DB=true terragrunt apply --target='helm_release.local["ha-supabase-db"]'
ENABLE_SUPABASE=true terragrunt apply --target='helm_release.local["supabase"]'
推定 RTO: 完全なクラスターの場合は 30 ~ 60 分。 EBS/CNPG データを復元する必要がある場合は 60 ~ 120 分。
シナリオ 5: Terragrunt 状態のロールバック
# List state versions in S3
aws s3api list-object-versions \
--bucket ekb-terraform-state-<your-env-name> \
--prefix <state-key>
# Restore a specific version
aws s3api get-object \
--bucket ekb-terraform-state-<your-env-name> \
--key <state-key> \
--version-id <version-id> \
terraform.tfstate
# Re-import or apply with the restored state
可観測性とアラート (SigNoz)
ENABLE_SIGNOZ=true の場合、SigNoz は monitoring 名前空間にデプロイされ、以下を提供します。
- すべての EKB サービスの分散トレース
- k8s-infra DaemonSet エージェント経由のクラスター メトリック (CPU、メモリ、ポッド ステータス)
- すべてのポッドからのログの集計
- アラート — SigNoz でアラート ルールを設定して、ポッドのクラッシュ ループ、高いエラー率、またはノードの負荷を通知します
DR の目的では、SigNoz ダッシュボードは、インシデント後の診断と回復の確認のための主要なツールです。 SigNoz データ自体は EBS PV に保存され、EBS スナップショット ポリシーの対象となります。
ギャップと推奨事項
| ギャップ | リスク | 推奨事項 |
|---|---|---|
| クロスリージョンレプリケーションなし | 完全なリージョン障害 = RTO の延長 | CNPG バックアップ用の RDS クロスリージョン読み取りレプリカまたは S3 クロスリージョンレプリケーションを検討してください |
| EBS スナップショットは毎日 | EBS ベースのワークロードで最大 24 時間のデータ損失 | 重要なボリュームの DLM 頻度を時間単位に増やしてください |
| RabbitMQ 単一インスタンス (デフォルト) | ブローカー障害時に送信中のメッセージが失われる | 本番環境では ACTIVE_STANDBY_MULTI_AZ 展開モードに切り替えてください |
| 自動 DR ドリルなし | 必要になるまで回復手順が未テスト | 四半期ごとの回復ドリルをスケジュールしてください。ステージング環境で CNPG PITR 復元をテストしてください |
| 同じクラスター上の SigNoz | クラスター障害時に可観測性が失われる | 別の軽量な監視エンドポイントまたは CloudWatch フォールバックアラートを検討してください |