こんにちは、西海です。
前回、ECSのデプロイ方式についてまとめた記事を作成しました。
その中で、Blue/Greenデプロイについて実際に環境を作成して検証してみたのでまとめます。
※日本時間で2025年7月18日にAWSからCodeDeployを使用せずECS単体でBlue/Greenデプロイが可能となる機能がリリースされました。
しかし、本記事ではCodeDeployを使用したBlue/Greenデプロイについて記載しています。
検証環境構築
検証のための環境を作成します。
今回は以下のような設定値の各リソースを作成します。
また、ALBとECSクラスター/サービスはマネコンから作成する想定で設定箇所のみ記載します。
※以下に記載されていない箇所はデフォルトのままとします。
■ネットワーク関係
・VPC
IP | |
---|---|
VPC | 10.0.0.0/20 |
public-subnet | 10.0.1.0/24 |
private-subnet1 | 10.0.0.0/24 |
private-subnet2 | 10.0.2.0/24 |
●ルートテーブル
・public-subnet用
送信先 | ターゲット | |
---|---|---|
送信先1 | 0.0.0.0/0 | 作成したigwのID |
送信先2 | 10.0.0.0/20 | local |
・Private-subnet1,2用
送信先 | ターゲット | |
---|---|---|
送信先1 | 10.0.0.0/20 | local |
●IAMロール
・Codedeploy用
許可ポリシー | タイプ |
---|---|
AWSCodeDeployRoleForECS | AWS管理 |
●セキュリティグループ
・ALB用
プロトコル | ポート | ソース | 備考 | |
---|---|---|---|---|
インバウンドルール1 | TCP | 80 | 0.0.0.0/0 | 一般ユーザー用 |
インバウンドルール2 | TCP | 9000 | [ローカルPCのIPアドレス]/32 | 開発ユーザー用 |
アウトバンドルール | 全て | 全て | 0.0.0.0/0 | ー |
■ALB関連
・ALB(マネコンから作成する際の設定箇所と設定値を記載)
設定箇所 | 設定値 |
---|---|
ロードバランサー名 | 任意の名前 |
スキーム | インターネット向け |
ロードバランサーの IP アドレスタイプ | IPv4 |
・ネットワークマッピング
設定箇所 | 設定値 |
---|---|
VPC | 事前に作成したVPC名 |
アベイラビリティーゾーンとサブネット | 事前に作成したサブネット名 |
・セキュリティグループ
設定箇所 | 設定値 |
---|---|
セキュリティグループ | ALB用に事前に作成したSG名 |
・リスナーとルーティング
設定箇所 | 設定値 |
---|---|
デフォルトアクション | 事前に作成したターゲットグループ名 |
●ターゲットグループ
IP アドレスタイプ | プロトコル : ポート | プロトコルバージョン | VPC | ヘルスチェック(プロトコル:パス) | |
---|---|---|---|---|---|
Bule用 | IPv4 | HTTP:80 | HTTP1 | 上記で事前に作成したVPC | HTTP:/ |
Green用 | IPv4 | HTTP:80 | HTTP1 | 上記で事前に作成したVPC | HTTP:/ |
■ECR関連
・ECRリポジトリ
リポジトリ種類 | リポジトリ名 |
---|---|
プライベートリポジトリ | 任意のリポジトリ名 |
■Dorkerイメージ作成
今回はnginx上でHello worldを表示するだけのDockerイメージを用意します。
各ファイルの設定はこちらです。
・htmlファイル
<html>
<head>
<meta charset="utf-8">
<title>Hello World</title>
</head>
<body>
Hello World
</body>
</html>
・nginx.conf
server {
listen 80;
location / {
root /var/www/;
index index.html index.htm;
}
}
・Dorker file
FROM nginx:1.25.3
COPY /html /var/www
COPY nginx.conf /etc/nginx/conf.d/default.conf
上記を任意のフォルダ内に作成し、そのフォルダに移動してから以下のコマンドを実行しDockerイメージを作成します。
docker image build .
その後、以下のコマンドでDockerイメージの動作確認を実施します。
下記コマンドでDorkerコンテナを起動し、curlコマンドで先ほど作成したhtmlファイルの中身が表示されれば成功です。
docker container run -p 8080:80 [作成したDockerイメージのID]
curl http://localhost:8080
■DorkerイメージをECRリポジトリにPush
ECRリポジトリを作成すると、自動的にPushコマンドが作成されます。
画面右上の「プッシュコマンドを表示」をクリックし、使用しているOSのタブから各コマンドを順番に実行します。
ECRリポジトリプッシュコマンド
pushコマンド実行後、イメージが新規に表示されていれば成功です。
■ECS関連
・タスク定義
{
"taskDefinitionArn": "arn:aws:ecs:使用リージョン:AWSアカウント ID:task-definition/タスク定義名:1",
"containerDefinitions": [
{
"name": "frontend",
"image": "ECRリポジトリにプッシュしたイメージのURI",
"cpu": 0,
"portMappings": [
{
"name": "frontend-80-tcp",
"containerPort": 80,
"hostPort": 80,
"protocol": "tcp",
"appProtocol": "http"
}
],
"essential": true,
"environment": [],
"environmentFiles": [],
"mountPoints": [],
"volumesFrom": [],
"ulimits": [],
"systemControls": []
}
],
"family": "saikai-app-flontend",
"executionRoleArn": "arn:aws:iam::AWSアカウント ID:role/ecsTaskExecutionRole",
"networkMode": "awsvpc",
"revision": 1,
"volumes": [],
"status": "ACTIVE",
"requiresAttributes": [
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.18"
},
{
"name": "ecs.capability.task-eni"
}
],
"placementConstraints": [],
"compatibilities": [
"EC2",
"FARGATE"
],
"requiresCompatibilities": [
"FARGATE"
],
"cpu": "256",
"memory": "512",
"runtimePlatform": {
"cpuArchitecture": "X86_64",
"operatingSystemFamily": "LINUX"
},
"registeredAt": "2025-03-22T05:23:44.109Z",
"registeredBy": "arn:aws:iam::AWSアカウント ID:user/ユーザ名",
"enableFaultInjection": false,
"tags": []
}
・ECSクラスター(マネコンから作成する際の設定箇所と設定値を記載)
設定箇所 | 設定値 |
---|---|
クラスター名 | 任意の名前 |
インフラストラクチャ | AWS Fargate (サーバーレス) |
・ECSサービス(マネコンから作成する際の設定箇所と設定値を記載)
・サービスの詳細
設定箇所 | 設定値 |
---|---|
タスク定義ファミリー | 事前に作成したタスク定義名 |
タスク定義のリビジョン | 最新のリビジョン |
サービス名 | 任意の名前 |
・環境
設定箇所 | 設定値 |
---|---|
コンピューティングオプション | キャパシティープロバイダー戦略 |
コンピューティングオプション | 起動タイプ |
プラットフォームバージョン | LATEST |
・デプロイ設定
設定箇所 | 設定値 |
---|---|
サービスタイプ | レプリカ |
必要なタスク | 1 |
デプロイタイプ | ブルー/グリーンデプロイ (AWS CodeDeploy を使用) |
デプロイ設定 | CodeDeployDefault.ECSAllAtOnce |
CodeDeployのサービスロール | Codedeploy用に作成したIAMロール |
・ネットワーキング
設定箇所 | 設定値 |
---|---|
VPC | 事前に作成したVPC |
サブネット | Public用に作成したサブネット2つを選択 |
セキュリティグループ | 既存のセキュリティグループを使用 |
セキュリティグループ名 | Bule/Greenデプロイ用に事前に作成したSG名 |
・ロードバランシング
設定箇所 | 設定値 |
---|---|
ロードバランシングを使用 | ☑を入れる |
ロードバランサー | 既存のロードバランサーを使用 |
Application Load Balancer | 上述で作成したロードバランサ― |
リスナー | 既存のリスナーを使用 |
プロダクションリスナー | ALB作成時に作成したリスナー |
テストリスナー | 新しいリスナーを作成 |
テストリスナーポート | 9000 |
ターゲットグループ 1 | Bule用に作成したターゲットグループを使用 |
ターゲットグループ 2 | Green用に作成したターゲットグループを使用 |
■Codedeploy関連
次に、Codedeployのデプロイグループが作成されていることを確認します。
マネコン上の検索からCodedeployを検索し、左メニューのデプロイ>アプリケーションを選択します。
その中にECSサービスを作成した際に同時作成されたものがあるのでそれを選択しデプロイグループタブを選択します。
デプロイグループ内に作成したECSサービスの名前が含まれたグループが存在していれば問題ありません。
また、BuleGreenデプロイ時、トラフィックの置き換えを即時実行するか指定した時間待機させるかを設定できます。
今回は仮として3時間ほど待機させてからトラフィックを移動する設定にします。(実際には任意の時間で大丈夫です)
設定はデプロイグループを選択し、編集ボタンから設定可能です。
・デプロイ設定
設定箇所 | 設定値 |
---|---|
トラフィックの再ルーティング | トラフィックを再ルーティングするタイミングを指定します |
時間 | 3 |
検証環境動作確認
ALBのDNSをコピーし、Webブラウザで以下のように入力します。
http://[ALBのDNS名]
作成したhtmlファイル通りにページが表示されれば問題ありません。
次に、htmlファイルの中身を以下のように変更します。
<html>
<head>
<meta charset="utf-8">
<title>Hello World</title>
</head>
<body>
Blue/Greenデプロイ確認用
</body>
</html>
その後、再度Dockerイメージを作成し、ECRへプッシュします。
その際、Dockerイメージのタグ名を新しくします。今回はBuleGreenとしておきます。
作成したECRリポジトリ内にBuleGreenタブのついたイメージが存在すれば成功です。
Dockerイメージの更新が完了したら、次はECSのタスク定義を変更します。
新規リビジョンとしてイメージURIの値をBuleGreen用のイメージのURIに変更したものを作成します。
その後、ECSサービスの設定からタスク定義のリビジョンの値を最新に更新し、変更を保存します。
変更の保存が完了すると、遷移した画面の上部に次のような表示がされます。
こちらの表示がされると、Codedeployが正常に起動しBuleGreenデプロイが実行されています。
表示されているデプロイステータスのIDをクリックすると、デプロイステータスの画面に遷移しステータスの進行具合が確認できます。
Green環境が構築完了すると、ステップ2まで成功となります
ステップ3が待機中となっていますが、こちらはトラフィックの宛先をGreen環境に移すのを指定の時間だけ待機する処理となります。
現在3時間待機する設定にしていますので、3時間待つか右上の「トラフィックの再ルーティング」をクリックすると即時にトラフィックが移ります。
正常にトラフィックが移ると、以下のようなステータスとなります。
この状態で、先ほどのHello world画面を更新または再度表示させてみます。
すると、更新したhtmlファイルの中身が記載されています。
以上のことから、Blue環境からGreen環境へのデプロイが正常に完了したことになります。
まとめ
Blue/Greenデプロイはローリングデプロイと比較して設定が複雑になりますが、元環境をそのまま残せるので何か問題が生じた際に切り戻しが簡単ということが実感として理解できました。
ただ、記事の冒頭でも触れた通りにCodeDeployを使用せずにECSのみで設定が可能になったため、そちらのやり方についても今後勉強しておきたいです。
また、弊社メンバーも記事を書いていますので、こちらもご覧ください。