ECS

ECS ExecでFargateのコンテナの中に入ってデバッグする (execute-command) Terraform版

TerraformでECS Exec を有効にしてコンテナで直接コマンドを実行してみます。(AWS CLIを使用してECS Execを有効化する方法はこちらの記事をご参照ください)

Fargateの場合、この機能が出るまで、実行中のコンテナ内で新しいコマンドを実行することができませんでした。


通常のdockerコマンドの

$ docker exec -it cotainer bash

のようにコンテナの中に入れなかったので、タスク定義で一緒に起動しているコンテナ間のマウントや、ログ転送のfirelensなどの設定がうまくいかなかったとき、正確に状況が掴めずじれったい思いをしました。


が今後は、この機能のおかけでデバッグも捗りそうです。

また開発段階にPHPやRubyなどで、ちょっと一行デバッグ用にコードを仕込むなどもできてかなり便利です。ちょっとした確認に、わざわざビルド&デプロイは手間ですよね。。

スポンサーリンク

ECS Execの有効化手順

Terraform AWSプロバイダのバージョンアップ

こちらのissueの通りAWSプロバイダのv3.34.0からECS Execに対応しているので、それ以降のVersionへアップデートします。

### バージョン確認。terraform.io/hashicorp/aws が v3.34以上であればOKです
$ terraform version
Terraform v0.13.5
+ provider registry.terraform.io/hashicorp/aws v3.33.0

...
$
$ cat provider.tf
terraform {
  required_version = "0.13.5"
  backend "local" {}

  required_providers {
    aws = {
      source = "hashicorp/aws"
   
   ### 3.34以上にします。
      version = ">= 3.34"
    }
  }
}

...


tfファイルでバージョンを設定した後、init で忘れずにプラグインをダウンロードします。

$ terraform init

Initializing the backend...

Initializing provider plugins...
- Finding hashicorp/aws versions matching ">= 3.34.*"...
- Installing hashicorp/aws v3.39.0...
- Installed hashicorp/aws v3.39.0 (self-signed, key ID xxxxx)

...

TerraformでECS Execを有効にする

Terraformで設定する際のポイントは3つになります。

ECSサービスでの設定

まず以下2つのポイントを aws_ecs_service にて設定します。

  • aws_ecs_service の platform_versionを1.4.0以上。
  • aws_ecs_service の enable_execute_command をtrue。
resource "aws_ecs_service" "test" {
  name                       = "test-service"
  launch_type                = "FARGATE"
...

  platform_version           = "1.4.0"
  enable_execute_command     = true
...

}


ECSタスクロールの作成&アタッチ

3つ目は、

  • ECSタスクロールにSSM サービス関連のアクセス許可を付与

です。

ECS Execの機能が、SSM Session Manager を利用してセキュアに接続しているため、この許可が必要になります。

以下例のように、ECSタスクロールを作成して公式ドキュメントに記載されているSSMサービス関連のポリシーをアタッチします。

### ECSタスクロール作成
resource "aws_iam_role" "ecs-task" {
  assume_role_policy = <<POLICY
{
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Effect": "Allow",
      "Principal": {
        "Service": "ecs-tasks.amazonaws.com"
      },
      "Sid": ""
    }
  ],
  "Version": "2012-10-17"
}
POLICY

  max_session_duration = "3600"
  name                 = "ecsTaskRole"
  path                 = "/"
}

### SSM サービス関連のアクセス許可ポリシー作成
resource "aws_iam_policy" "ecs-exec" {
  name        = "EcsExec"
  policy = <<POLICY
{
    "Version": "2012-10-17",
    "Statement": [
        {
        "Effect": "Allow",
        "Action": [
             "ssmmessages:CreateControlChannel",
             "ssmmessages:CreateDataChannel",
             "ssmmessages:OpenControlChannel",
             "ssmmessages:OpenDataChannel"
        ],
       "Resource": "*"
       }
    ]
 }
POLICY
}

### ポリシーをロールにアタッチ
resource "aws_iam_role_policy_attachment" "ecs-exec" {
  policy_arn = aws_iam_policy.ecs-exec.arn
  role       = aws_iam_role.ecs-task.name
}


次に上記ロールをタスク定義のタスクロールに設定します。

