Amazon Web Services ブログ

Amazon ECS の新しい組み込みブルー/グリーンデプロイを使用して、安全なソフトウェアリリースを加速

コンテナは開発チームがアプリケーションをパッケージ化およびデプロイする方法に革命をもたらしましたが、これらのチームは、デプロイリスクを軽減するためにリリースを注意深くモニタリングしたり、カスタムツールを構築したりする必要があり、これがリリース速度の低下につながっています。大規模な開発では、開発チームはビジネスのためのイノベーションではなく、差別化につながらないデプロイツールの構築とメンテナンスに貴重なサイクルを費やしています。

7 月 17 日より、Amazon Elastic Container Service (Amazon ECS) に組み込まれているブルー/グリーンデプロイ機能を使用して、アプリケーションのデプロイをより安全かつ一貫性のあるものにすることができます。この新機能により、カスタムデプロイツールを構築する必要がなくなり、ロールバック機能を使用してソフトウェアアップデートをより頻繁にリリースすることについての自信がつきます。

Amazon ECS コンソールで組み込みのブルー/グリーンデプロイ機能を有効にする方法を次に示します。

既存の「ブルー」環境でライブトラフィックを引き続き処理しながら、新しい「グリーン」アプリケーション環境を作成します。グリーン環境を徹底的にモニタリングおよびテストした後、ライブトラフィックをブルーからグリーンにルーティングします。この機能により、Amazon ECS は、コンテナ化されたアプリケーションのデプロイをより安全で信頼性の高いものにする組み込み機能を提供するようになりました。

アプリケーショントラフィックをブルー環境からグリーン環境にシフトすることで、ブルー/グリーンデプロイがどのように機能するかを説明する図を以下に示します。詳細については、Amazon ECS ブルー/グリーンサービスデプロイのワークフローのページをご覧ください。

Amazon ECS は、本番トラフィックをルーティングする前に合成トラフィックを使用して新しいバージョンを検証するためのイベントフックを提供しながら、このワークフロー全体をオーケストレートします。エンドユーザーに公開する前に本番環境で新しいソフトウェアバージョンを検証し、問題が発生した場合にはほぼ瞬時にロールバックできます。この機能は Amazon ECS に直接組み込まれているため、カスタムツールを構築することなく、設定を更新するだけでこれらの安全対策を追加できます。

開始方法
ECS サービスのブルー/グリーンデプロイを設定して使用する方法を示すデモをご紹介します。その前に、AWS Identity and Access Management (IAM) ロールの設定など、いくつかのセットアップステップを完了する必要があります。IAM ロールは、「Required resources for Amazon ECS blue/green deployments」ドキュメントページに記載されています。

このデモでは、リスクを最小限に抑えるために、ブルー/グリーン戦略を使用してアプリケーションの新しいバージョンをデプロイします。まず、ブルー/グリーンデプロイを使用するように ECS サービスを設定する必要があります。これは、ECS コンソールや AWS コマンドラインインターフェイス (AWS CLI) を通じて、または Infrastructure as Code を使用して行うことができます。

Amazon ECS コンソールを使用して、新しいサービスを作成し、通常どおりに設定します:

[デプロイオプション] セクションで、[デプロイコントローラータイプ] として [ECS] を選択し、[デプロイ戦略] として [ブルー/グリーン] を選択します。[ベイク時間] とは、本番トラフィックがグリーンにシフトした後、ブルーへの即時ロールバックが可能になるまでの時間です。ベイク時間が経過すると、ブルータスクは削除されます。

また、デプロイライフサイクルフックも導入されます。これらは、デプロイワークフローを拡張するために使用できるイベントドリブンのメカニズムです。デプロイライフサイクルフックとして使用する AWS Lambda 関数を選択できます。Lambda 関数は必要なビジネスロジックを実行できますが、フックステータスを返す必要があります。

Amazon ECS は、ブルー/グリーンデプロイ中に次のライフサイクルフックをサポートします。各ステージの詳細については、デプロイライフサイクルステージのページをご覧ください。

  • スケールアップ前
  • スケールアップ後
  • 本番トラフィックシフト
  • テストトラフィックシフト
  • 本番トラフィックシフト後
  • テストトラフィックシフト後

