ECS Fargateのコンテナ内にECS Execでアクセスする方法 (ローカルpcから)


# はじめに
ECS Execの機能を使って、Fargateのコンテナにアクセスする方法を記載します。

ECS Execによるコンテナへのアクセスは、以下の4つを行うことで実行できます。

- クライアントサーバーには、ECS Exec コマンドを実行するための AWS CLI がインストールされていること

- クライアントサーバーには、AWS CLI 用の `Session Manager plugin` がインストール

- `enable-execute-command`を使い、Fargateのタスク定義の`enableExecuteCommand `を有効にすることで、ECS Exec の機能が有効になります。

- コンテナがSystems Managerと連携するため、FargateのタスクロールにIAM権限を付与します。
下記に記事に、詳細な理由が記載されています。

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/userguide/ecs-exec.html
>ECS Exec 機能には、マネージド型 SSM エージェント (execute-command エージェント) と SSM サービス間の通信に必要なアクセス許可をコンテナに付与するためのタスク IAM ロールが必要です。

# 構築図
今回は、ローカルPCから、Systems Manager の Session Manager 経由で、`execute-command`を用いて、コンテナにアクセスします。
ローカルPCには、Systems Manager の Session Managerを使用するため、`Session Manager plugin` のインストールが必要です。


![スクリーンショット 2022-03-30 0.04.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/8bc4467d-132c-f125-fc9c-886539f3bdf3.png)

:::note warn
ローカルPCではなく、踏み台サーバーを使いコンテナにアクセスする場合、こちらの記事を参考にしてください

https://qiita.com/drafts/0725a476f587e1d64253/
:::


# 流れ
1. IAMポリシーとロール作成
1. ローカルPCにSession Manager pluginをインストール
1. ECSのタスクロールにIAM権限を付与
1. ECSのサービスにECS Execの機能を有効にする
1. Fargateのコンテナにアクセス


