メインコンテンツへスキップ

災害復旧と RTO/RPO ガイド

このドキュメントでは、EKB AWS/EKS インフラストラクチャの災害復旧 (DR) 戦略、目標復旧時間 (RTO)、および目標復旧時点 (RPO) について説明します。組み込みの HA 機能、アクティブなバックアップ システム、リカバリ手順、既知のギャップについて説明します。

情報

デプロイ手順については、Terragrunt デプロイ ガイド を参照してください。


アーキテクチャと高可用性の概要​

インフラストラクチャコンポーネント​

コンポーネント実装HA モデル
ComputeEKS (Kubernetes 1.33) + KarpenterMulti-AZ nodes, Spot + On-Demand
Pod autoscalingKEDACPU/Memory-based, min 2 replicas
Ingress / SSLALB + ACMMulti-AZ, health-check routing
CacheElastiCache Redis (conditional)Multi-AZ with automatic failover
Message queueAmazon MQ / RabbitMQ (conditional)Single-instance or active/standby
Database (self-hosted)CloudNativePG HA cluster + PgBouncerPrimary + replicas, auto-failover
Database (cloud)Supabase CloudManaged, cross-region by provider
ObservabilitySigNoz + k8s-infra (conditional)In-cluster, no single point of failure
IaC stateS3 (versioned) + DynamoDB lockEncrypted, versioned
Persistent volumesEBS (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 フォールバックアラートを検討してください