BLOG
エンジニアブログ

【第2回】ALB+ECR+ECS Fargateを作って覚えるAWS ECSの基礎

shibuya
shibuya
【第2回】ALB+ECR+ECS Fargateを作って覚えるAWS ECSの基礎

はじめに

この連載では、AWS ECS を使ったコンテナ環境を AWS マネジメントコンソールから手作業で 構築し、そこに CI/CD を少しずつ足していきます。

想定している読者は次のような方です。

  • VPCやEC2等の設定、構築をした事がある方。
  • コンテナは触ったことがあるが、ECS はこれからという方。
  • ECS Fargateを使用して、ECSの基礎知識を確認しておきたい方。
  • 昔ECSを使ったが久しぶりのため、改めて作業方法の再確認をしたい方、復習をして知識を維持したい方。

前回について

本ブログは第2回目となります。前回(第1回へ移動する)は、ALB + ECR + Fargate の構成を手で作り、ブラウザにversion: v1を表示させるところまで実施しました。

本記事について

  • 本記事ではALBやFargateなどの有料サービスを使用するため、費用が発生します。ALBとFargateは起動している時間に応じた課金のため、数時間で完了すれば数USドル程度ですみますが、削除し忘れて1か月放置すると40USドル程度になります。検証後は必ずリソースの削除をお願いします(手順は記事末尾に記載しています)。
  • AWSマネジメントコンソールの画面構成は、随時更新されます。本記事は2026年9月時点の画面をもとにしています。項目名や配置が異なる場合は、適宜読み替えてください。
  • 掲載している手順は、実際にAWS上で検証した内容です。ただし、学習しやすさを優先してセキュリティ設定を簡略化している箇所があります(タスクをパブリックサブネットに配置する、セキュリティグループで広い範囲からのアクセスを許可する、など)。そのため、検証用のAWSアカウントでの実施を推奨します。
  • 本記事では、GitHubとAWSを連携させる設定(OIDCのIDプロバイダー、GitHubアプリの連携など)を行います。これらは他のプロジェクトと共有される設定のため、検証後に削除する際はご注意ください。同じアカウントやGitHub組織で他にも利用しているものがあると、そちらの連携まで止まってしまう可能性があります。削除対象かどうか分からない場合は、無理に消さずに残しておくほうが安全です(残しておいても費用は発生しません)。
  • 共用アカウントや業務で使用しているアカウントで実施する場合は、組織のルールを確認したうえで設定内容を見直してから、本記事を参考にしたり、手順の実施をしてください。

テーマとゴール

いくつかテーマと、ゴールを決めて進めていきます。内容を1つのブログにすると長くなるため、複数回に分けています。

第何回 テーマ ゴール
第1回 コンテナと ECS の基礎、手動構築 ブラウザに「Hello from Amazon ECS」 が表示される
第2回 手動リリースと CodePipeline による自動リリース ECR への push でローリングアップデート
第3回 ECS ネイティブ Blue/Green デプロイ テストリスナーで確認してから本番切り替え
第4回 GitHub Actions で ECR への push を自動化

“git push”だけでリリースまで完了する

第5回 プライベートサブネットを使用した構成

プライベートサブネットとエンドポイントを利用した環境構築の検証をする

第2回目のゴール

今回は「リリース」を目的に進めます。進め方は2段階です。

  1. 手動リリース : タスク定義の新しいリビジョンを作り、サービスを更新する
  2. 手動リリースと同等作業をCodePipelineで実行 : ECR への push を検知して自動でリリースする

 


1.準備

第1回で作成した以下のリソースが残っていること。(リソースが未作成の場合は、第1回を参照ください。)

  • ECRリポジトリecs-handson-nginx(v1/latestタグ)
  • ALB ecs-handson-albとターゲットグループecs-handson-tg-blue
  • ECSクラスター ecs-handson-cluster、サービスecs-handson-service(タスク 2 つ)

作業を進める前に、設定を変更します。

登録解除の遅延を短くする

