re:Invent 2024: AWSが解説 Amazon ECSの継続的デプロイメント手法
はじめに
海外の様々な講演を日本語記事に書き起こすことで、隠れた良質な情報をもっと身近なものに。そんなコンセプトで進める本企画で今回取り上げるプレゼンテーションはこちら!
📖 AWS re:Invent 2024 - Continuous deployment on Amazon ECS (SVS338)
この動画では、AWSのContainer専門のSpecialist Solutions ArchitectであるSai Kumar Samalaが、Amazon ECSでの継続的デプロイメントについて解説しています。Source、Build、Test、Productionの4つのリリースステージを通じて、Amazon ECSのDeployment Circuit Breaker機能がどのように自動ロールバックを実現するかを説明し、実際のデモを通じて検証しています。Rolling Deploymentを使用した際のMinimum Running TasksとMaximum Running Tasksの設定方法や、新旧バージョンの切り替え時にもダウンタイムを発生させない方法など、実践的な内容を具体的に紹介しています。
※ 画像をクリックすると、動画中の該当シーンに遷移します。
re:Invent 2024関連の書き起こし記事については、こちらのSpreadsheet に情報をまとめています。合わせてご確認ください!
本編
Amazon ECSを活用した継続的デプロイメントの概要
みなさん、こんにちは。本日のセッションにご参加いただき、ありがとうございます。私はSai Kumar Samalaと申します。AWSのContainerを専門とするSpecialist Solutions Architectとして、お客様のコンテナワークロードのAWSへのデプロイをサポートしています。オンプレミスからAWSへの移行支援や、時にはワークロードの移行とモダナイズを担当しており、具体的にはオンプレミス環境からAmazon ECSやEKSへの移行とモダナイゼーションをお手伝いしています。
お客様とお話しする際によく耳にするのが、毎日あるいは毎週新しいバージョンをリリースしたいというご要望です。その際の主な課題は、デプロイメントインフラの管理に多くの時間を費やすことなく、また手動でのロールバック作業も避けながら、いかに迅速にデリバリーを行うかということです。本日は、Amazon ECSでの継続的デプロイメントについてお話しし、Amazon ECSの組み込み機能がどのように迅速で信頼性の高いデプロイメントを実現し、アプリケーションを常時稼働させながら、手動介入なしでロールバックを行えるかをご紹介します。
アプリケーションのリリースについて話す際、リリースプロセスには通常4つのステージがあります。Source、Build、Test、そしてProductionです。Sourceステージでは、通常、開発者がコードリポジトリにソースコードをコミットします。このステージでピアレビューも行われます。Buildステージでは、アプリケーションのすべてのアーティファクトをビルドして生成します。ここでコードをコンパイルし、コンテナワークロードを実行している場合は、コンテナイメージを生成してAmazon ECRなどのリポジトリにプッシュします。
コンテナイメージの準備が整うと、Testステージにデプロイします。ここで統合テスト、負荷テスト、セキュリティテストなど、すべてのテストが実施されます。このステージですべてが問題なければ、アプリケーションをProductionにデプロイします。Productionへのデプロイ後は、デプロイしたアプリケーションが正常に動作していることを確認し、リソースのパフォーマンスなどを監視するため、可観測性ツールをデプロイします。
継続的インテグレーションは、SourceステージとBuildステージの間で行われます。ユーザーがコードをコミットすると同時に、継続的インテグレーションシステムがアーティファクトをビルドします。ユーザーがコードに小さな変更を加えた場合でも、自動的にコードがビルドされ、新しいアーティファクトが生成され、新しいコンテナイメージがビルドされてECRにプッシュされるシステムが必要です。新しいコミットハッシュごとにビルドが実行されなければなりません。継続的デプロイメントは、SourceからProductionまでの全工程を対象とします。継続的デプロイメントでは、手動のステップは一切ありません。開発者がコードをリポジトリにコミットすると同時に、ビルドが開始され、すべてのアーティファクトが生成され、コンテナイメージがECRまたは他のコンテナレジストリにプッシュされます。
このリリースプロセスの段階全体において、Amazon ECSやAWS Fargateはデプロイ段階で活用されます。継続的デプロイメントの目標として、コードがテスト用のステージング環境に自動的にデプロイされることを確認したいと考えています。また、顧客に影響を与えることなく、安全な本番環境へのデプロイを実現します。デプロイの頻度を高めながら、より迅速なデリバリーを実現し、リードタイムと障害率を低減することを目指しています。
Amazon ECSとデプロイメントサーキットブレーカーの機能
継続的デプロイメントの目標を踏まえ、Amazon ECSはRollingデプロイメントを使用してロールバックを処理します。Amazon ECSはRollingデプロイメントとBlue-Greenデプロイメントの両方をサポートしています。今日のデモでは、Rollingデプロイメントについて説明します。しかしその前に、先ほどリリースプロセスの段階で触れたように、Amazon ECSはデプロイと実行の段階に位置づけられます。ステージングクラスターであれ本番クラスターであれ、インフラストラクチャーはAmazon ECS上で稼働することになります。それでは、Amazon ECSがワークロードをどのように処理するかについて詳しく見ていく前に、Amazon ECSについて簡単におさらいしましょう。
Amazon Elastic Container Serviceは、フルマネージド型のコンテナオーケストレーションサービスで、お客様がAWSクラウド上でコンテナワークロードを効率的にデプロイ、管理、スケーリングできるよう支援します。高性能でスケーラブルなサービスであり、AWS Fargateというエンタープライズグレードのサーバーレスコンピューティングを提供します。AWS Fargateを使用すると、AWSがタスクやコンテナに適切なサイズのワーカーノードを起動してくれるため、コンテナホストを管理する必要がありません。お客様はEC2起動タイプを使用してワークロードをデプロイすることもできますし、独自のハードウェアをお持ちの場合は、Amazon ECS Anywhereを使用してそれらの上にワークロードをデプロイすることも可能です。
Amazon ECSはデプロイメントサーキットブレーカー機能を提供します。Rollingデプロイメントを使用する際、デプロイメントサーキットブレーカーは新しいデプロイメントのタスク起動とヘルスチェックの失敗を自動的に監視します。新しいデプロイメントに問題がある場合、最後の正常な状態に自動的にロールバックします。最後の正常な状態をどのように把握するのでしょうか?デプロイメント履歴には完了状態のデプロイメントが記録されているため、デプロイメントサーキットブレーカーは完了状態だった以前の状態に自動的にロールバックします。以前のTask Definitionを使用して、以前のタスクが確実にデプロイされるようにします。ECSデプロイメントサーキットブレーカーの有効化はワンクリックで設定できるため、すでにECSを使用していて、デプロイメントサーキットブレーカーを導入したい場合は、サービスの更新で有効化するだけです。
ライブデモ:Amazon ECSによる自動ロールバックの実演
それでは、ライブデモに移りましょう。このライブデモでは、意図的にアプリケーションにエラーを作り出してデプロイします。Amazon ECSがアプリケーションを稼働させたまま、どのようにロールバックを行うかを確認します。 ここにStagingとProductionという2つのクラスターがあります。 Staging内には、Hello-serverというECSサービスがあり、 3つのタスクが実行状態にあります。このクラスターのレプリカが本番環境にも存在し、このProductionクラスターにも同じくHello-serverがあり、3つのタスクが実行状態になっています。
これからStagingクラスターとProductionクラスターの両方のエンドポイントに対して負荷をかけてみたいと思います。ご覧の通り、これは「Welcome to re:Invent」というグリーティングを表示するシンプルなアプリケーションです。StagingとProductionクラスターの2つのエンドポイントにループでcurlを実行しているため、リクエスト数が変動しています。これからコードに小さな変更を加えて、アプリケーションにいくつかの障害を発生させますが、画面右側のモニタリングを継続して、アプリケーションが決してダウンせず、HTTP 200 OKが常に返されることを確認していきます。
このアプリケーションにヘルスチェックの失敗を導入し、グリーティングを「Welcome to re:Invent」から「Welcome to re:Invent 2024」に変更しようと思います。 開発者が単にグリーティングを更新しようとして、誤ってヘルスチェックのエラーを引き起こしてしまうというシナリオを再現しています。グリーティングを更新してコードをプッシュしてみましょう。 コードをプッシュしたので、AWS Consoleに戻ってみましょう。 すでに作成済みのCode Pipelineがあり、コードをプッシュした時点でSourceステージがトリガーされています。このCode Pipelineの内容を簡単に説明させていただきます。
Source、Build、Deploy、そしてTestingステージがあります。コードがDeployステージにデプロイされると、 Testingステージでテストが実行され、問題が見つかった場合は自動的に前回のデプロイメントにロールバックされ、Production環境へのデプロイは行われません。
ビルドの実行中に、サービスの設定を変更してみましょう。Amazon ECS サービスを開いています。これはStagingクラスターです。hello serverを開いてUpdate Service をクリックします。ここでDeployment Circuit BreakerとRollback機能を有効にできます。Rolling Deploymentでは、 Minimum Running TasksとMaximum Running Tasksを設定できます。この例では、Desired Tasksを3に設定しています。Amazon ECSは常に3つのタスクを実行状態に保ちます。1つのタスクがダウンした場合、Amazon ECSは設定された数を維持するために新しいタスクをデプロイします。
Minimum Running TasksとMaximum Running Tasks percentageは、Rolling Deploymentを実行する際に重要な役割を果たします。私の場合、Desired Countが3なので、最低3つのタスクを常に実行するようAmazon ECSに指示しています。Maximum percentageは200%に設定されており、3の200%は6になります。新しいデプロイメント中は、最大6つのタスクが実行状態になることがあります。6つのタスクのうち、3つが古いバージョン、3つが新しいバージョンとなります。新しいバージョンの3つのタスクが完全に正常な状態になってはじめて、Amazon ECSは古い3つのタスクを終了させます。
デプロイメントのCircuit Breakerを有効にすることで、デプロイメントタスクの起動状態を常時監視します。問題が発生した場合は、以前の正常な状態にロールバックされます。パイプラインの実行中に、ターミナルに戻ってみましょう。ご覧のように、カウントは増加しており、依然として200 OKの状態です。ここを見ると、まだ「Welcome to re:Invent」と表示されています。私は「Welcome to re:Invent 2024」に変更しましたが、アプリケーションはまだそれをデプロイしていません。
パイプラインを見てみましょう。現在はデプロイのステージにあります。ここでStagingクラスターに戻ってみましょう。Hello Serverです。デプロイメントを見ると、2つのデプロイメントが進行中で、ロールバックがすでに発生しています。その理由は、一部のタスクが正常な状態ではなかったためです。ここで確認すると、ご覧のようにデプロイステージが失敗しましたが、次のステップには進みませんでした。Test StagingやDeploy Productionには進まなかったのです。なぜなら、失敗したアプリケーションやエラーのあるアプリケーションをProduction環境にデプロイすることはないからです。
ここでターミナルを見ると、まだ200 OKが返ってきており、「Welcome to re:Invent」のメッセージもそのままです。しかし、「2024」は表示されていません。新しいバージョンがProductionはおろか、Stagingにもまだデプロイされていないからです。ロールバックが発生すると、ECS内でロールバック情報を確認することができます。これはAmazon ECSに追加された新機能であるDeploymentsタブで確認できます。Deploymentsタブでは、ロールバックの履歴や成功したデプロイメントの履歴を、日時などの情報とともに確認することができます。DevOpsエンジニアとして過去のデプロイメントの状況をトラブルシューティングして理解したい場合は、Amazon ECSコンソールのDeploymentsタブで詳細な情報を確認することができます。
次に、パイプラインで実際に何が起きたのかを確認してみましょう。このコミットのハッシュコードを見ると、開発者が実際にどのような変更を加えたのかがわかります。ここでは、グリーティングメッセージを変更するとともに、53行目にも変更を加えました。この53行目が実際に問題を引き起こしている箇所です。
この問題はヘルスチェックの失敗を引き起こしているため、アプリケーションは新しいバージョンに移行できません。先に進む前に、Production ServiceでもDeployment Circuit Breakerを有効にしておきましょう。Productionクラスター内のHello Serverで、サービスの更新を行います。これはワンクリックで実行できる操作です。デプロイメントが失敗した際には必ずロールバックするように設定しておきたいと思います。
Amazon ECSコンソールでは、 タスク定義のリビジョン25を使用して起動された3つのタスクすべてを確認できます。これらの3つはすべて異常な状態で、Amazon ECSはまだ新しいバージョンにトラフィックをルーティングしていません。 ここでアプリケーションに変更を加えてみましょう。 変更をプッシュしたので、サーバーパイプラインに戻ってみましょう。 これから行われるデプロイメントを監視していきます。Buildステージでコンテナイメージが作成され、ビルドが完了すると、Stagingクラスターのデプロイステージにデプロイされます。
ターミナルを見てみましょう。 ご覧の通り、開発者がコードをコミットして変更を加えている最中でも、エラーを起こしているかどうかに関わらず、アプリケーションは稼働し続けています。現時点でダウンタイムは一切ありません。アプリケーションは稼働中で、トラフィックも問題なく処理されています。パイプラインを監視してみましょう。現在Buildステージにいます。Buildステージが終わり、デプロイステージに移行しました。 ECSクラスターのStagingの環境に戻って、このサービスで何が起きているか確認してみましょう。
実際の運用では、 週に複数回デプロイメントを行う場合、コンソールに来てデプロイメントが上手くいっているかを確認することは一般的ではありません。サービスイベントやデプロイメント履歴を見ることで、ECSデプロイメントで何が起きているのか、あるいは進行中の状況を把握することができます。デプロイメントタブでは、デプロイメントのステータスが進行中であることが分かります。右側では、アプリケーションがまだ稼働中で、「welcome」を表示している古いタスクにトラフィックがルーティングされており、2024バージョンが立ち上がってきているところが確認できます。
新しいタスクが起動され、正常な状態として表示されています。Amazon ECSは、この場合2024を表示している新しいタスクにトラフィックをルーティングしています。重要なポイントとして、新しいアプリケーションはまだStagingの環境にあるということです。デプロイされたアプリケーションが正しく動作していることを確認するためのテストを実行したいので、まだProductionには新しいバージョンがデプロイされていません。すべてが問題なければ、Productionに進みます。パイプラインの中で何が起きているか見てみましょう。 Stagingへのデプロイメントはまだ進行中です。その直後にTest Stagingが実行されます。 Test Stagingが失敗した場合はProductionにデプロイされませんが、パスすればProductionへのデプロイに進みます。
ECSクラスターに戻って ここで実行中のタスクの数を確認してみましょう。3つのタスクが実行中の状態です。タスク定義のバージョンを見ると、 古いタスク定義バージョンのタスクは正常に停止され、新しいタスク定義が実行中の状態です。リビジョン24と26の間に、リビジョン25で失敗したデプロイメントがありました。リビジョン25はここには存在していません。デプロイメントはまだ進行中で、すべてのタスクが正常であることを確認しています。今、成功状態に移行しました。 パイプラインを監視して、Test Stagingフェーズで何が起きているか見てみましょう。
※ こちらの記事は Amazon Bedrock を利用することで全て自動で作成しています。
※ 生成AI記事によるインターネット汚染の懸念を踏まえ、本記事ではセッション動画を情報量をほぼ変化させずに文字と画像に変換することで、できるだけオリジナルコンテンツそのものの価値を維持しつつ、多言語でのAccessibilityやGooglabilityを高められればと考えています。
Discussion