メインコンテンツまでスキップ

デプロイ戦略

このドキュメントの目的

SaaSアプリケーションのデプロイ戦略を理解し、安全かつ効率的にリリースを行うための設計ができるようになることが目標です。

IDサービスを題材にした具体例を使用しますが、設計原則自体はあらゆるSaaSに共通して適用できます。


どの戦略を選ぶか

デプロイ戦略は「何をリリースするか」と「止まったときの影響」で決まります。

選択フローチャート

リリース内容は?

├── バグ修正、設定変更、後方互換な変更
│ → ローリングアップデート(最もシンプル)

├── DB スキーマ変更を伴う新機能
│ │
│ └── ダウンタイムが許容できるか?
│ ├── YES → メンテナンスウィンドウで適用
│ └── NO → Blue-Green デプロイ

├── リスクが高い変更(認証フロー変更等)
│ │
│ └── 全ユーザーへの影響を段階的に確認したいか?
│ ├── YES → Canary デプロイ
│ └── NO → Blue-Green デプロイ

└── 特定のユーザー/テナントだけに先行リリースしたい
→ Feature Flags

判断基準の比較

判断軸ローリングBlue-GreenCanaryFeature Flags
ダウンタイム短いゼロゼロゼロ
ロールバック速度遅い瞬時速い瞬時
DB スキーマ変更後方互換のみ非互換も可後方互換のみ後方互換のみ
本番事前テストできないできる一部で検証Flag で制御
追加コストなし2倍(一時的)少しなし
複雑さ
適用場面通常リリーススキーマ変更、無停止必須大規模、高リスク段階的公開

サービスの重要度で判断する

サービスが止まったときの影響:

低: 社内ツール、バッチ処理
→ ローリングアップデートで十分

中: 一般的な Web アプリ
→ ローリング or Canary

高: 決済、認証、インフラ基盤
→ Blue-Green(瞬時ロールバック必須)

認証サービス(idp-server):
→ ダウンタイム = 全テナント・全ユーザーに影響
→ Blue-Green が基本、Canary を併用

デプロイ戦略の比較

主要なデプロイ戦略

デプロイ戦略の選択肢:

┌───────────────────────────────────────────────────────────────┐
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ ローリング │ │ Blue-Green │ │ Canary │ │
│ │ アップデート │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ │ 段階的に │ │ 2環境を │ │ 少量の │ │
│ │ 入れ替え │ │ 切り替え │ │ トラフィック │ │
│ │ │ │ │ │ で検証 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ ↑ ↑ ↑ │
│ │ │ │ │
│ シンプル 安全性重視 大規模サービス │
│ │
└───────────────────────────────────────────────────────────────┘

ローリングアップデート

既存のインスタンスを段階的に新バージョンに置き換えます。

ローリングアップデートの流れ:

Step 1: 初期状態
[v1] [v1] [v1] [v1] ← 4台すべてv1

Step 2: 1台目を更新
[v2] [v1] [v1] [v1] ← 1台をv2に更新、ヘルスチェック

Step 3: 2台目を更新
[v2] [v2] [v1] [v1] ← 問題なければ次を更新

Step 4: 3台目を更新
[v2] [v2] [v2] [v1]

Step 5: 完了
[v2] [v2] [v2] [v2] ← 全台v2に更新完了
利点欠点
追加リソース不要更新中にv1とv2が混在
Kubernetesのデフォルトロールバックに時間がかかる
シンプルな設定APIの後方互換性が必須

IDサービスの場合: トークンエンドポイントのレスポンスフォーマットを変更する場合、v1とv2が混在する期間があるため、クライアントが両バージョンのレスポンスを処理できる必要があります。


Blue-Greenデプロイ

2つの同一環境(Blue/Green)を用意し、トラフィックを一括で切り替えます。

Blue-Green デプロイの流れ:

Step 1: 初期状態(Blue がアクティブ)
ユーザー ──▶ [ロードバランサー] ──▶ Blue [v1] [v1]
Green [ ] [ ] (待機)

Step 2: Green に新バージョンをデプロイ
ユーザー ──▶ [ロードバランサー] ──▶ Blue [v1] [v1] (アクティブ)
Green [v2] [v2] (テスト中)

Step 3: トラフィックを Green に切り替え
ユーザー ──▶ [ロードバランサー] ──▶ Green [v2] [v2] (アクティブ)
Blue [v1] [v1] (待機)

Step 4: 問題があれば Blue に戻す(瞬時ロールバック)
ユーザー ──▶ [ロードバランサー] ──▶ Blue [v1] [v1] (アクティブ)
Green [v2] [v2] (停止)
利点欠点
瞬時の切り替え・ロールバック2倍のリソースが必要
本番同等環境での事前テストデータベース互換性の管理が必要
ダウンタイムなしコストが高い

IDサービスの場合: 認証サービスのダウンタイムは全テナントに影響するため、Blue-Greenデプロイにより無停止での切り替えが有効です。