# 前提条件
- ECS作成済み
WordPressFargateの作成方法はこちら
[Fargate＋WordPress構築](https://qiita.com/holdout0521/items/bde67b8334f3362c8009)

- Fargate プラットフォームバージョン 1.4.0

- コマンドは全て、踏み台サーバーで実行します。


# IAMポリシーとロール,ユーザーを作成
以下のようにロールを作成します。

|IAMロール名	  |ポリシー	| 付与先サービス| 目的|
| ---- | ---- | ---- | ---- |
| ECS-Exec-Fargate-role | ECS-Exec-Fargate |ECS | コンテナにアクセスするためには execute-command を用いて、SSM サービス間の通信が必要なため |  

|IAMユーザー名	  |ポリシー	|  目的|
| ---- | ---- | ---- |
| ECS-Exec-User |ECS-Exec-from-pc  |  ECS execを利用しECSにアクセスするため | 

 

`ECS-Exec-Fargate`という名前のIAMポリシーを作成します。

```json:ECS-Exec-Fargate
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VisualEditor0",
      "Effect": "Allow",
      "Action": [
        "ssmmessages:CreateDataChannel",
        "ssmmessages:OpenDataChannel",
        "ssmmessages:OpenControlChannel",
        "ssmmessages:CreateControlChannel"
      ],
      "Resource": "*"
    }
  ]
}
```

また、`ECS-Exec-from-pc`という名前のIAMポリシーを作成します。
```json:ECS-Exec-Fargate
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VisualEditor0",
      "Effect": "Allow",
      "Action": [
        "ecs:UpdateService",
        "ecs:ExecuteCommand",
        "ecs:DescribeTasks",
        "ecs:DescribeServices",
        "ecs:UpdateServicePrimaryTaskSet"
      ],
      "Resource": "*"
    }
  ]
}
```



`ECS-Exec-Fargate-role`のロールを作成します。
- `ユースケースの選択`：`ECS`の`Elastic Container Service Task`
先程作成した`ECS-Exec-Fargate`ポリシーをアタッチします。


![スクリーンショット 2021-10-23 23.41.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/ca06d2e6-fff9-a4fc-d07b-02b63e223784.png)

![スクリーンショット 2021-10-24 11.55.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/5b345af0-37ae-5ac8-f77f-d1e70327891b.png)


次に、アクセスキーとシークレットキーを発行したIAMユーザー`ECS-Exec-User`を作成し、`ECS-Exec-from-pc`ポリシーを付与します。

ローカルに、`ecs-fargate-exec`という名前付きプロファイルを作成し、設定します。

ちなみに、pcはMacを使っています。

```terminal
$ aws configure --profile ecs-fargate-exec
AWS Access Key ID [None]: xxxxx
AWS Secret Access Key [None]: xxxxx
Default region name [None]: ap-northeast-1
Default output format [None]: 

// credentials配下に保存されたか確認
$ cat ~/.aws/credentials 

[ecs-fargate-exec]
aws_access_key_id = AKIxxx
aws_secret_access_key = xxxxxxx

// 下記のコマンドに設定することで、すべてのコマンドでプロファイルを指定せずにすみます。
$ export AWS_PROFILE=ecs-fargate-exec
```

# ローカルに` Session Manager plugin `をインストール

ECS Exec コマンドを実行するための AWS CLI がインストールされていること必須なため、CLIが以下の条件に当てはまるか確認します。

```
AWS CLI v1 バージョン 1.19.28以上
             or
AWS CLI v2 バージョン 2.1.31以上
```
ローカルPCに、以下のコマンドで確認します。

```terminal
$ aws --version
aws-cli/1.18.147 Python/2.7.18 Linux/4.14.246-187.474.amzn2.x86_64 botocore/1.18.6
```
バージョンが当てはまらないので、CLIの最新版をインストールしましょう。



```terminal
$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"

$ unzip awscliv2.zip

$ sudo ./aws/install

$ aws --version
aws-cli/2.3.0 Python/3.8.8 Linux/4.14.248-189.473.amzn2.x86_64 exe/x86_64.amzn.2 prompt/off
```
バージョンが最新になりました。

Session Manager プラグインをインストールしましょう！

```terminal
$ cd /tmp
$ curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/mac/sessionmanager-bundle.zip" -o "sessionmanager-bundle.zip"
$ unzip sessionmanager-bundle.zip
$ sudo ./sessionmanager-bundle/install -i /usr/local/sessionmanagerplugin -b /usr/local/bin/session-manager-plugin


$ session-manager-plugin

The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.
```
インストールできました。

## windosの場合
下記の記事通りに行ってください

https://dev.classmethod.jp/articles/ec2-login-with-session-manager/

# ECSのタスクロールにIAM権限を付与
コンテナがSystems Managerと連携するため、FargateのタスクロールにIAM権限を付与します。

タスク定義のタスクロールに`ECS-Exec-Fargate-role`を選択し、サービスを更新します。
![スクリーンショット 2021-10-24 11.56.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/5a37024b-7157-5d84-16f8-8ccfa8bb9a3e.png)


サービスを最新バージョンに更新して、タスクを立ち上げましょう。

## タスクロールとタスク実行ロールの違いについて
`タスク実行ロール`は、ECSコンテナエージェントがECRからのコンテナイメージプルや、コンテナログをCloudWatchに送信するためIAMポリシーが必要となります。

対して、`タスクロール`は、コンテナが他のAWSサービスと連携する際にのみ、必要なIAMポリシーを設定します。

今回であれば、コンテナが`Systems Manager`と連携するため、`タスクロール`に権限を付与したということになります。
![スクリーンショット 2021-10-24 12.14.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/d63f7b23-8cd7-97fa-0deb-a466aa557684.png)

# ECSのサービスにECS Execの機能を有効にする

`enable-execute-command`を用いて、`enableExecuteCommand`を有効にすることで、ECS Exec の機能を有効にすることができます。
タスクが立ち上がっていることを確認し、以下のコマンドを実施しましょう。

成功すると、長文の結果が返ってきますので、エンターを押し続けてください。

```terminal
$ aws ecs update-service \
    --cluster クラスター名 \
    --service サービス名 \
    --enable-execute-command

#省略(結果は長いです。エンターを押し続けましょう)
     "enableExecuteCommand": true
  }
}
```


もしくは以下のコマンドでも、Exec の機能が有効どうか確認できます。
`true`と返ってきたら、有効ということです。

```terminal
$ aws ecs describe-services --cluster クラスター名 --services サービス名 | jp.py 'services[].enableExecuteCommand'

[
    true
]
```

## エラー集
以下のようなエラーが出た場合、サービスの実行ロールに`ECS-Exec-Fargate-role`を付与し、そのサービスを更新していない可能性があります。
または、FargateもしくはローカルPCのIAMポリシーが不適切な可能性があります。

```terminal
$ aws ecs update-service \
    --cluster クラスター名 \
    --service サービス名\
    --enable-execute-command

An error occurred (InvalidParameterException) when calling the UpdateService operation: The service couldn't be updated because a valid taskRoleArn is not being used. Specify a valid task role in your task definition and try again.
```


# Fargateのコンテナにアクセス
まず、起動しているタスクを全て停止し、再度タスクを起動します。
そして、`execute-command`を使い、コンテナにアクセスします。
`タスクID`は、稼働中（Running）のものに限ります。

```terminal
$ aws ecs execute-command \
    --cluster クラスター名 \
    --task タスクID \
    --container コンテナ名 \
    --interactive \
    --command "/bin/sh"



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

Starting session with SessionId: 
```

コンテナにアクセスできました！！

## エラー集

ECS Execの機能を有効にしていない場合に、`execute-command`を使用すると以下のエラーが起きます。
有効にし、サービスを更新し、タスクを再起動しましょう。

```terminal
$ aws ecs execute-command \
    --cluster クラスター名 \
    --task タスクID \
    --container コンテナ名 \
    --interactive \
    --command "/bin/sh"

An error occurred (InvalidParameterException) when calling the ExecuteCommand operation: The execute command failed because execute command was not enabled when the task was run or the execute command agent isn’t running. Wait and try again or run a new task with execute command enabled and try again.
```

# 参考

https://qiita.com/okubot55/items/b1fb07b2de08c354275b

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html

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

https://dev.classmethod.jp/articles/ecs-exec-enableexecutecommand-error/