🔥

ECSコンテナへの接続方法とトラブルシューティングの解決方法

2024/09/14に公開

はじめに

Amazon ECS (Elastic Container Service) でのタスクやサービスの作成が完了した後、コンテナ内にシェルアクセスを行うためには、ECS Exec を利用するのが便利です。

本記事では、ECS Execを使ってコンテナに接続する方法と、接続時に遭遇した問題のトラブルシューティングについて詳しく説明します。


ECS Execを利用したコンテナ接続の手順

大まかな手順としては下記の通りです。

  1. タスクとサービスの作成
  2. IAMでポリシーをロールにアタッチ
  3. ECS Execの有効化
  4. サービスの再起動
  5. コンテナにアクセスする

次は、1つ1つの手順を解説していきます。


タスクとサービスの作成

まずは、ECSでタスクやサービスを作成します。
これにより、コンテナがECSクラスター内で実行されるようになります。
今回、作成したタスクのタスク定義の起動タイプは Fargate を使用しました。


IAMでポリシーをロールにアタッチ

次に、こちらの記事を参考に、ECSコンテナにアクセスするために必要なIAMロールを作成するため、IAMでAmazonECSTaskExecutionRolePolicyAmazonSSMManagedInstanceCore のポリシーをロールにアタッチさせました。

https://zenn.dev/nenenemo/articles/9f66924801114c


ECS Execの有効化

次に、今回、ECSコンテナにアクセスするために、ECS Exec というECSの機能を使用しました。

ECS Exec とは?
AWS ECS Exec とは、Amazon Elastic Container Service (ECS) 上で稼働しているコンテナに対して、セキュアにインタラクティブシェルを実行できる機能です。

これは、ECSでデプロイされているコンテナにSSHなしで直接アクセスし、デバッグやトラブルシューティングを行うことを可能にします。

通常、コンテナ内で直接コマンドを実行するのは難しいですが、ECS Exec を使うことで、以下のような操作が可能です。

  • リアルタイムでのデバッグ:アプリケーションのログやステータスをその場で確認したり、トラブルシューティングを行う。
  • コンテナ内でコマンド実行:ファイルの確認、設定変更などを行える。
  • SSHなしのアクセス:SSHを設定せずに、AWSの権限管理 (IAM) を通じて安全にアクセスできる。

使い方としては、AWS CLIやAWSコンソールを通じて、指定したタスクやコンテナにアクセスし、シェルを立ち上げることができます。

例えば、aws ecs execute-command コマンドを使用してシェルを開くことができます。

これにより、特定のサーバーやインスタンスにログインすることなく、ECSクラスタ上で動いているアプリケーションの問題解決が行うことができる便利なツールです。

ただ、ECS Execを利用するためには、こちらの記事より、ECSサービスでECS Execを有効化する必要があります。

以下のコマンドを実行して、ECS Execを有効化します。

//  ECS の Exec機能 を有効化にする
$ aws ecs update-service --region ap-northeast-1 --cluster examle-cluster-name --service service-name --enable-execute-command

上記コマンドの意味を解説します。

各オプションの意味

aws ecs update-service

AWS CLIコマンドで、ECSサービスの設定を更新するためのコマンドです。サービスのタスク数やその他の設定を変更する際に使います。

-region ap-northeast-1

AWSのリージョンを指定しています。ap-northeast-1は東京リージョンを意味します。

これにより、指定されたリージョン内で動作するECSサービスに対して操作を行います。

-cluster クラスター名

更新する対象のECSクラスター名を指定します。クラスターは、ECSのリソース(タスクやサービスなど)が稼働している環境です。

-service サービス名

更新するECSサービスの名前を指定します。サービスは、ECSでコンテナを定義し、それを自動的にスケーリングしたり、ロードバランシングを行う単位です。

-enable-execute-command

ECS Exec機能を有効化するオプションです。

このオプションを使うことで、そのサービスで動作するコンテナに対して、後からECS Exec機能を使用してコンテナに直接シェルアクセス(リモートコマンド実行)できるようにします。

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs-exec.html

https://docs.aws.amazon.com/cli/latest/reference/ecs/update-service.html

早速、aws ecs update-service ~ コマンドを実行しました。

しかし、上記の aws ecs update-service ~ コマンドを実行した時、下記のようなエラーが出ました。

$ aws ecs update-service --region ap-northeast-1 --cluster example-cluster --service example-service --enable-execute-command