Canaryデプロイ

新バージョンに少量のトラフィックを流し、問題がないことを確認してから段階的に拡大します。

Canary デプロイの流れ:

Step 1: Canary インスタンスをデプロイ(トラフィック5%)
ユーザー ──▶ [ロードバランサー] ──95%──▶ [v1] [v1] [v1] [v1]
──5%───▶ [v2] (Canary)

Step 2: メトリクスを監視(エラー率、レイテンシ)
エラー率 OK? レイテンシ OK? → 次のステップへ
異常あり? → 自動ロールバック

Step 3: トラフィックを段階的に拡大(25%)
ユーザー ──▶ [ロードバランサー] ──75%──▶ [v1] [v1] [v1]
──25%──▶ [v2]

Step 4: 全トラフィックを新バージョンへ(100%)
ユーザー ──▶ [ロードバランサー] ──100%─▶ [v2] [v2] [v2] [v2]
利点欠点
リスクの最小化設定が複雑
実際のトラフィックで検証監視基盤が必要
段階的な拡大が可能v1/v2混在期間がある

IDサービスの場合: 新しい認証フローを追加する場合、まず一部のテナントのトラフィックのみ新バージョンに流して検証してから全テナントに展開できます。


Feature Flags

コードレベルでの機能切り替えにより、デプロイとリリースを分離します。

Feature Flags の仕組み:

デプロイ: v1 → v2(新機能のコードを含む)
リリース: Feature Flag OFF → ON(機能を有効化)

┌──────────────────────────────────────────┐
│ if (featureFlags.isEnabled("new_auth")) { │
│ // 新しい認証ロジック │
│ } else { │
│ // 従来の認証ロジック │
│ } │
└──────────────────────────────────────────┘

デプロイ: 全ユーザーに v2 をデプロイ(Flag OFF)
有効化: 特定テナントのみ Flag ON → 段階的に拡大
ロールバック: Flag OFF にするだけ(再デプロイ不要)
利点欠点
デプロイとリリースの分離コードの複雑性が増加
テナント別の段階的リリースFlag管理のオーバーヘッド
瞬時の無効化(再デプロイ不要)古いFlagの削除漏れリスク

デプロイ戦略の比較まとめ

戦略ダウンタイムロールバック速度リソースコスト複雑さ
ローリングなし遅い(段階的)低い低い
Blue-Greenなし瞬時高い(2倍)中程度
Canaryなし速い中程度高い
Feature Flagsなし瞬時(Flag OFF)低い中程度

ロールバック設計

ロールバックの基本原則

デプロイが失敗した場合に、安全に前のバージョンに戻す仕組みが必要です。

ロールバックの判断フロー:

デプロイ完了


ヘルスチェック ──失敗──▶ 自動ロールバック

OK


Smoke Test ──失敗──▶ 自動ロールバック

OK


メトリクス監視(5分間)

├── エラー率 > 閾値 ──▶ 自動ロールバック
├── レイテンシ > 閾値 ──▶ 自動ロールバック

OK


デプロイ成功

自動ロールバックのトリガー

トリガー閾値(例)検出方法
ヘルスチェック失敗3回連続失敗ロードバランサー / Kubernetes Probe
エラー率の急増5%超過(通常時0.1%)APM / メトリクス監視
レイテンシの劣化P99が3倍以上に増加APM / メトリクス監視
クラッシュループPod再起動3回以上Kubernetes CrashLoopBackOff

データベースとの互換性

ロールバック時にデータベースの互換性が問題になるケースがあります。

危険なパターン:

v1 デプロイ中 → v2 デプロイ(DBマイグレーション) → ロールバック!
┌──────────┐ ┌──────────────────────┐ ┌──────────┐
│ DB: v1 │ │ DB: v2 │ │ App: v1 │
│ カラムA │ ──▶ │ カラムA削除, カラムB追加│ ──▶ │ DB: v2 │
└──────────┘ └──────────────────────┘ │ カラムAが │
│ 存在しない│
└──────────┘
↑ エラー!

安全なDBマイグレーション手順:

Phase 1: 新カラム追加(下位互換あり)
DB: カラムA + カラムB(追加)
App v1: カラムAを使用(カラムBは無視)

Phase 2: アプリケーション更新
DB: カラムA + カラムB
App v2: カラムBを使用(カラムAも読める)

Phase 3: 旧カラム削除(v2が安定した後)
DB: カラムB(カラムA削除)
App v2: カラムBを使用

環境管理

環境の分離

環境の昇格フロー:

┌──────────┐ ┌──────────┐ ┌──────────┐
│ Dev │───▶│ Staging │───▶│Production│
│ │ │ │ │ │
│・開発者 │ │・テスト │ │・全ユーザー│
│ のみ │ │ チーム │ │ │
│・最新 │ │・本番と │ │・本番 │
│ コード │ │ 同等構成 │ │ データ │
│・テスト │ │・テスト │ │・監視 │
│ データ │ │ データ │ │ アラート │
└──────────┘ └──────────┘ └──────────┘
自動 自動 手動承認
デプロイ デプロイ デプロイ