ターゲットグループには「登録解除の遅延(deregistration delay)」という設定があり、デフォルトは300 秒です。古いタスクをターゲットグループから外したあと、処理中のリクエストが終わるのを5分待ってから停止する、という意味です。本記事の内容では待ち時間が長いため、30秒に短縮します。実業務では、アプリケーションの最長リクエスト時間より少し長めに設定する(例えば、API サーバーならリクエストは数秒で終わるので30〜60秒)など、運用に合わせて変更してください。

EC2 コンソール → ターゲットグループ → ecs-handson-tg-blue →「属性」タブ →「編集」

項目 設定値
登録解除の遅延 30秒


2.手動リリース作業

2-1. v2 イメージを作る

CloudShellを開きます。前回のセッションが切れていると変数も消えているので、最初に設定し直します。


cd ~/ecs-handson

AWS_REGION=ap-northeast-1
AWS_ACCOUNT_ID=$(aws sts get-caller-identity –query Account –output text)
REPO=ecs-handson-nginx
REGISTRY=${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com
ECR_URI=${REGISTRY}/${REPO}

aws ecr get-login-password –region ${AWS_REGION} \
    | docker login –username AWS –password-stdin ${REGISTRY}

 


index.htmlファイルの内容を変更します。バージョン表記を変更と、背景色を変更しバージョン変更を目視で確認しやすくします。


cat > index.html <<'EOF'
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>ECS ハンズオン</title>
</head>
<body style="font-family:sans-serif;text-align:center;padding-top:80px;background:#e8f4ff">
  <h1>Hello from Amazon ECS</h1>
  <p>version: <strong>v2</strong></p>
</body>
</html>
EOF

ビルドし、v2タグのみをつけてpushします。ここで、latestタグをつけないでおきます。手動リリースでは「どのバージョンをデプロイするか」をタスク定義に明示的に書くためです。latestタグの扱いについては、後半の自動リリースで触れます。


docker build -t ${REPO}:v2 .
docker tag ${REPO}:v2 ${ECR_URI}:v2
docker push ${ECR_URI}:v2

2-2.タスク定義の新しいリビジョンを設定

タスク定義を変更できないため、イメージを変更する時は既存の定義をコピーして新しいリビジョンを作成します。
ECS コンソール → タスク定義 → ecs-handson-task → リビジョン1にチェック →「新しいリビジョンを作成」

コンテナ-1の画面が表示されたら、ECRイメージを閲覧ボタンを押下します。一覧から、イメージタグv2のイメージを選択して更新します。

2-3. サービスを更新する

ECS コンソール → クラスター ecs-handson-cluster → サービスタブ→ サービス名 ecs-handson-serviceにチェックをつける → 更新 →「サービスを更新」

画面が開いたら、タスク定義のリビジョンを2に変更し更新します。

2-4. ローリングアップデート

サービスを更新するとローリングアップデートが開始されます。AWSコンソールでECSサービスのデプロイ他タブを参照すると更新作業の状況を確認できます。

ブラウザで新しいタブ(または、別のウィンドウ)でロードバランサーのターゲットグループにある、ターゲットのタブを選択します。一時的に4つのタスクが開始され、新しイメージに置き換わっていくのが観察されます。

ブラウザでALBのDNS名を開いて新しいリビジョンに置き換わっていることを確認します(更新中は古いのも表示されるので、何回か更新ボタンで更新してください。)

デプロイ画面

ターゲットグループ画面

2-5. 動作の確認

一時的にタスクが 4 つになったのは、前回サービス作成時に設定した 2 つの値の組み合わせによるものです。

項目 設定値 説明
最小実行タスク率 100%

更新中も、正常なタスクを必要数(2)の 100% = 2 つ以上維持する

最大実行タスク率 200%

更新中は、必要数の 200% = 4 つまで同時に起動する

2つのタスクを実行したまま、最大4つのタスクまで実行数を増やせるため、ECSは新しいタスクを2つ先に起動し、正常状態になってから古い2つのタスクを停止する流れになります。サービスを停止しないまま更新する仕組みとなります。

設定値を変更した場合の挙動になります。

最小実行タスク率 最大実行タスク率 挙動 適用想定の運用
100% 200% 新しいタスクを増やしてから、古いタスクを減らす 可用性重視
50% 100% 半分停止してから、半分起動を繰り返す リソースに余裕がないとき。一時的に処理能力が半減する
0% 100% 全部停止してから起動する

開発環境のみ。ダウンタイムが発生する

 


3.CodePipelineで自動リリース

手動リリースで以下の3点を実施します。Codepipelineでは、2点目と3点目の作業を任せます。

  1. イメージをECRにpush
  2. ECRにpushしたイメージを指すタスク定義にて、新しいリビジョンの作成
  3. ECSのサービスを新しいリビジョンで更新

3-1. パイプラインの構成

設定するパイプラインのイメージを確認しておきます。

ステージ間で受け渡すファイル形式を確認します。

ファイル 誰が生成して使用する 中身
imageDetail.json ECRソースアクションが出力 イメージのURIのみ
imagedefinitions.json ECSデプロイアクションが要求 コンテナ名とイメージURI

ECSデプロイアクションは、「タスク定義のどのコンテナを、どのイメージに差し替えるか」を知る必要があります。タスク定義には複数のコンテナを書けるので、コンテナ名の指定が必要になります。ECRソースアクションはイメージ情報のみ持っているため、コンテナ名の出力ができません。そのため、間にCommandsアクションをいれてimagedefinitions.jsonファイルを作成します。

Commandsアクションとは:CodeBuild プロジェクトを最初に作成することなくコマンドを指定できます。CodeBuildプロジェクトを作らずに、パイプラインの中で直接シェルコマンドを実行できるアクションになります。裏ではCodeBuildの実行環境が使われ、CodeBuild の料金がかかります(今回の処理は数十秒で終わるので、1 回あたり1円未満です)。V2 タイプのパイプラインでのみ使えます。以前は、この変換のためだけに CodeBuild プロジェクトとbuildspec.ymlファイルを用意する必要がありましたが、Commandsアクションで代替できるようになっています。詳細は、マニュアル「コマンドアクションリファレンス」を参照ください。

 3-2. ダイジェストでイメージを指定する

imageUriの末尾が、:latestではなく@sha256:…になっています。これがイメージダイジェストで、イメージの中身から計算されたハッシュ値になります。

:latestタグをタスク定義に記載すると、どのイメージが動いているか分からない(どのリビジョンでもlatestになる)状態になるため、パイプラインではECRのソースアクションが出力する、ダイジェストを使用してイメージを指定します。

  • 監視対象はlatestタグ(pushされたことを検知する。)
  • タスク定義に記載するのはダイジェスト(中身を一意に特定する。)

タスク定義のリビジョンを見れば、どのイメージが動いていたかが必ず分かります。タグはあとから別のイメージに付け替えられますが、ダイジェストは中身が同じである限り変わりません。

3-3. パイプラインを作成

CodePipeline コンソール →「パイプラインを作成する」

Step1:作成オプションを選択する画面で「カスタムパイプラインを構築する」を選んで「次へ」。

Step2:パイプラインの設定を選択する

項目 設定値
パイプライン名 ecs-handson-pipeline
実行モード 優先済み
サービスロール 新しいサービスロール(自動入力値を使用します。)

実行モードは以下の3つがありますが、今回は優先済みを選択します。

  • 優先済み(SUPERSEDED) モード: より新しい実行が、より古い実行を追い越すことができます。

  • キュー(QUEUED) モード: 実行は、キューに登録した順に 1 つずつ処理されます。これにはパイプラインタイプ V2 が必要です。

  • 並行(PARALLEL) モード: PARALLEL モードでは、複数の実行が同時に、互いに独立して実行されます。実行は、他の実行が完了するまで待たずに開始または終了します。これにはパイプラインタイプ V2 が必要です

詳細設定はしません。アーティファクト用のS3バケットは自動作成されます。

Step3: ソースステージを追加

項目 設定値
ソースプロバイダー Amazon ECR
リポジトリ名 ecs-handson-nginx
画像タグ latest
ソースの変更を自動的に検出するEventBridgeルールを作成 チェックをつける
ステージ障害時の自動再試行を有効にする チェックをつける

Step4 : ビルドステージを追加する

項目 設定値
プロバイダーを構築する コマンド
コマンド

1行目(改行コードを入れずに1行で記入)
printf ‘[{“name”:”nginx”,”imageUri”:”%s”}]’ “#{SourceVariables.RegistryId}.dkr.ecr.ap-northeast-1.amazonaws.com/#{SourceVariables.RepositoryName}@#{SourceVariables.ImageDigest}” > imagedefinitions.json

2行目

cat imagedefinitions.json

環境変数 追加しない
VPC ID 空欄
環境タイプ 空欄
入力アーティファクト SourceArtifact

#{SourceVariables.xxx}は、ソースアクションの出力変数を参照する書き方です。ECR ソースアクションは次の変数を出力します。

変数 変数の中身例
RegistryId 123456789012(アカウント ID)
RepositoryName ecs-handson-nginx
ImageTag latest
ImageDigest sha256:abcd…
ImageURI イメージの URI
  • SourceVariablesという名前空間について
    • 出力変数は「名前空間(namespace)」を付けて参照します。コンソールのウィザードで作ったソースアクションには、自動でSourceVariablesという名前空間が付きます。もしパイプライン実行時に変数が解決されないエラーが出たら、パイプラインを編集してソースアクションの「変数の名前空間」欄を確認し、そこに書かれている名前に合わせてください。

Step5 : テストステージを追加

特に設定をせずに、「テストステージをスキップ」ボタンを押下します。

Step6 : デプロイステージを追加する

特に設定をせずに、「導入段階をスキップ」ボタンを押下します。

  • デプロイステージをスキップする理由
    • 「入力アーティファクト」のプルダウンを開くと、SourceArtifactしか選べません。SourceArtifact選んで先に進むこともできますが、中身はimageDetail.jsonのみとなっています。デプロイは「imagedefinitions.jsonが見つからない」というエラーで必ず失敗します。そのため。いったん SourceとBuildだけでパイプラインを作り、あとから編集で出力とデプロイを足します。

Step7 : レビュー

設定内容に問題が無ければ、パイプラインを作成するボタンを押下します。

3-4. 初回実行で Build の出力を確認する

パイプラインは作成直後に1回自動実行されます。この時点ではデプロイステージがないため、SourceとBuildだけが走り、ECSには何も起きません。Buildステージの「詳細を表示」を開き、ログにcatコマンドで出力されたJSONの出力結果を確認してください。

  • 確認したいポイント
    • nameがタスク定義のコンテナ名nginxになっているか
    • imageUriのアカウントIDとリポジトリ名が正しいか
    • 末尾が”@sha256″から始まるダイジェストになっているか

3-5. 編集で出力アーティファクトとデプロイステージを追加する

CodePipelineコンソール → ecs-handson-pipeline →「編集する」

①Build ステージに出力アーティファクトを追加する

Build ステージの「ステージを編集する」→ アクションの編集アイコン(鉛筆)を押し、画面下部の「出力アーティファクト」を設定します。

項目 設定値
名前 BuildArtifact
ファイル imagedefinitions.jsonを入力し、「ファイルパスに追加」を押す

それ以外の項目(コマンド、変数の名前空間BuildVariablesなど)は変更不要です。設定したら完了ボタンを押下します。

② Deploy ステージを追加する

Build ステージの下にある「+ ステージを追加する」を押します。

ステージ名を追加する画面が表示されたら、ステージ名に「Deploy」を入力しステージを追加するボタンを押下します。

作成されたステージで「+ アクショングループを追加する」ボタンを押下します。次のように設定します。

項目 設定値
アクション名 Deploy
アクションプロバイダー Amazon ECS
リージョン アジアパシフィック (東京)
入力アーティファクト BuildArtifact
クラスター名 ecs-handson-cluster
サービス名 ecs-handson-service
イメージ定義ファイル imagedefinitions.json
デプロイのタイムアウト 空欄
変数の名前空間 空欄

※注 : 入力アーティファクトは必ずBuildArtifactを選択してください。SourceArtifactを選ぶとデプロイに失敗します。アクションプロバイダーには「Amazon ECS (Blue/Green)」という選択肢もありますが、これはCodeDeployを使う旧方式です。

「完了」→「完了」→ 画面上部の「保存」の順番に押下し、パイプラインの変更を保存するの確認サブウィンドウが表示されたら保存ボタンを押下します。

③ サービスロールに ECS の権限を追加する

ウィザードが作るサービスロールには、作成時点のパイプラインにあるアクションの分だけ権限が付きます。今回はデプロイステージをスキップして作ったので、ロールに ECS を操作する権限が入っていません。編集でデプロイステージを足しても、ロールは自動では更新されません。

  • 以下のいずれかの手順でIAMロール編集画面に移動します。
    • IAM コンソール → ロール → AWSCodePipelineServiceRole-ap-northeast-1-ecs-handson-pipeline →「許可を追加」→「インラインポリシーを作成」→「JSON」タブに切り替え、以下を貼り付けます。
    • Codepipelineの画面にある設定タブを選択し、サービスロールARNが表示されているのでそのリンクをクリックします。IAM コンソールに遷移しするので、AWSCodePipelineServiceRole-ap-northeast-1-ecs-handson-pipeline →「許可を追加」→「インラインポリシーを作成」→「JSON」タブに切り替え、以下を貼り付けます。

以下のJSONの123456789012(オレンジ色)箇所は、ご自身のアカウントIDに変更します。(3か所あります。)

ポリシー名は「ecs-handson-deploy-policy」に設定して下さい。



{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "TaskDefinitionPermissions",
      "Effect": "Allow",
      "Action": [
        "ecs:DescribeTaskDefinition",
        "ecs:RegisterTaskDefinition"
      ],
      "Resource": "*"
    },
    {
      "Sid": "ECSServicePermissions",
      "Effect": "Allow",
      "Action": [
        "ecs:DescribeServices",
        "ecs:UpdateService"
      ],
      "Resource": "arn:aws:ecs:ap-northeast-1:123456789012:service/ecs-handson-cluster/*"
    },
    {
      "Sid": "ECSTagResource",
      "Effect": "Allow",
      "Action": "ecs:TagResource",
      "Resource": "arn:aws:ecs:ap-northeast-1:123456789012:task-definition/ecs-handson-task:*",
      "Condition": {
        "StringEquals": {
          "ecs:CreateAction": "RegisterTaskDefinition"
        }
      }
    },
    {
      "Sid": "IamPassRolePermissions",
      "Effect": "Allow",
      "Action": "iam:PassRole",
      "Resource": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
      "Condition": {
        "StringEquals": {
          "iam:PassedToService": [
            "ecs.amazonaws.com",
            "ecs-tasks.amazonaws.com"
          ]
        }
      }
    }
  ]
}