私のアプリケーションでは、テストトラフィックシフトが完了し、グリーンサービスがすべてのテストトラフィックを処理するようになったときにテストしたいと考えています。エンドユーザートラフィックはないため、このステージでロールバックしてもユーザーに影響はありません。そのため、まずは自分の Lambda 関数を使用してテストできるので、[テストトラフィックシフト後] が私のユースケースに適しています。

少しコンテキストを変えて、デプロイの続行を許可する前にそのデプロイを検証するために使用する Lambda 関数に注目してみましょう。デプロイライフサイクルフックとしての Lambda 関数では、合成テスト、別の API の呼び出し、メトリクスのクエリなど、あらゆるビジネスロジックを実行できます。

Lambda 関数内では、hookStatus を返す必要があります。hookStatusSUCCESSFUL の場合、プロセスは次のステップに進みます。ステータスが FAILED の場合、ブルーデプロイにロールバックします。IN_PROGRESS の場合、Amazon ECS は 30 秒後に Lambda 関数を再試行します。

次の例では、アプリケーションのテストスイートの一部としてファイルアップロードを実行する Lambda 関数を使用して検証をセットアップしました。

import json
import urllib3
import logging
import base64
import os

# ログ記録を設定します
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

# HTTP クライアントを初期化します
http = urllib3.PoolManager()

def lambda_handler(event, context):
    """
    Validation hook that tests the green environment with file upload
    """
    logger.info(f"Event: {json.dumps(event)}")
    logger.info(f"Context: {context}")
    
    try:
        # 実際のシナリオでは、テストエンドポイント URL を作成します
        test_endpoint = os.getenv("APP_URL")
        
        # アップロード用のテストファイルを作成します
        test_file_content = "This is a test file for deployment validation"
        test_file_data = test_file_content.encode('utf-8')
        
        # ファイルアップロード用のマルチパートフォームデータを準備します
        fields = {
            'file': ('test.txt', test_file_data, 'text/plain'),
            'description': 'Deployment validation test file'
        }
        
        # ファイルアップロードを含む POST リクエストを /process エンドポイントに送信します
        response = http.request(
            'POST',
            test_endpoint,
            fields=fields,
            timeout=30
        )
        
        logger.info(f"POST /process response status: {response.status}")
        
        # レスポンスに OK ステータスコード (200~299 の範囲) が含まれているかどうかを確認します
        if 200 <= response.status < 300:
            logger.info("File upload test passed - received OK status code")
            return {
                "hookStatus": "SUCCEEDED"
            }
        else:
            logger.error(f"File upload test failed - status code: {response.status}")
            return {
                "hookStatus": "FAILED"
            }
            
    except Exception as error:
        logger.error(f"File upload test failed: {str(error)}")
        return {
            "hookStatus": "FAILED"
        }

デプロイがフックに関連付けられたライフサイクルステージに達すると、Amazon ECS は、デプロイコンテキストを使用して Lambda 関数を自動的に呼び出します。この検証関数は、グリーンリビジョンに対して包括的なテスト (アプリケーションの正常性のチェック、統合テストの実行、パフォーマンスメトリクスの検証など) を実行できます。その後、関数は、デプロイを続行するか、中止するかを ECS に知らせます。

また、私はブルー/グリーンデプロイ戦略を選択したため、ロードバランサーおよび/または Amazon ECS Service Connect を設定する必要があります。[ロードバランシング] セクションで、[Application Load Balancer] を選択します。

[リスナー] セクションで、ポート 80 の既存のリスナーを使用し、2 つの [ターゲットグループ] を選択します。

この設定に問題がなければ、サービスを作成し、ECS が新しいサービスをプロビジョニングするのを待ちます。

ブルー/グリーンデプロイのテスト
次に、ブルー/グリーンデプロイをテストします。このテストでは、テストトラフィックシフトが完了した後、Amazon ECS は Lambda 関数をトリガーします。この場合、私の Lambda 関数はアプリケーションへのファイルアップロードを実行するため FAILED を返しますが、私のアプリケーションにはこの機能がありません。

