Amazon ECS サービスを更新していないタスク定義のリビジョンは ECS 標準デプロイアクションでは無視される

AWS

2024.12.23

Topics

この記事は NHN テコラス Advent Calendar 2024 の 23 日目の記事です。

概要

ECS のタスク定義を更新した後、CodePipeline を実行するとタスク定義で変更した更新がロールバックされていました。
その動作と解決策について色々と検証した記録をまとめます。

結論

先に結論を述べます。

ECS 標準デプロイアクションの仕様として、ECS サービスを更新していないタスク定義のリビジョンは無視されるようです。

CodePipeline の Amazon ECS 標準デプロイアクションは、Amazon ECS サービスによって使用されるリビジョンに基づいて、タスク定義の独自のリビジョンを作成します。
Amazon ECS サービスを更新せずにタスク定義の新しいリビジョンを作成した場合、デプロイアクションはそれらのリビジョンを無視します。
Tutorial: Amazon ECS Standard Deployment with CodePipeline – AWS CodePipeline

そのため、今回の検証内容のように以下の両条件を満たす場合、タスク定義を更新する際は変更がロールバックされる可能性があるためご注意ください。

  1. タスク定義のリビジョンだけを更新した場合
    • ECS サービスは更新していない
  2. CodePipeline の ECS 標準デプロイアクションを実行する場合

対策としては、タスク定義のリビジョンを更新した後、ECS サービスで最新のリビジョンを使用してタスクをデプロイしてください。

発生した事象

発生した事象の前提について、以下の内容に沿って簡単に記述します。

  • 構成図
  • 発生した事象

構成図

ポイントとしては、以下の通りです。

  • CodePipeline のデプロイステージでは、「ECS 標準デプロイアクション」を使用している点
  • ECS 標準デプロイアクションでは、タスク定義の独自のリビジョンを新規で作成する点

その他については、基本的な ECS 設定 と CI/CD の環境です。

構成図

チュートリアル: を使用した Amazon ECS 標準デプロイ CodePipeline – AWS CodePipeline
Amazon Elastic Container Service デプロイアクションリファレンス – AWS CodePipeline

発生した事象

実際の動作については、後述の検証で確認しますが以下の流れです。
ここでは、構成図をもとに机上で解説します。

1. 初期状態

リビジョン 1 のタスク定義を用いて、タスクが起動している状態です。

初期状態の机上図

2. 手動でタスク定義を更新した状態

タスク定義を CPU とメモリのみを手動でコンソールから更新します

手動でタスク定義を更新した状態の机上図

3. CodePipeline で自動パイプライン実行された状態

CodePipeline を実行すると新しいタスク定義が作成されます。
作成された新しいタスク定義のリビジョン 3 にはリビジョン 2 の CPU とメモリが引き継がれておりません。

CodePipeline が実行された状態の机上図

リビジョン 2 で手動で変更した内容をもとに、新しいリビジョン 3 のタスク定義がデプロイされることを期待しましたが、実際はリビジョン 1 の内容がデプロイされています。

回避する方法

ECS 標準デプロイアクションは、現在デプロイされているタスク定義をもとに更新を行う仕様のようです。
そのため、タスク定義を更新した場合は、そのタスク定義でタスクをデプロイするようにすれば、設定がロールバックされることはありません。

この動作は、CodePipeline の仕様のようなので、運用面で見直していくしか方法はなさそうです。

動作検証

では、続いては上述した動作を実際に検証してみます。
この動作検証では、以下の 2 つのケースを確認します。

  1. 手動でタスク定義のリビジョンを更新しただけの場合
    • 実際の挙動の事実確認
  2. 手動でタスク定義のリビジョンを更新したあと ECS サービスをアップデートした場合
    • 事象を回避するための方法

手動でタスク定義のリビジョンを更新しただけの場合

手順

  1. タスク定義を手動で更新
    1. CPU とメモリを変更
  2. CodePipeline でパイプラインを実行
    1. 新しいリビジョンでタスク定義を更新
  3. ECS サービスが更新される
    1. 新しいリビジョンのタスク定義でタスク作成