iam:PassRoleが必要な理由 : パイプラインは、タスク定義を登録する際に「このタスクは ecsTaskExecutionRoleの権限で動かしてよい」とECSに伝えます。もし誰でも任意のロールを渡せたら、自分より強い権限を持つロールをタスクに付けて権限昇格ができてしまいます。そのため「どのロールを、どのサービスに渡してよいか」を明示的に許可する必要があるため、ecsTaskExecutionRoleをECSに渡すことだけを許可するという設定をしています。

3-6. 変更をリリースして、デプロイまで通す

画面右上の「変更をリリース」をボタンを押下、変更をリリースする確認画面で「リリースする」ボタンを押下し、手動で実行します。

リリースしたら処理が進み、以下のように全てのステージが完了することを確認します。

完了後、ECS のタスク定義一覧を確認します。新しいリビジョンが自動で作られているはずです(手順どおりならリビジョン3。参考画面はリビジョンが進んでいますが、途中で再実行や試行錯誤をした場合は番号が進んでいることがあります。)

タスク一覧の「ヘルスステータス:不明」は正常です。ECS のタスク一覧にある「ヘルスステータス」は、タスク定義で設定するコンテナのヘルスチェックの結果です。今回のタスク定義ではコンテナのヘルスチェックを設定していないため「不明」と表示されます。ALBのターゲットグループの「ターゲット」タブでから健全性を確認し、そこでhealthyと表示されていれば問題ありません。
タスク定義番号が変わらない場合は、右上の更新ボタンを押下し確認してください。