サービスを更新し、ブルー/グリーンデプロイ機能が失敗を検出した場合にはロールバックしてくれるので安心して [新しいデプロイの強制] にチェックを入れます。タスク定義は変更していませんが、引き続き新しいデプロイをトリガーする必要があるため、このオプションを選択します。

このステージでは、ブルー環境とグリーン環境の両方が実行中であり、グリーンリビジョンがすべてのテストトラフィックを処理しています。一方、Lambda 関数の Amazon CloudWatch Logs に基づいて、デプロイライフサイクルフックが想定どおりに機能し、次のペイロードが出力されていることも確認できます:

[INFO]	2025-07-10T13:15:39.018Z	67d9b03e-12da-4fab-920d-9887d264308e	Event: 
{
    "executionDetails": {
        "testTrafficWeights": {},
        "productionTrafficWeights": {},
        "serviceArn": "arn:aws:ecs:us-west-2:123:service/EcsBlueGreenCluster/nginxBGservice",
        "targetServiceRevisionArn": "arn:aws:ecs:us-west-2:123:service-revision/EcsBlueGreenCluster/nginxBGservice/9386398427419951854"
    },
    "executionId": "a635edb5-a66b-4f44-bf3f-fcee4b3641a5",
    "lifecycleStage": "POST_TEST_TRAFFIC_SHIFT",
    "resourceArn": "arn:aws:ecs:us-west-2:123:service-deployment/EcsBlueGreenCluster/nginxBGservice/TFX5sH9q9XDboDTOv0rIt"
}

想定どおり、私の AWS Lambda 関数はテストの実行に失敗したため、hookStatus として FAILED を返します。

[ERROR]	2025-07-10T13:18:43.392Z	67d9b03e-12da-4fab-920d-9887d264308e	File upload test failed: HTTPConnectionPool(host='xyz.us-west-2.elb.amazonaws.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x7f8036273a80>, 'Connection to xyz.us-west-2.elb.amazonaws.com timed out. (connect timeout=30)'))

検証が正常に完了しなかったため、Amazon ECS は、以前の機能するデプロイバージョンであるブルーバージョンへのロールバックを試みます。[イベント] セクションの ECS イベントを通じてこのプロセスをモニタリングでき、デプロイの進行状況を詳細に確認できます。

Amazon ECS は、デプロイを以前の機能するバージョンに正常にロールバックします。ブルーリビジョンは実行中のままとなり、本番トラフィックを受信できる準備が整っているため、ロールバックはほぼ瞬時に行われます。このプロセス中は、本番トラフィックが新しいアプリケーションバージョンにシフトすることはないため、エンドユーザーへの影響はありません。ECS がテストトラフィックを元の安定したバージョンにロールバックするだけです。これにより、従来のローリングデプロイに伴う一般的なデプロイのダウンタイムが排除されます。

また、ロールバックのステータスは [前回のデプロイ] セクションで確認できます。

テスト全体を通じて、ブルー/グリーンデプロイ戦略が一貫した予測可能な動作を提供することがわかりました。さらに、デプロイライフサイクルフックにより、デプロイの動作をより柔軟に制御できます。各サービスリビジョンは、タスク定義、ロードバランサーの設定、Service Connect の設定など、イミュータブルな設定を維持します。これは、ロールバックによって、以前実行されていたのとまったく同じ環境が復元されることを意味します。

知っておくべき追加情報
いくつかの留意点を次に示します:

  • 料金 – ブルー/グリーンデプロイ機能は、追加料金なしで Amazon ECS に含まれます。お支払いいただくのは、デプロイプロセス中に使用されたコンピューティングリソースについての料金のみです。
  • 利用可能なリージョン – この機能は、すべての商用 AWS リージョンでご利用いただけます。

Amazon ECS コンソールで Amazon ECS サービスの設定を更新して、ブルー/グリーンデプロイの使用を開始しましょう。

よいデプロイを!
Donnie

原文はこちらです。