An error occurred (AccessDeniedException) when calling the UpdateService operation: User: arn:aws:iam::xxxxxxxxxx:user/example_user is not authorized to perform: ecs:UpdateService on resource: arn:aws:ecs:ap-northeast-1:xxxxxxxxxx:service/example-cluster/example-service because no identity-based policy allows the ecs:UpdateService action

調べると、このエラーの原因は、指定されたユーザー(example_user)が、AWS ECSのサービスを更新するための権限を持っていないことです。

https://docs.aws.amazon.com/ja_jp/ram/latest/userguide/tshoot-access-denied.html

https://dev.classmethod.jp/articles/an-error-occurred-accessdeniedexception-iam/

つまり、ユーザーがecs:UpdateServiceという操作を実行しようとしたけれども、その操作を許可するIAMポリシーが設定されていないため、アクセスが拒否されたということを表しているらしいです。

なので、まずIAMユーザーに付与されているIAMポリシーの ecs:UpdateService に該当するポリシーがないか確認しました。

ただ、ecs:UpdateService というポリシー名のポリシーはなく、これはIAMポリシーのアクションのようです。


IAMポリシー の「アクション」とは?
AWS リソースへのアクセス権限を管理する IAMサービスにおいて、利用者(IAM ユーザーなど)が実行できる操作を定義するものです。

IAM ポリシーのアクションには、次のような特徴があります。

  • リソースレベルの許可をサポートしているかどうかは、アクションテーブルの「リソースタイプ」列で確認できます。
  • リソースタイプがオプションの場合は、オプションのリソースタイプのいずれかを使用できます。
  • 必須リソースは、アクションテーブルにアスタリスク (*) で示されています。
  • 複数のリソースタイプがサポートされているアクションもあります。
  • ポリシーステートメントの Condition 要素で指定できるキーは、アクションテーブルの「条件キー」列に記載されています。

IAM ポリシーは、AWS サービスが提供するアクション、リソース、条件キーを定義することもできます。

https://docs.aws.amazon.com/ja_jp/service-authorization/latest/reference/list_awsidentityandaccessmanagementiam.html

なので、今回は ecs:UpdateService をアクションに持つカスタムポリシーを作成し、対象のIAMユーザーにアタッチしました。

そのあと、aws ecs update-service ~ コマンドを再び実行すると下記のような結果になり、先ほどのエラーは表示されずに aws ecs update-service ~ コマンドを実行することができました。

$ aws ecs update-service --region ap-northeast-1 --cluster example-cluster --service example-service --enable-execute-command

