Amazon ECS on EC2でキャッシュされたコンテナイメージを使用するには?

ECS on EC2はエージェントの環境変数「ECS_IMAGE_PULL_BEHAVIOR」設定でコンテナイメージのキャッシュを利用できます。
2021.02.03

Amazon ECS on EC2利用時に、コンテナの起動時間を短縮させるために、ホストでキャッシュされたコンテナイメージを使用したいことがあります。

Amazon ECS コンテナエージェントの環境変数「ECS_IMAGE_PULL_BEHAVIOR」を利用すると、イメージのプルプロセスをカスタマイズできます。

ECS_IMAGE_PULL_BEHAVIOR パラメーター

4つの中から選べます(説明文はマニュアルから引用)。

  • キャッシュを優先しない
    • default : リモートでイメージがプルされます。イメージのプルに失敗した場合、コンテナはそのインスタンスにキャッシュされたイメージを使用します。
    • always : 常にリモートでイメージがプルされます。イメージのプルに失敗した場合、そのタスクは失敗します。このオプションを選択すると、最新バージョンのイメージが常にプルされます。キャッシュされたイメージはすべて無視され、イメージの自動クリーンアッププロセスが適用されます。
  • キャッシュを優先する
    • once : 同じコンテナインスタンスの以前のタスクによりイメージがプルされていないか、自動クリーンアッププロセスによってキャッシュされたイメージが削除された場合にのみ、イメージがリモートでプルされます。それ以外の場合は、インスタンスにキャッシュされたイメージが使用されます。これにより、不要なイメージのプルがなくなります。
    • prefer-cached : キャッシュされたイメージがない場合に、リモートでイメージがプルされます。それ以外の場合は、インスタンスにキャッシュされたイメージが使用されます。キャッシュされたイメージが削除されないように、そのコンテナの自動イメージクリーンアップは無効です。

Linux/Windows ともにデフォルト値は default でまずはリモートからプルします。 結果的に、タグ名を固定する運用であっても、常に最新のイメージを利用できます。

ECS on Fargate は挙動としては always に該当します。

また、イメージの自動クリーンアッププロセスは次のドキュメントを参照ください。

自動化タスクとイメージのクリーンアップ - Amazon Elastic Container Service

やってみた

ホストでキャッシュされたイメージを使用するように設定変更し(ECS_IMAGE_PULL_BEHAVIOR=once)、イメージhttpd:2.4 を利用したタスクを起動して設定の違いを確認します。

デフォルト設定

まずはデフォルト設定での挙動を確認します。 default モードではリモートからイメージがプルされ、イメージのプルに失敗した場合、コンテナはそのインスタンスにキャッシュされたイメージを使用します。

初期状態

/etc/ecs/ecs.config

ECS_CLUSTER=test
ECS_BACKEND_HOST=

ECSクラスター起動直後は、タスクのイメージはホストには存在しません。

$ docker images
REPOSITORY                TAG                 IMAGE ID            CREATED             SIZE
amazon/amazon-ecs-agent   latest              52b440d0453a        7 days ago          61.4MB
amazon/amazon-ecs-pause   0.1.0               4451bd4bb15a        7 days ago          954kB

タスクを起動

タスク起動時のエージェントのログを確認します。

/var/log/ecs/ecs-agent.log

Task engine [...]: pulling image httpd:2.4 for container sample-zz-app concurrently" module=docker_task_engine.go
Task engine [...]: recording timestamp for starting image pulltime: 2021-01-28 19:36:11.914154829 +0000 UTC m=+125.610526843" module=docker_task_engine.go
Adding image name- httpd:2.4 to Image state- sha256:683a7aad17d3baed344799b397c55a9ccbc3ddabf0d077862739585ee76d4cb3" module=types.go
Updating container reference sample-zz-app in Image State - sha256:683a7aad17d3baed344799b397c55a9ccbc3ddabf0d077862739585ee76d4cb3" module=types.go
Task engine [...]: finished pulling image httpd:2.4 for container sample-zz-app in 4.653489084s" module=docker_task_engine.go

※ msg 部分のみ抜粋

"pulling image httpd:2.4 for container ..." からイメージをプルしていることがわかります。 プルプロセスには約6秒かかっていました。

$ docker images
REPOSITORY                TAG                 IMAGE ID            CREATED             SIZE
amazon/amazon-ecs-agent   latest              52b440d0453a        7 days ago          61.4MB
amazon/amazon-ecs-pause   0.1.0               4451bd4bb15a        7 days ago          954kB
httpd                     2.4                 683a7aad17d3        2 weeks ago         138MB

同じイメージを使ったコンテナをもう一度起動します。

/var/log/ecs/ecs-agent.log

Task engine [...]: pulling image httpd:2.4 for container sample-zz-app concurrently" module=docker_task_engine.go
Task engine [...]: recording timestamp for starting image pulltime: 2021-01-28 19:43:08.580561889 +0000 UTC m=+31.046339842" module=docker_task_engine.go
Updating container reference sample-zz-app in Image State - sha256:683a7aad17d3baed344799b397c55a9ccbc3ddabf0d077862739585ee76d4cb3" module=types.go
Task engine [...]: finished pulling image httpd:2.4 for container sample-zz-app in 1.597031292s" module=docker_task_engine.go

ホストにイメージキャッシュが存在するにも関わらず、初回と同じくリモートからプルしています。 プルプロセスも約6秒かかっていました。

once設定

次に、ホストのキャッシュを優先する once に設定変更します。

/etc/ecs/ecs.config

ECS_CLUSTER=test
ECS_BACKEND_HOST=
ECS_IMAGE_PULL_BEHAVIOR=once

タスクを起動

先ほどと同じイメージのコンテナを起動します。

/var/log/ecs/ecs-agent.log

Task engine [..]: image httpd:2.4 for container sample-zz-app has been pulled once, not pulling it again" module=docker_task_engine.go

"image httpd:2.4 for container sample-zz-app has been pulled once, not pulling it again" からキャッシュを利用していることがわかりますね。

約6秒かかっていたプルプロセスがほぼ0秒になりました。

ECS on Fargate ではキャッシュを利用できない

今回紹介したキャッシュ設定は ECS on EC2 では利用できますが ECS on Fargate では利用できません。

起動時間の短縮や転送量削減のために、待ち望んでいる人は多いかと思います。

次の GitHub 上のイシューでロードマップに積まれているので、今後に期待しましょう。

[Fargate/ECS] [Image caching]: provide image caching for Fargate. · Issue #696 · aws/containers-roadmap

参考