AWS ECSのメタデータを動的に取得する方法とその環境構築
こんにちは、エンジニアの角です。
背景
弊社ではバッチ処理の通知をSlackで行っています。
バッチ処理は、異なるVPCでの2種類のECSタスクを実行して、結果を通知しているのですが、
通知メッセージが同一であったため、どちらのタスクで行われているものなのかが判別しづらい状況でした。
そこで、ECSメタデータを取得し、そこからタスク定義などを通知メッセージに付加することにしました。
今回は、ローカルのDocker環境において、ECSと見立てたコンテナを含む環境を構築し、
疑似的にエンドポイントを生成して、ECSメタデータ(のようなもの)を取得する構築方法をご紹介します。
結論
下記のcompose.ymlファイルでメタデータ取得のための環境が構築できます。
version: "3.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:
# Mount /var/run so we can access docker.sock and talk to Docker
- /var/run:/var/run
networks:
credentials_network:
ipv4_address: "169.254.170.2" #subnet内。メタデータのエンドポイントになる。
batch:
build:
context: .
dockerfile: Dockerfile
target: development
container_name: batch
volumes:
- ./app/:/app/
environment:
- ECS_CONTAINER_METADATA_URI_V4=http://169.254.170.2/v3/containers/batch
platform: linux/amd64
ports:
- "9000:8080"
networks:
credentials_network:
ipv4_address: "169.254.170.3" #subnet内
depends_on:
ecs-local-endpoints:
condition: service_started
ポイント
credentialのマウントは今回不要です。
services:
ecs-local-endpoints:
volumes:
# Mount the shared configuration directory, used by the AWS CLI and AWS SDKs
# On Windows, this directory can be found at "%UserProfile%\.aws"
# - $HOME/.aws/:/home/.aws/
ECSメタデータ
先述した環境でECSメタデータを取得すると、以下のようなjsonデータが取得することができます。
{
"Cluster": "arn:aws:ecs:us-west-2:ExampleAWSAccountNo1;:cluster/default",
"TaskARN": "arn:aws:ecs:us-west-2:ExampleAWSAccountNo1;:task/default/febee046097849aba589d4435207c04a",
"Family": "query-metadata",
"Revision": "7",
"DesiredStatus": "RUNNING",
"KnownStatus": "RUNNING",
"Limits": {
"CPU": 0.25,
"Memory": 512
},
"PullStartedAt": "2020-03-26T22:25:40.420726088Z",
"PullStoppedAt": "2020-03-26T22:26:22.235177616Z",
"AvailabilityZone": "us-west-2c"
}
今回はここからECSのタスク定義とそのリビジョンを取り出して、通知を行います。
実装
タスク定義(Family)およびリビジョン(Revision)を取得しSlackのwebhookにポストするPythonスクリプトを作りました。
# ECSメタデータAPIから情報を取得
response = requests.get(os.environ.get("ECS_CONTAINER_METADATA_URI_V4") + "/task")
# 取得したメタデータの整形
family = response.json()["Family"]
revision = response.json()["Revision"]
message = f"""
タスク定義:{family}
リビジョン:{revision}
"""
# slack webhookへpost
requests.post(
"slackのURL",
data=json.dumps(
{
"attachments": [
{
"text": message,
}
],
}
),
)
開発環境とECS環境での違い
開発環境とECS環境での違いを図を用いて紹介します。
開発環境ではECSメタデータエンドポイントを自前で用意しているところがポイントです。
開発環境
ECS環境
ECSの環境ではECSメタデータエンドポイントははじめから用意されています。
その他
ECSメタデータには、取得方法にいくつかのバージョンがあります。以下の記事を参考にしてみてください。
今回の実装は、以下の記事の最初のシナリオを参考にしました。
まとめ
ECSメタデータを取得することができるローカル環境を構築する方法を今回はご紹介しました。
ぜひ、みなさんも試してみてください。
参考
Discussion