4. ECRへのpushで自動リリース

4-1. 新しいリビジョンv3イメージをpushする

CloudShellを使用します。イメージpush後の確認が目視で分かるようにするためindex.htmlを変更し、ビルドしてECRへpushします。

CloudShellのセッション切れている場合は、変数を再設定してください。

AWS_REGION=ap-northeast-1
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
REPO=ecs-handson-nginx
REGISTRY=${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com
ECR_URI=${REGISTRY}/${REPO}

cd ~/ecs-handson

sed -i -e ‘s/v2/v3/’ -e ‘s/#e8f4ff/#eaffea/’ index.html

docker build -t ${REPO}:v3 .
docker tag ${REPO}:v3 ${ECR_URI}:v3
docker tag ${REPO}:v3 ${ECR_URI}:latest

docker push ${ECR_URI}:v3
docker push ${ECR_URI}:latest


sedコマンドでバージョンをv3に変更し、背景を薄い緑に書き換えています。

4-2. パイプラインが動くのを見る

push が完了してから数十秒以内に、CodePipeline コンソールでecs-handson-pipelineが自動で実行を開始します。

Source → Build → Deploy と進み、数分後にブラウザで v3(緑背景)が表示されれば成功です。(ALBの画面に、DNS名があるのでhttpにてブラウザで接続して確認してください。)

タスク定義のリビジョン作成もサービスの更新も、CodePipelineが稼働して代わりに実行しているはずです。

なお、v3タグをpushした時点ではパイプラインは動かず、latestでpushしたときに初めて動きます。ECR ソースアクションは設定した 1 つのタグしか監視しないためです。

4-3. EventBridgeの確認

「ECRにpushしたら、なぜパイプラインが起動するのか」を確認します。EventBridge コンソール →「ルール」を開くと、パイプライン作成時に自動で作られたルールがあります(名前はcodepipeline-ecshan-latest-で始まる名称です。)

イベントパターンを見ると、以下のようになっています。



{
  "source": ["aws.ecr"],
  "detail-type": ["ECR Image Action"],
  "detail": {
    "action-type": ["PUSH"],
    "result": ["SUCCESS"],
    "repository-name": ["ecs-handson-nginx"],
    "image-tag": ["latest"]
  }
}

「ECR リポジトリecs-handson-nginxにlatestタグのpushが成功したら」というイベントを確認し、ターゲットの CodePipeline を起動しています。CodePipeline がリポジトリを定期的にポーリングしているわけではなく、ECR が出したイベントを EventBridge が中継している、というのがポイントです。また、パイプラインが起動しないとき、まずこのルールが存在し有効になっているかを確認します。

5.デプロイ失敗時の自動ロールバック確認

壊れたイメージをデプロイしたらどうなるかを試します。

5-1. わざと壊れたイメージを push する

起動しても、すぐに終了してしまうイメージを作ります。

CloudShellのセッション切れている場合は、変数を再設定してください。

AWS_REGION=ap-northeast-1
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
REPO=ecs-handson-nginx
REGISTRY=${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com
ECR_URI=${REGISTRY}/${REPO}

cd ~/ecs-handson

cat > Dockerfile.broken <<‘EOF’
FROM public.ecr.aws/nginx/nginx:1.27-alpine
CMD [“sh”, “-c”, “echo ‘broken image’ && exit 1”]
EOF

docker build -f Dockerfile.broken -t ${REPO}:broken .
docker tag ${REPO}:broken ${ECR_URI}:broken
docker tag ${REPO}:broken ${ECR_URI}:latest

docker push ${ECR_URI}:broken
docker push ${ECR_URI}:latest


5-2. 動作確認

パイプラインが起動し、Source と Build は成功します。Deploy ステージで ECS が新しいタスクを起動しますが、タスクはすぐに終了します。ECS サービスの「デプロイ」タブと「イベント」タブを見ていると、次の流れが確認できます。

  1. 新しいタスクが起動 → すぐにSTOPPED(終了コード 1)

  2. ECS が起動を何度か再試行する

  3. 失敗が続いたため、サーキットブレーカーが作動

  4. デプロイがROLLBACK_IN_PROGRESS→ 直前のリビジョン(v3)に自動で戻る
  5. CodePipeline の Deploy ステージは Failed になる

 

この間、エンドユーザーが見ているであろうブラウザの表示はv3のリビジョンの内容を表示し続けます。新しいタスクが正常にならない限り、古いタスクは止められないためです(最小実行タスク率100%の設定にしているためです)。

5-3. ECRのlatestを元に戻す

ECRのlatestタグは壊れたイメージを指したままです。このまま放置すると、次に誰かが何かを push したり、パイプラインを再実行したりしたときに、また壊れたイメージがデプロイされかねません。latestをv3に付け直して、パイプラインを正常終了させておきます。

docker tag ${REPO}:v3 ${ECR_URI}:latest
docker push ${ECR_URI}:latest

Codepipelineが、Deployまで成功したことを確認してください。

まとめ

以下の点を確認しました。

  1. リリースの実体は、「新しいリビジョンを作って、サービスを更新する」であること。

  2. ローリングアップデートは、最小 / 最大実行タスク率で挙動が決まること。
  3. ECR ソースが出すのはimageDetail.jsonファイル、ECS デプロイが求めるているのはimagedefinitions.jsonファイル。そのため、CodePipelineでCommandsアクションを使用して間をつないでいます。
  4. パイプラインの起動は EventBridge 経由であること。

続き

ECSネイティブ Blue/Greenデプロイを確認します。 (第3回へ移動する。)

最後に

ここで作成したリソースを削除する場合は、以下のリソースを削除してください。次の回に進む場合は、同じリソースを使用しますので削除せずに進みます。

  1. CodePipeline…ecs-handson-pipelineを削除
  2. EventBridge ルール…パイプライン削除時に自動で消えない場合があるので確認し、残っていれば削除
  3. パイプラインのサービスロール…IAM コンソールでAWSCodePipelineServiceRole-ap-northeast-1-ecs-handson-pipelineを削除
  4. アーティファクト用 S3 バケット…codepipeline-ap-northeast-1-で始まるバケット。中身を空にしてから削除します。(必ずバケットの中を確認し、他の人や別プロジェクトで同じバケットを使用している場合はバケットは削除しないでください。)
  5. CloudWatch ロググループ…/aws/codepipeline/ecs-handson-pipeline(Commands アクションのログ)
  6. ECS サービス … ecs-handson-service を削除(タスクも一緒に消えます)
  7. ECS クラスター … ecs-handson-cluster を削除
  8. ALB … ecs-handson-alb を削除
  9. ターゲットグループ … ecs-handson-tg-blue を削除(ALB 削除後でないと消せません)
  10. ECR リポジトリ … ecs-handson-nginx を削除(イメージが入っていても強制削除できます)
  11. CloudWatch ロググループ … /ecs/ecs-handson-task を削除
  12. VPC … ecs-handson-vpc を削除

アーティファクト用バケットは同じリージョンの他のパイプラインでも共用されます。他にパイプラインを使っている場合は削除しないでください。

 

shibuya
著者:shibuya
クラウドセントリック株式会社 所属ITエンジニア(主にインフラ構築) 時々、演劇を観にいくことで気晴らししています。

エンジニア積極採用中!

クラウドセントリックでは、業務拡大に伴いエンジニアを積極採用中です。
一緒に働きたいと思った方は、採用フォームからぜひご応募ください。
MENU