ECSに必要なVPCエンドポイントまとめ(2022年版)
こんにちは、八木です。
プライベートサブネットからAWSのサービスエンドポイントに接続するには、NAT Gatewayを使ってインターネット経由でアクセスするか、VPCエンドポイントを使用する必要があります。
この際、セキュリティ要件などからインターネットを経由したくない場合があります。また、料金の面からNAT GatewayではなくVPCエンドポイントを使いたいといったケースもあるでしょう。
今回の記事では、ECSを利用する際に必要なVPCエンドポイントをまとめてみました。
NATとVPCエンドポイントどちらを使うか悩んでいる方、VPCエンドポイントのみで構成したい方の参考になれば幸いです。
以前の記事で似たものがありますが、本記事執筆時点ではサービスアップデートによる変更があります。
具体的には、Fargateのプラットフォームタイプ、バージョンによって必要なエンドポイントが変わりました。
また、今回の記事では必須のエンドポイントだけでなく、構成によって必要になるエンドポイントもあわせてご紹介します。
先に結論
ECSのエンドポイント
エンドポイント | EC2 | Fargate |
---|---|---|
com.amazonaws.region.ecs-agent | 必要 | 不要 |
com.amazonaws.region.ecs-telemetry | 必要 | 不要 |
com.amazonaws.region.ecs | 必要 | 不要 |
ECRのエンドポイント
エンドポイント | EC2 | Fargate Linux 1.4.0 | Fargate Linux 1.3.0以前 | Fargate Windows 1.0.0 |
---|---|---|---|---|
com.amazonaws.region.ecr.dkr | 必要 | 必要 | 必要 | 必要 |
com.amazonaws.region.ecr.api | 必要 | 必要 | 不要 | 必要 |
com.amazonaws.region.s3(ゲートウェイ型) | 必要 | 必要 | 必要 | 必要 |
その他エンドポイント
以下のエンドポイントは構成によって必要になります。
- CloudWatch Logs エンドポイント(
com.amazonaws.region.logs
) - Secrets Manager エンドポイント(
com.amazonaws.region.secretsmanager
) - Systems Manager エンドポイント(
com.amazonaws.region.ssm
,com.amazonaws.region.ssmmessages
)
ECSのエンドポイント解説
表に記載した通りです。EC2の場合はVPCエンドポイントが必要な一方、Fargateでは必要ありません。
EC2ではコンテナエージェントがECSサービスと通信する必要があるため、VPCエンドポイントが必要になっています。
ECRのエンドポイント解説
コンテナイメージをECRに保存している場合はECRへのエンドポイントが必要です。
必要なエンドポイントはキャパシティプロバイダーごとに決まっており、EC2の場合はcom.amazonaws.region.ecr.dkr
, com.amazonaws.region.ecr.api
, com.amazonaws.region.s3
(ゲートウェイ型)の3つ全てが必要です。
Fargateは以前はcom.amazonaws.region.ecr.api
が必要なかったのですが、Linux 1.4.0およびWindows 1.0.0から必要になりました。
その他エンドポイントの解説
以降のエンドポイントは、構成によって必要なものです。それぞれ解説していきます。
CloudWatch Logs エンドポイント
com.amazonaws.region.logs
ログをCloudWatch Logsに送信するのに必要なエンドポイントです。SaaSや独自でログを取得するシステムを構築していない限り、サービス運用上ほぼ必須と言って良いでしょう。
awslogsログドライバーを使用する場合、必ず必要になります。
Secrets Manager エンドポイント
com.amazonaws.region.secretsmanager
タスク定義でSecrets Managerの値を環境変数として渡すように指定していた場合、必要になります。
DBへの接続情報などをSecrets Managerに保存している場合は利用することになるでしょう。
Systems Manager エンドポイント
com.amazonaws.region.ssm
,com.amazonaws.region.ssmmessages
Systems Managerのエンドポイントは、パラメータストアとECS Execを使用する際に必要です。
Secrets Managerと同様、ECSではコンテナに環境変数としてSSMパラメータストアの値を渡すことができます。
SSMパラメータストアを利用するには、com.amazonaws.region.ssm
のVPCエンドポイントが必要です。
ECS Execは稼働中のコンテナにログインできる機能です。この機能はSSM Session Managerを利用しており、com.amazonaws.region.ssmmessages
のVPCエンドポイントが必要になります。
やってみた
今回の記事で取り上げたVPCエンドポイントを使う構成を作ってみます。
VPCエンドポイントが1つもない状態から構築し、タスク起動時のエラー内容を確認しながらVPCエンドポイントを追加していきます。
構成は以下です。
キャパシティプロバイダー:Fargate
コンテナイメージリポジトリ:ECR
ログ:CloudWatch Logs
パラメータストア:Systems Manager Parameter Store, Secrets Manager
事前準備
ECR, ECS, KMS, SSM Parameter Store, Secrets Managerを作成します。
なお、今回の検証ではVPCエンドポイント起因のエラーに着目するため、ECSのタスク実行ロールおよびタスクロールにAdministrator権限を使用しています。本番運用では必要最小限のアクセス許可を指定してください。
まずECRリポジトリを作成します。
aws ecr create-repository --repository-name ecs-test
作成したECRリポジトリにログインし、
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com
適当なDockerイメージをDocker Hubからpullして、
docker pull --platform linux/amd64 httpd:2.4
ECRリポジトリにpushします。
docker tag httpd:2.4 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/ecs-test:latest docker push 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/ecs-test:latest
次にSSMパラメータストアの暗号化に使用するKMSキーを作成します。
aws kms create-key
SSMパラメータストアに、作成したKMSを使って暗号化した値を保存します。
(暗号化してもしなくても、必要なVPCエンドポイントは変わりません。KMSのVPCエンドポイントが必要ないことを確認するためにKMS暗号化をしています。)
aws ssm put-parameter --name ecs-test --value "secret-value-in-parameter-store" --type SecureString --key-id xxxx-xxxxxxx-xxxxxxx-xxxxxxx
Secrets Managerのシークレットを作成します。
aws secretsmanager create-secret --name ecs-test --secret-string '{"key1":"secret-value-1"}'
次にECSクラスター、タスク定義を作成します。
タスク定義では、Secrets ManagerおよびSSMパラメータストアの値をコンテナの環境変数で利用するように設定します。
aws ecs create-cluster --cluster-name ecs-test --capacity-providers FARGATE
aws ecs register-task-definition \ --family ecs-test \ --task-role-arn arn:aws:iam::123456789012:role/ECSExecTaskRole \ --execution-role-arn arn:aws:iam::123456789012:role/ecsTaskExecutionRole \ --network-mode awsvpc --cpu 256 --memory 512 \ --container-definitions '[{"name":"web","image":"123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/ecs-test","portMappings":[{"containerPort":80}],"essential":true,"secrets":[{"name":"SECRETS_MANAGER_VALUE","valueFrom":"arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:ecs-test-0x0KIE:key1::"},{"name":"SSM_PARAMETER_VALUE","valueFrom":"arn:aws:ssm:ap-northeast-1:123456789012:parameter/ecs-test"}],"logConfiguration":{"logDriver":"awslogs","options":{"awslogs-region":"ap-northeast-1","awslogs-group":"/ecs/ecs-test","awslogs-stream-prefix": "ecs"}}}]' \ --runtime-platform '{"cpuArchitecture":"X86_64","operatingSystemFamily":"LINUX"}' \ --requires-compatibilities "FARGATE"
以上でECSの実行環境が整いました。
エラーを確認しつつ、VPCエンドポイントを追加してみる
ではタスクを実行し、エラーを確認しつつエンドポイントを追加していきます。
まず、VPCエンドポイントがない状態でECSタスクを実行してみます。
aws ecs run-task \ --task-definition ecs-test \ --cluster ecs-test \ --count 1 \ --enable-execute-command \ --launch-type FARGATE \ --network-configuration '{"awsvpcConfiguration":{"subnets":["subnet-xxxxxxxxxxxxxx"],"securityGroups":["sg-xxxxxxxxxxxxxxxxxxx"]}}'
AWSコンソールからタスクを確認してみると、ステータスが「停止済み」になっていました。
停止理由に ResourceInitializationError: unable to pull secrets or registry auth: execution resource retrieval failed: unable to retrieve secret from asm: service call has been retried 5 time(s): failed to fetch secret arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:ecs-test-0x0KIE from secrets manager: RequestCanceled: request context canceled caused by: context deadline exceeded
とあります。
環境変数に指定しているSecrets Managerの値を取得できないことが原因のようです。
Secrets ManagerへのVPCポイント(com.amazonaws.region.secretsmanager
)を追加してみます。
再度ECSタスクを実行してみると、停止理由が変わりました。
ResourceInitializationError: unable to pull secrets or registry auth: execution resource retrieval failed: unable to retrieve secrets from ssm: service call has been retried 5 time(s): RequestCanceled: request context canceled caused by: context deadline exceeded
Secrets Managerのエラーは解消しましたが、次はSSMパラメータストアからの値が取れていないようです。
SSMパラメータストアに必要なVPCポイント(com.amazonaws.region.ssm
)を追加してみます。
再びECSタスクを立ち上げると停止理由が以下になりました。
ResourceInitializationError: unable to pull secrets or registry auth: execution resource retrieval failed: unable to retrieve ecr registry auth: service call has been retried 3 time(s): RequestError: send request failed caused by: Post "https://api.ecr.ap-northeast-1.amazonaws.com/": dial tcp xxx.xxx.xxx.xxx:443: i/o timeout
ECRレジストリの認証エラーです。
今回はFargate Linux 1.4.0を利用しているため、ECRからイメージのプルに必要な以下のVPCエンドポイントを追加します。
com.amazonaws.region.ecr.dkr
com.amazonaws.region.ecr.api
com.amazonaws.region.s3
(ゲートウェイ型)
再びECSタスクを立ち上げると停止理由が変わりました。
ResourceInitializationError: failed to validate logger args: : signal: killed
エラー内容からは原因を特定しにくいですが、CloudWatch Logsへ通信できないことが原因です。
awslogsログドライバーが無効の場合はこちらのエラーは発生しません。
では、CloudWatchLogsのエンドポイントを追加します。
タスクはまた停止しましたが、別の停止理由になりました。
ResourceInitializationError: failed to validate logger args: create stream has been retried 1 times: failed to create Cloudwatch log stream: ResourceNotFoundException: The specified log group does not exist. : exit status 1
今度は通信エラーではなく、Cloud Watch Logsのロググループが存在しないことが原因でした。
CLIからロググループを作成し、再度起動します。
aws logs create-log-group --log-group-name /ecs/ecs-test
ついにタスクが停止することなく、動作しました。
以上でECSタスクの実行に必要なVPCエンドポイントは揃いました。
最後はECS Execの確認です。
CLIからECS Execを実行してみます。
aws ecs execute-command --cluster ecs-test --task d3d8b8e2a39c46b6a9d69b057eb7302d --container web --interactive --command "/bin/bash" The Session Manager plugin was installed successfully. Use the AWS CLI to start a session. An error occurred (TargetNotConnectedException) when calling the ExecuteCommand operation: The execute command failed due to an internal error. Try again later.
エラー終了してしまいました。
ECS Execに必要なVPCエンドポイントはcom.amazonaws.region.ssmmessages
です。
ただしログをCloud Watch LogsやS3に保存する場合や、クライアントとECSタスク間の通信の暗号化に独自のKMSキーを利用する場合は、別途VPCエンドポイントが必要です。
com.amazonaws.region.ssmmessages
を追加します。
既存のタスクに再度接続しようとしましたが、同じエラーが発生してしまいました。
新しくタスクを起動してログインしてみると問題なく接続できました。
aws ecs execute-command --cluster ecs-test --task b89090a220ba42b7a215b0d28203efa1 --container web --interactive --command "/bin/bash" The Session Manager plugin was installed successfully. Use the AWS CLI to start a session. Starting session with SessionId: ecs-execute-command-09f3ef4c8736bf1fa root@ip-10-0-3-225:/usr/local/apache2#
Secrets ManagerおよびSSMパラメータストアから正常に環境変数に設定されていることも確認できました。
root@ip-10-0-3-225:/usr/local/apache2# echo $SECRETS_MANAGER_VALUE secret-value-1 root@ip-10-0-3-225:/usr/local/apache2# echo $SSM_PARAMETER_VALUE secret-value-in-parameter-store
さいごに
今回の記事ではECSに必要なVPCエンドポイントをまとめました。
コンプライアンスやコストの面から、NAT Gatewayではなく、VPCエンドポイントを利用するという選択肢を取ることもあるかと思います。
アーキテクチャによって、必要なVPCエンドポイントを整理し、追加していきましょう。
以上、八木でした!
参考リンク
Linux プラットフォームのバージョン - Amazon Elastic Container Service
Amazon ECR インターフェイス VPC エンドポイント (AWS PrivateLink) - Amazon ECR
ステップ 6: VPC エンドポイントの作成 - AWS Systems Manager
Amazon ECS とインターフェイス VPC エンドポイント (AWS PrivateLink) - Amazon Elastic Container Service
デバッグ用にAmazon ECS Exec を使用 - Amazon ECS
コンテナへの機密データの受け渡し - Amazon ECS
リファレンス: ec2messages、ssmmessages およびその他の API オペレーション - AWS Systems Manager