{
    "service": {
        "serviceArn": "arn:aws:ecs:ap-northeast-1:yyyyyyyyyy:service/example-cluster/example-service",
        "serviceName": "example-service",
        "clusterArn": "arn:aws:ecs:ap-northeast-1:yyyyyyyyyy:cluster/example-cluster",
        "loadBalancers": [
            {
                "targetGroupArn": "arn:a...

・
・
・

確認のため、enableExecuteCommand が true になっているか確認します。

// サービスの詳細を確認
$ aws ecs describe-services --cluster example-cluster --service example-service | grep enableExecuteCommand

"enableExecuteCommand": true

上記の結果とこちらの記事より、enableExecuteCommand が true になったことが確認できたので、ECS Exec が有効になったということになります。

aws ecs describe-services ~ コマンドと enableExecuteCommand の意味
https://docs.aws.amazon.com/cli/latest/reference/ecs/describe-services.html


サービスの再起動

次は、こちらの記事より、先ほどECS Execを有効化に変更した設定内容を新しいタスクに反映させるため、ECSのサービスの再起動を行いました。

対応はこちらの記事を参考に行いました。

ざっくり説明すると、実行手順は下記の通りです。

タスクの更新を使用して再起動

  1. ECS コンソールに移動します。
  2. 再起動したいサービスがあるクラスタを選択します。
  3. Services」タブをクリックし、対象のサービスを選択します。
  4. Update」をクリックします。
  5. 特に設定を変更せず「Force New Deployment」オプションにチェックを入れます。
  6. Update Service」をクリックしてデプロイを強制し、タスクが再起動されます。


コンテナにアクセスする

最後に、サービス再起動後のタスク名を確認し、コンテナにアクセス使用としました。

実行コマンドは下記の通りです。

// タスク名の確認
$ aws ecs list-tasks --cluster example-cluster --service-name example-service-db

{
    "taskArns": [
        "arn:aws:ecs:ap-northeast-1:yyyyyyyy:task/example-cluster/xxxxxxx"
    ]
}

// クラスター内のタスクに対してECS Exec機能が有効かどうかの確認
$ aws ecs describe-tasks --cluster example-cluster --tasks example-task-id | grep enableExecuteCommand

"enableExecuteCommand": true

// コンテナにアクセス
$ aws ecs execute-command --cluster example-cluster --task example-task-id --container example-container --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.

An error occurred (TargetNotConnectedException) ~ というエラー原因を考える前に、まず aws ecs describe-tasks ~ コマンドについて解説します。

説明は下記の通りです。

aws ecs describe-tasks

AWS CLIコマンドで、Amazon ECSのタスクに関する詳細情報を取得します。describe-tasksは指定されたタスクのステータスや設定、実行状況に関する情報を返します。

-cluster example-cluster

対象となるECSクラスターを指定します。example-clusterはクラスターの名前で、このクラスター内のタスクを対象に情報を取得します。

-tasks example-task-id

情報を取得するタスクのIDを指定します。example-task-idはタスクの識別子です。このオプションにより、どのタスクに関する情報を取得するかが指定されます。

| grep enableExecuteCommand

パイプ(|)は、前のコマンドの出力を次のコマンドの入力として渡す役割を果たします。grepは、特定の文字列を含む行を出力するコマンドです。

enableExecuteCommandという文字列を含む行だけを表示します。ECSタスクに対して「ECS Exec」機能が有効かどうかを確認するために使います。

つまり、aws ecs describe-tasks ~ コマンドは、指定されたクラスター内の特定のタスクに対して、ECS Exec機能(コンテナ内でコマンドを実行できる機能)が有効になっているかを確認するために使用することができます。

https://docs.aws.amazon.com/cli/latest/reference/ecs/describe-tasks.html

次に An error occurred (TargetNotConnectedException) ~ というエラー原因ですが、こちらの記事を参考に、Amazon ECS Exec Checker というサービスを用いて、設定内容を確認しました。


Amazon ECS Exec Checker とは?
Amazon ECS クラスターとタスクが ECS Exec 機能を使用するための前提条件を満たしているかどうかを確認できるツール。

https://github.com/aws-containers/amazon-ecs-exec-checker

Amazon ECS Exec Checker を用いたECSの設定内容を確認する手順は下記の通りです。

  1. Amazon ECS Exec Checker のリポジトリを git clone する
  2. jq --version コマンドを実行し、jq がインストールされていなければ、brew install jq コマンドを実行
  3. ./check-ecs-exec.sh [クラスター名] [タスクID] コマンドを実行する

実行結果は下記の通りです。

$ ./check-ecs-exec.sh example-cluster example-task-id
-------------------------------------------------------------
Prerequisites for check-ecs-exec.sh v0.7
-------------------------------------------------------------
  jq      | OK (/usr/local/bin/jq)
  AWS CLI | OK (/usr/local/bin/aws)

-------------------------------------------------------------
Prerequisites for the AWS CLI to use ECS Exec

・
・
・

An error occurred (AccessDenied) when calling the SimulatePrincipalPolicy operation: User: arn:aws:iam::xxxxxxxxx:user/example_user is not authorized to perform: iam:SimulatePrincipalPolicy on resource: arn:aws:iam::xxxxxxxxx:user/example_user because no identity-based policy allows the iam:SimulatePrincipalPolicy action

上記の実行結果より、An error occurred (AccessDenied) ~ エラーが発生しました。

エラー内容を確認すると、IAMポリシーに関連するアクセス権の問題を示しており、具体的には、SimulatePrincipalPolicy アクションを実行するための権限が不足していることが原因らしいです。

なので、IAMからSimulatePrincipalPolicy というアクションを持つカスタムポリシーを作成し、IAMユーザーにアタッチしました。

その後、サービスを再起動し、ECSコンテナにアクセスするための aws ecs execute-command --cluster ~ コマンドを再度実行しました。

実行結果は下記の通りです。

// ECS コンテナへアクセス
$ aws ecs execute-command --cluster example-cluster --task example-task-id --container example-container --interactive --command "/bin/bash"

The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.

Starting session with SessionId: example-session-id

ip-container-IP:/#

どうやらコンテナに接続できたようです。


まとめ

今回 ECS Execを利してコンテナに接続する手順と、接続時に遭遇した問題のトラブルシューティングについて説明しました。

適切なIAMポリシーの設定やネットワーク設定の確認が成功の鍵です。

これらの手順を参考に、ECSコンテナへのスムーズなアクセスを実現してみてください。


参考

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs-exec.html

https://zenn.dev/nenenemo/articles/9f66924801114c

https://blog.serverworks.co.jp/ecs-exec

Discussion