各環境の役割

環境目的データアクセス
Dev開発中の機能検証テストデータ開発者
Staging本番リリース前の最終検証本番に近いデータ開発・QA
Production実際のサービス提供本番データ全ユーザー

環境間の設定管理

環境ごとに異なる設定値を管理する方法です。

方式説明適用場面
環境変数DATABASE_URL, API_KEYシンプルな設定
設定ファイルapplication-staging.yml構造化された設定
シークレット管理AWS Secrets Manager, Vault等認証情報

原則: コードと設定を分離する。同じアーティファクト(Docker Image)を全環境で使用し、設定のみ環境変数で切り替えます。

同一イメージ・設定で切り替え:

Docker Image: idp-server:v1.2.3

├── Dev: DATABASE_URL=dev-db:5432
├── Staging: DATABASE_URL=staging-db:5432
└── Production: DATABASE_URL=prod-db:5432

リリース管理

セマンティックバージョニング

バージョン番号: MAJOR.MINOR.PATCH

v2.3.1
│ │ │
│ │ └── PATCH: バグ修正(後方互換あり)
│ └──── MINOR: 機能追加(後方互換あり)
└────── MAJOR: 破壊的変更(後方互換なし)
変更の種類バージョン
バグ修正PATCH (x.x.+1)トークン有効期限の計算バグ修正
新機能追加MINOR (x.+1.0)新しい認証方式の追加
破壊的変更MAJOR (+1.0.0)APIレスポンス形式の変更

リリースノートの構成

リリースノートにはユーザー・開発者が必要とする情報を記載します。

## v1.2.3 (2026-03-04)

### 新機能
- FIDO2認証フローを追加

### バグ修正
- リフレッシュトークンの有効期限計算を修正

### 破壊的変更
- なし

### セキュリティ
- 依存ライブラリの脆弱性を修正(CVE-YYYY-XXXXX)

### アップグレード手順
- 特別な手順は不要

変更ログの自動生成

コミットメッセージから変更ログを自動生成するには、Conventional Commits を使用します。

Conventional Commits の形式:

feat: FIDO2認証フローを追加
fix: リフレッシュトークンの有効期限計算を修正
docs: API仕様書を更新
chore: 依存ライブラリを更新

feat → 新機能 (MINOR)
fix → バグ修正 (PATCH)
feat! → 破壊的変更 (MAJOR)

デプロイの安全策

ヘルスチェック

デプロイ後にアプリケーションが正常に動作しているかを確認します。

チェック種別確認内容頻度
Livenessプロセスが生存しているか10秒ごと
Readinessリクエストを受け付けられるか5秒ごと
Startup起動が完了したか起動時のみ

IDサービスの場合:

Liveness:  GET /health → 200 OK
Readiness: GET /health/ready → 200 OK
・DB接続確認
・暗号鍵のロード確認
・テナント設定のロード確認

Smoke Test

デプロイ後に最小限のテストを実行し、基本的な機能が動作していることを確認します。

Smoke Test の実行タイミング:

デプロイ完了


┌──────────────────────────────────────────┐
│ Smoke Test │
│ │
│ 1. ヘルスエンドポイントが200を返すか │
│ 2. OpenID Configuration が取得できるか │
│ 3. JWKSエンドポイントが応答するか │
│ 4. トークンエンドポイントが応答するか │
└──────────────────────────────────────────┘

├── 全件成功 → デプロイ成功
└── 1件でも失敗 → ロールバック

段階的トラフィック移行

新バージョンへのトラフィックを段階的に移行し、各段階でメトリクスを確認します。

段階的トラフィック移行:

時間 トラフィック比率 判断基準
─────────────────────────────────────
T+0 v2: 5% Smoke Test通過
T+5m v2: 25% エラー率 < 0.5%
T+15m v2: 50% レイテンシP99 < 200ms
T+30m v2: 100% 全メトリクス正常

デプロイ戦略の選択指針

プロジェクトの状況に応じて、適切なデプロイ戦略を選択します。

条件推奨戦略
小規模チーム・初期段階ローリングアップデート
ダウンタイムゼロが必須Blue-Green
大規模ユーザーベースCanary
テナント別の段階的リリースFeature Flags + Canary
頻繁なリリース(日次以上)Feature Flags
データベースマイグレーションを伴うBlue-Green + 段階的マイグレーション

IDサービスの場合: マルチテナント環境では、特定のテナントに対して先行リリースし、問題がなければ全テナントに展開するFeature Flags + Canary の組み合わせが有効です。


次のステップ

デプロイ戦略を理解しました。

次に読むべきドキュメント

  1. パイプライン設計 - デプロイ戦略をパイプラインに組み込む
  2. CI/CDの基礎 - CI/CDの全体像を復習する

関連リソース


最終更新: 2026-03-04 対象: SaaS開発者・インフラエンジニア