概要
- Amazon ECS 上で実行するコンテナをローカルでテストする際ってどうしてます?
- すでにご存知の方はバシバシ使われているかもですが、改めて焼き直しということで本ブログを書いていきます。
- 紹介するツールは、こちらの amazon-ecs-local-container-endpoints と ecs-cli です。
ちなみに ECS ってなにもの?
- Amazon ECSとは、AWSのフルマネージドなコンテナオーケストレータサービスです。
- また、コンテナが実行される場所(データプレーン)としては、fargate、EC2、Anywhere などがあります。
amazon-ecs-local-container-endpoints
- まず初めに amazon-ecs-local-container-endpoints についてです。
- 一言で表すと、ECS 上で実行するコンテナをデプロイする前に手元のローカル環境上でテストするためのツールです。
- ちなみに、ここで述べているテストというのは複数のテストを指しています。下記がツールを使用したときに検証できる内容になります。
- AWS の各サービスとコンテナ内のアプリがやりとりしている場合、その権限等が足りているのかを検証
- ECS におけるタスク定義の検証
- データプレーンが EC2 の場合、使用可能なネットワーキングモードが選べ、 awsvpc を選択したときのエミュレートによる検証
- 個別のタスクとして実行される複数のアプリケーションをローカル環境で検証
何が嬉しいの?
- このツールの嬉しいところは、コンテナ実行のクレデンシャル情報やタスクメタデータのエンドポイントへのアクセスを検証するだけのために ECS に対しデプロイする必要がなくなることですね。
このツールを使わないとどうすることになるのか。
- 例えば、ECS 上で実行されているコンテナが IAM ロールを使用して S3 などのサービスにアクセスする場合に、ローカルで実行するには、ローカルではクレデンシャルを環境変数などで起動するアプリケーションに渡して実行したりする必要があります。(もしくは、ローカル起動時には S3 にアクセスする機能を別の代替措置になるよう実装しておくとか)
- そんな時にこのツールを使うと、ECS で実行されるコンテナが使用するタスク用の IAM ロールを使用しているかのようにローカル環境のコンテナを動かすことができるようになります。
- それ以外にも美味しい機能がたくさんあるので、検証しながら残りを説明していきます。
検証
AWS の他のサービスを使用するためにクレデンシャル情報が必要なコンテナのテスト
- まず初めに検証することは、AWS のクレデンシャル情報を必要とするコンテナをローカルでテストする場合を想定します。
- 本ツールを使わないとなると、例えば環境変数にクレデンシャル情報を食わせ実行するなどする必要がありますが、本ツールを使用することでローカルで起動するコンテナに安全に認証情報を渡すことができます。
- 下記に、サンプルの docker-compose.yml と docker-compose.override.yml を用意しました。
docker-compose.yml
- ざっくりみていただければわかると思いますが、今回ローカルで起動するコンテナイメージには MySQL と WorldPress を使用しました。
docker-compose.yml
version: '3'
services:
db:
image: mysql:5.7
platform: linux/amd64
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
platform: linux/amd64
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
volumes:
db_data:
docker-compose.override.yml
- 上記のような docker-compose ファイルがあったときに、docker-compose.yml と同時に読まれ上書きしてくれる docker-compose.override.yml を用意し、下記の例のように Amazon ECS Local Container Endpoints を使用するための設定を記述します。
- 何をここではしているのかというと、この例では、ローカルのコンテナエンドポイントが IPアドレス(169.254.170.2)をリッスンできるように Docker のブリッジネットワークを作成し、環境変数 $AWS_CONTAINER_CREDENTIALS_RELATIVE_URI に指定した 169.254.170.2/creds にHTTPリクエストを行い資格情報を取得する仕組みになっています。
- ECS 上でコンテナが実運用されている場合、ECSエージェントはこのエンドポイントを経由してコンテナにクレデンシャルを送ります。
- じゃあ、元のクレデンシャル情報は???というと、この場合、デフォルトのAWS CLI Profileから取得した一時的なクレデンシャルを送信します。これは、AWS CLI用の資格情報と設定を含む.awsフォルダをマウントすることで実現しているのが分かるのではないでしょうか。
docker-compose.override.yml
version: "3"
networks:
credentials_network:
driver: bridge
ipam:
config:
- subnet: "169.254.170.0/24"
gateway: 169.254.170.1
services:
ecs-local-endpoints:
image: amazon/amazon-ecs-local-container-endpoints
volumes:
- /var/run:/var/run
- $HOME/.aws/:/home/.aws/
environment:
HOME: "/home"
AWS_PROFILE: "default"
networks:
credentials_network:
ipv4_address: "169.254.170.2"
wordpress:
depends_on:
- ecs-local-endpoints
networks:
credentials_network:
ipv4_address: "169.254.170.3"
environment:
AWS_DEFAULT_REGION: "ap-northeast-1"
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI: "/creds"
実際に、docker-compose up をしてみると下記のようなコンテナたちが起動していることが確認できます。
タスク用の IAM ロールの認証情報を使用したテスト
- ローカルでのテストする用の docker-compose ファイルで タスク用の IAM ロールを使用するには、AWS_CONTAINER_CREDENTIALS_RELATIVE_URIの値を変更するだけです。
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI: "/role/<name of your role>"
- 例えば、ecs_task_role という名前のロールであれば、環境変数を /role/ecs_task_role に設定する必要があります。
- これだけで、ecs-local-endpoints コンテナは、タスクロールを引き受けることで得られた認証情報を利用して、タスク用の IAM ロールに設定された権限が、アプリケーションを実行するのに十分であるかをテストすることができます。
タスクメタデータエンドポイントを使用するコンテナのテスト
- タスクメタデータエンドポイントを利用すると、ECS上で動作するコンテナ自身に関する情報を取得できるようにできます。
- つまり、コンテナに関するリソース情報を取れるということですね。
- 下記のように設定します。
ECS_CONTAINER_METADATA_URI: "http://169.254.170.2/v3"
ecs-cli
-
ecs-cli とは、
Docker Compose ファイル形式を使用して、Amazon ECS および AWS Fargate でアプリケーションを実行するためのCLI
と公式ドキュメントでは記載されています。
引用: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html
- では、ecs-cli を使用するとどのようにローカルでのテストができるようになるのかを検証していきます。
タスク定義から(ローカルにあるタスク定義)
- ecs-cli を使用するとローカル環境用でテストしたい ECS のタスク定義があった時に、タスク定義からDocker Composeファイルを生成し、検証することができるのです。
- やってみましょう。
- まずは、タスク定義を用意します。ここでも image に wordpress と mysql を使用しています。
test.json
{
"containerDefinitions": [
{
"name": "wordpress",
"image": "wordpress",
"cpu": 10,
"memory": 500,
"essential": true,
"links": [
"mysql"
],
"portMappings": [
{
"containerPort": 80,
"hostPort": 8080
}
]
},
{
"name": "mysql",
"image": "mysql",
"cpu": 10,
"memory": 500,
"essential": true,
"environment": [
{
"name": "MYSQL_ROOT_PASSWORD",
"value": "password"
}
]
}
],
"family": "test"
}
- 次に、下記コマンドで、タスク定義から、docker-composeファイルを生成します。
$ ecs-cli local create --task-def-file test.json --output docker-compose.test.yml 1 err 23:19:47
INFO[0000] Reading task definition from /Users/koitabashi/Desktop/qiita/20221108/test.json
INFO[0000] Successfully wrote docker-compose.test.yml
INFO[0000] Successfully wrote docker-compose.test.override.yml
- 下記が生成された docker-compose ファイル群になります。
docker-compose.yml
version: "3.4"
services:
mysql:
logging:
driver: json-file
wordpress:
logging:
driver: json-file
docker-compose.test.yml
version: "3.4"
services:
mysql:
environment:
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI: /creds
ECS_CONTAINER_METADATA_URI: http://169.254.170.2/v3
MYSQL_ROOT_PASSWORD: password
image: mysql
labels:
ecs-local.task-definition-input.type: local
ecs-local.task-definition-input.value: /Users/koitabashi/Desktop/qiita/20221108/test.json
networks:
ecs-local-network: null
wordpress:
environment:
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI: /creds
ECS_CONTAINER_METADATA_URI: http://169.254.170.2/v3
image: wordpress
labels:
ecs-local.task-definition-input.type: local
ecs-local.task-definition-input.value: /Users/koitabashi/Desktop/qiita/20221108/test.json
links:
- mysql
networks:
ecs-local-network: null
ports:
- target: 80
published: 8080
networks:
ecs-local-network:
external: true
- 次に、生成された docker-compose.test.yml を使用して、ローカル環境でコンテナを起動します。
$ ecs-cli local up --task-def-compose docker-compose.test.yml ok 23:27:22
INFO[0000] Creating network: ecs-local-network...
INFO[0000] Created network ecs-local-network with ID 6574c1e44a0e065b53f633edd08d489534aa30aa3740eb78c29ae3f24a36e130
INFO[0000] Created the amazon-ecs-local-container-endpoints container with ID ec6fb6c6638b9504abe1883ba4dc7b0a01807b9ee4faa4c1b0c88c3dda8cc21f
INFO[0000] Started container with ID ec6fb6c6638b9504abe1883ba4dc7b0a01807b9ee4faa4c1b0c88c3dda8cc21f
INFO[0000] Using docker-compose.test.yml, docker-compose.test.override.yml files to start containers
⠿ Container 20221108-mysql-1 Started
⠿ Container 20221108-wordpress-1 Started
- さてプロセスを確認してみましょう。
- いい感じですね。
$ docker ps ok 4s 23:28:34
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
10c90bf94b9a wordpress "docker-entrypoint.s…" 52 seconds ago Up 51 seconds 0.0.0.0:8080->80/tcp 20221108-wordpress-1
16d49da1dfc9 mysql "docker-entrypoint.s…" 54 seconds ago Up 52 seconds 3306/tcp, 33060/tcp 20221108-mysql-1
ec6fb6c6638b amazon/amazon-ecs-local-container-endpoints "/local-container-en…" 2 minutes ago Up 2 minutes 80/tcp amazon-ecs-local-container-endpoints
この検証より、ECSのタスク定義だけを利用して、ローカル環境でdocker-composeなどを0ベースで書かずにコンテナを起動することができました。
タスク定義から(AWS上にあるタスク定義)
-
実は上記で検証したタスク定義から Docker-compose を利用してコンテナを起動するやり方にはもう一つ方法があります。
-
それは、AWS上に既にあるタスク定義を指定して、ローカル環境で起動することができるというものです。
-
やってみましょう。
-
次に、ecs-cli を実行する際にタスク定義の ARN が必要になるので、aws cli を利用して取得します。
aws ecs describe-task-definition --task-definition test --query "taskDefinition.taskDefinitionArn" --output text
- 次に取得した ARN を使用して ecs-cli を実行します。
ecs-cli local up --task-def-remote arn:aws:ecs:ap-northeast-1:123456789012:task-definition/test:2
INFO[0000] Reading task definition from test:2
INFO[0000] Task Definition network mode is ignored when running containers locally. Tasks will be run in the ecs-local-network. networkMode=awsvpc
INFO[0000] Successfully wrote docker-compose.ecs-local.yml
INFO[0000] Successfully wrote docker-compose.ecs-local.override.yml
INFO[0000] Creating network: ecs-local-network...
INFO[0000] Created network ecs-local-network with ID xxxxxxxxxxxxxxxxxxxxxxxx
INFO[0000] Created the amazon-ecs-local-container-endpoints container with ID xxxxxxxxxxxxxxxxxxx
INFO[0000] Started container with ID xxxxxxxxxxxxxxxxxxxxxxxx
INFO[0000] Using docker-compose.ecs-local.yml, docker-compose.ecs-local.override.yml files to start containers
[+] Running 2/2
⠿ Container test-wordpress-1 Started
⠿ Container test-mysql-1 Started
- さてプロセスを確認してみましょう。
- こちらもいい感じですね。
docker ps ok 23:47:30
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
872dd7038a30 wordpress "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 80/tcp test-wordpress-1
9294fa575bf9 mysql "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 3306/tcp, 33060/tcp test-mysql-1
04544a72d52e amazon/amazon-ecs-local-container-endpoints "/local-container-en…" 2 minutes ago Up 2 minutes 80/tcp amazon-ecs-local-container-endpoints
検証より、AWS 上にあるタスク定義を利用して、ローカル環境上で簡単にコンテナを起動することができました。
まとめ
- まとめる元気も無くなってきたので、めっちゃ便利じゃない??で締めさせてください。。
- 最後まで読んでいただき、ありがとうございました!!
参考文献