ブルーグリーンデプロイメント - ダウンタイムゼロのリリース

14分 で読める | 2025.01.10

ブルーグリーンデプロイメントとは

ブルーグリーンデプロイメントは、2つの同一環境(Blue/Green)を用意し、トラフィックを瞬時に切り替えるデプロイ手法です。ダウンタイムゼロでリリースでき、問題発生時は即座にロールバックできます。

flowchart TB
    LB["ロードバランサー"]

    subgraph Blue["Blue環境(現行)"]
        B1["サーバー 1"]
        B2["サーバー 2"]
    end

    subgraph Green["Green環境(新版)"]
        G1["サーバー 1"]
        G2["サーバー 2"]
    end

    LB -->|"100%"| Blue
    LB -.->|"0%"| Green

    style Blue fill:#4a9eff
    style Green fill:#48bb78

デプロイ戦略の比較

戦略ダウンタイムロールバックコスト複雑さ
ローリング最小遅い
ブルーグリーンゼロ即座
カナリアゼロ即座
A/Bテストゼロ即座

実装パターン

AWS ALB + ECS

// AWS CDKでの実装
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';

// Blue/Green用のターゲットグループ
const blueTargetGroup = new elbv2.ApplicationTargetGroup(this, 'Blue', {
  port: 80,
  protocol: elbv2.ApplicationProtocol.HTTP,
  targetType: elbv2.TargetType.IP,
  healthCheck: {
    path: '/health',
    interval: Duration.seconds(10),
  },
});

const greenTargetGroup = new elbv2.ApplicationTargetGroup(this, 'Green', {
  port: 80,
  protocol: elbv2.ApplicationProtocol.HTTP,
  targetType: elbv2.TargetType.IP,
  healthCheck: {
    path: '/health',
    interval: Duration.seconds(10),
  },
});

// CodeDeployによる自動切り替え
new codedeploy.EcsDeploymentGroup(this, 'DeploymentGroup', {
  service: ecsService,
  blueGreenDeploymentConfig: {
    blueTargetGroup,
    greenTargetGroup,
    listener: albListener,
    terminationWaitTime: Duration.minutes(10),
  },
  deploymentConfig: codedeploy.EcsDeploymentConfig.ALL_AT_ONCE,
});

Kubernetes

# Blue Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-blue
  labels:
    app: myapp
    version: blue
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      version: blue
  template:
    metadata:
      labels:
        app: myapp
        version: blue
    spec:
      containers:
      - name: myapp
        image: myapp:v1.0.0
        ports:
        - containerPort: 8080
---
# Service(切り替え対象)
apiVersion: v1
kind: Service
metadata:
  name: myapp
spec:
  selector:
    app: myapp
    version: blue  # blueまたはgreenに切り替え
  ports:
  - port: 80
    targetPort: 8080

切り替えスクリプト

#!/bin/bash
# blue-green-switch.sh

CURRENT=$(kubectl get svc myapp -o jsonpath='{.spec.selector.version}')

if [ "$CURRENT" = "blue" ]; then
  NEW_VERSION="green"
else
  NEW_VERSION="blue"
fi

echo "Switching from $CURRENT to $NEW_VERSION"

# ヘルスチェック
kubectl rollout status deployment/myapp-$NEW_VERSION

# 切り替え実行
kubectl patch svc myapp -p "{\"spec\":{\"selector\":{\"version\":\"$NEW_VERSION\"}}}"

echo "Switch complete. Now serving: $NEW_VERSION"

ヘルスチェックとロールバック

interface DeploymentConfig {
  healthCheckUrl: string;
  healthCheckInterval: number;
  healthCheckThreshold: number;
  rollbackOnFailure: boolean;
}

async function performBlueGreenSwitch(config: DeploymentConfig) {
  const newEnvironment = await getInactiveEnvironment();

  // 新環境のヘルスチェック
  let healthyCount = 0;
  for (let i = 0; i < config.healthCheckThreshold; i++) {
    const isHealthy = await checkHealth(newEnvironment, config.healthCheckUrl);
    if (isHealthy) healthyCount++;
    await sleep(config.healthCheckInterval);
  }

  if (healthyCount < config.healthCheckThreshold * 0.8) {
    if (config.rollbackOnFailure) {
      await rollback();
      throw new Error('Health check failed, rolled back');
    }
    throw new Error('Health check failed');
  }

  // トラフィック切り替え
  await switchTraffic(newEnvironment);

  // 旧環境の保持(ロールバック用)
  console.log('Keeping old environment for 30 minutes');
  setTimeout(() => terminateOldEnvironment(), 30 * 60 * 1000);
}

データベースマイグレーション

ブルーグリーンデプロイメントでのDB変更は注意が必要です。

flowchart TB
    subgraph Phase1["フェーズ1: 後方互換スキーマ追加"]
        DB1["既存スキーマ"] --> DB2["新カラム追加<br/>(NULL許容)"]
    end

    subgraph Phase2["フェーズ2: アプリ切り替え"]
        App1["旧アプリ"] --> App2["新アプリ<br/>(両方対応)"]
    end

    subgraph Phase3["フェーズ3: クリーンアップ"]
        DB3["旧カラム削除"]
    end

    Phase1 --> Phase2 --> Phase3
-- フェーズ1: 後方互換性のある変更
ALTER TABLE users ADD COLUMN new_email VARCHAR(255);

-- フェーズ2: データ移行(バックグラウンド)
UPDATE users SET new_email = email WHERE new_email IS NULL;

-- フェーズ3: 旧カラム削除(アプリ切り替え後)
ALTER TABLE users DROP COLUMN email;
ALTER TABLE users RENAME COLUMN new_email TO email;

現場での注意点

  1. セッション管理 - 外部セッションストア(Redis)を使用
  2. キャッシュ無効化 - デプロイ時にキャッシュをクリア
  3. コスト - 2環境分のリソースが必要

関連記事

まとめ

ブルーグリーンデプロイメントは、ダウンタイムゼロと即座のロールバックを実現する強力な手法です。コストは高いですが、本番環境の安定性を重視するシステムには最適です。

← 一覧に戻る