resource "aws_ecs_task_definition" "test" {
  network_mode             = "awsvpc"

  ### こちらの タスクロール に設定します。
  task_role_arn            = aws_iam_role.ecs-task.arn

  ### こちらの タスク実行ロール ではないです。
  execution_role_arn       = aws_iam_role.ecs-task-execution.arn
...


準備ができたらapplyで適用しましょう。

execute-commandの基本構文と実行例

適用したら実際に試してみます。

クライアント側のAWS CLIも、execute-commandに対応していないとだめです。v2であればバージョンが2.1.31以上であればOKなようです。

$ aws --version
aws-cli/2.1.38 Python/3.8.8 Darwin/19.6.0 exe/x86_64 prompt/off
$

またAWS CLI Session Managerプラグインが必要になります。

基本構文

$ aws ecs execute-command --cluster クラスター名 \
--task タスクID \
--container コンテナ名 \
--interactive --command OSコマンド
$ 
$ 
### 例
$ aws ecs execute-command --cluster test-ecs-cluster \
--task 7ce698xxxxxxxxxxxxx \
--container test-container \
--interactive --command ls

AWSコンソール ECSサービス画面の、左ペイン [ クラスター ] → 対象クラスターをクリック → [ タスク ] タブ → タスクIDをクリック でそれぞれの情報を確認できます。


コンテナの中に入れます

コマンドを単発で実行するだけでなく、bashなどでコンテナに直接入れます。

以下のように必要パッケージをインストールしてからのファイル書き換えなども可能です。

$ aws ecs execute-command --cluster test-ecs-cluster \
--task 7ce698xxxxxxxxxxxxx \
--container test-container \
--interactive --command bash

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


Starting session with SessionId: ecs-execute-command-xxx
root@7cexx:/usr/local/apache2#
root@7cexx:/usr/local/apache2# ls
bin  build  cgi-bin  conf  error  htdocs  icons  include  logs	modules
root@7cexx:/usr/local/apache2# cd htdocs/
root@7cexx:/usr/local/apache2/htdocs# ls
index.html
root@7cexx:/usr/local/apache2/htdocs# cat index.html
<html><body><h1>It works!</h1></body></html>
root@7cexx:/usr/local/apache2/htdocs#
root@7cexx:/usr/local/apache2/htdocs# apt-get update
...

root@7cexx:/usr/local/apache2/htdocs# apt-get install vim
...

root@7cexx:/usr/local/apache2/htdocs# vi index.html
root@7cexx:/usr/local/apache2/htdocs# cat index.html
<html><body><h1>It works! Zoo! </h1></body></html>
root@7cexx:/usr/local/apache2/htdocs#
root@7cexx:/usr/local/apache2/htdocs# exit
exit


Exiting session with sessionId: ecs-execute-command-xxx.

$


複数コマンドの連続実行もできます

(bashであれば)bash -cを利用することで複数コマンドの実行も可能です。

 $ aws ecs execute-command --cluster test-ecs-cluster \
--task 7ce698xxxxxxxxxxxxx \
--container test-container \
--interactive --command "bash -c 'echo hoge && echo fugafuga'"


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


Starting session with SessionId: ecs-execute-command-xxx
hoge
fugafuga


Exiting session with sessionId: ecs-execute-command-xxx.

$

注意点

最初に試すときミスしてたのでメモっておきます。

AWSプロバイダーのバージョンが低い

enable_execute_commandを認識しません。

$ terraform version
Terraform v0.13.5
+ provider registry.terraform.io/hashicorp/aws v3.33.0
...

$
$ terraform apply

Error: Unsupported argument

  on ecs.tf line 50, in resource "aws_ecs_service" "test":
  50:   enable_execute_command             = true

An argument named "enable_execute_command" is not expected here.

$

SSM関連のポリシー付与忘れ

以下のようなエラーになります。

$ aws ecs execute-command --cluster test-ecs-cluster \
--task 7ce698xxxxxxxxxxxxx \
--container test-container \
--interactive --command ls


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.
$

SSM関連のポリシー付与は既存タスクには反映されない

既存のECSタスクロールに追加でポリシー付与した場合、起動中のタスクには反映されません。SSM関連のポリシー付与忘れと同じエラーが出ます。

サービスの更新などで新しいタスクを立ち上げましょう。


今回は以上です〜ノシ

参考

アリガト━━━ヾ(´∀`)ノ━━━━♪

デバッグに Amazon ECS Exec を使用する
[アップデート] 実行中のコンテナに乗り込んでコマンドを実行できる「ECS Exec」が公開されました
Amazon ECS Exec による AWS Fargate, Amazon EC2 上のコンテナへのアクセス