まずは、リビジョン 1 でデプロイしている状態です。

タスク定義 リビジョン1

リビジョン 1 のタスク定義の CPU とメモリは以下の通り定義しています。

  • CPU : 2 vCPU
  • メモリ : 4 GB

タスク定義 リビジョン1 CPUとメモリ

1. タスク定義を手動で更新

では、タスク定義をコンソールから手動で更新します。

リビジョン 2 のタスク定義の CPU とメモリは以下の通り更新しています。

  • CPU : 2 vCPU → 1 vCPU
  • メモリ : 4 GB → 3 GB

タスク定義 リビジョン2のCPUとメモリ

この状態で、 ECS サービスのタスク定義は更新しません。

2. CodePipeline でパイプラインを実行

では、続いては、パイプラインを実行します。
デプロイまで完了しました。

CodePipelineデプロイ画面

3. ECS サービスが更新される

まず、タスク定義の状態から確認します。
リビジョン 3 に更新されていました。

タスク定義 リビジョン3

リビジョン 3 の内容は、リビジョン 1 の CPU とメモリが引き継がれています。

タスク定義 リビジョン3のCPUとメモリ

次に、ECS サービスを確認します。
パイプラインで更新されたリビジョン 3 が指定されています。

タスク定義 リビジョン3 ECSデプロイ画面

当初、発生した事象が確認できました。
次は、これを回避する方法を試します。

手動でタスク定義のリビジョンを更新したあと ECS サービスをアップデートした場合

先ほどと違い、パイプラインを実行する前に、ECS サービスの更新手順を追加しています。

手順

  1. タスク定義を手動で更新
    1. CPU とメモリを変更
  2. 更新したリビジョンで ECS サービスを更新
  3. CodePipeline でパイプラインを実行
    1. 新しいリビジョンでタスク定義を更新
  4. ECS サービスが更新される
    1. 新しいリビジョンのタスク定義でタスク作成

先ほど使用したタスク定義をそのまま使うので、リビジョン 3 を初期状態とします。

タスク定義 リビジョン3初期状態

リビジョン 3 のタスク定義の CPU とメモリは以下の通り定義しています。

  • CPU : 2 vCPU
  • メモリ : 4 GB

タスク定義 リビジョン3 CPUとメモリ

1. タスク定義を手動で更新

では、先ほどと同じ様にタスク定義を更新します。

リビジョン 4 のタスク定義の CPU とメモリは以下の通り更新しています。

  • CPU : 2 vCPU → 1 vCPU
  • メモリ : 4 GB → 3 GB

タスク定義 リビジョン4

2. 更新したリビジョンで ECS サービスを更新

次は、先程はなかった手順で ECS サービスを先程のリビジョン 4 に更新します。

更新したリビジョンで ECS サービスをアップデート

3. CodePipeline でパイプラインを実行

ここからは同じ様に、パイプラインを実行し、デプロイまで完了しました。

CodePipelineパイプライン実行

4. ECS サービスが更新される

まず、タスク定義から確認しますが、リビジョンが 5 に更新されています。

タスク定義 リビジョン5

内容は以下の通りです。
CPU とメモリは、リビジョン 4 を引き継いでいます。
意図した通りの挙動になっています。

タスク定義 リビジョン5のCPUとメモリ

タスクを見ると、リビジョン 5 がデプロイされています。

タスク定義 リビジョン5 ECSデプロイ画面

まとめ

CodePipeline の仕様によって、設定がロールバックすることがあるため、運用の際はご注意ください。

参考情報

Tutorial: Amazon ECS Standard Deployment with CodePipeline – AWS CodePipeline

テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!

Cold-Airflow

2021年新卒入社。インフラエンジニアです。RDBが三度の飯より好きです。 主にデータベースやAWSのサーバレスについて書く予定です。あと寒いのは苦手です。

Recommends

こちらもおすすめ

Special Topics

注目記事はこちら