AWS CLIでaws ecs execute-commandを使えるようにする
AWS ECS Exec
は現時点では AWS CLI
を使って設定や利用を行う。サービスの設定時にも必要だが、セッションの開始にも必要になる。
AWS CLIをインストールする
v1系は1.19.28以降、v2系は2.1.31以降が必要となる。
brew install awscli
バージョンを確認する。
aws --version
aws-cli/2.13.28 Python/3.11.6 Darwin/22.6.0 source/x86_64 prompt/off
Session Manager pluginをインストールする
Session Manager pluginも必要になるのでインストールする。
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html
IAMの設定
AWS ECS Execの実行にSessionManagerの権限が必要になる。
ポリシー
SessionManagerの必要な権限を付与したIAMポリシーを作成する。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ssmmessages:CreateControlChannel", "ssmmessages:CreateDataChannel", "ssmmessages:OpenControlChannel", "ssmmessages:OpenDataChannel" ], "Resource": "*" } ] }
ロール
ECSのタスクロールに先程作成したポリシーをアタッチする。ECSを実行したことがある場合ecsTaskExecutionRoleというロールが既に存在する。今回はそのロールにアタッチした。
ECSの設定
タスク定義
前述で作成したロールをタスクロールとして設定する。
クラスタ
サービス
サービスに対してAWS ECS Execの機能を有効化する必要がある。ただしAWS Console上からそれを設定することはできない。そのためAWS CLIで --enable-execute-command
オプションを使って設定の変更を行う。
aws ecs update-service --cluster sample --service sample1 --enable-execute-command
再起動
設定がもろもろ済んだらタスクの再起動を行う。サービスの更新メニューから 強制的にデプロイする
のチェックをいれて更新すれば良い。
実行中のタスクのAWS ECS Exec機能が有効になっているかを確認する。
aws ecs describe-tasks
コマンドで機能が有効になっているかを確認できる。実行中のタスク情報の enableExecuteCommand
が true
になっていれば有効になっている。
aws ecs describe-tasks --cluster sample --tasks 12334567890abcdef1234567890abcde
false
になっている場合はなんらかの設定が足りていない。サービスの設定などをAWS CLIを用いて確認してみると良い。
接続方法
aws ecs execute-command
でセッションを開始できる。
aws ecs execute-command --cluster sample --task 2d4a10c81ddf473d851e5daf3566f1c4 --container test --interactive --command "/bin/bash"
主に指定するオプション引数を以下に示す。
オプション | 引数の有無 | 引数の例 | 説明 |
---|---|---|---|
–cluster | あり | sample | ECSクラスター名を指定する。 |
–task | あり | 2d4a10c81ddf473d851e5daf3566f1c4 | セッションを開始するタスク名を指定する。 |
–container | あり | test | セッションを開始するタスク内のコンテナを指定する。 |
–interactive | なし | インタラクティブな操作がひつような場合に指定する。 | |
–command | あり | "/bin/bash" | 実行するコマンドを指定する。 |
SessionManagerを使ってセッションを開始する方法との違い
AWS ECS Execは内部でSessionManagerを使っているらしい。本質的に違いがあるわけではなさそうだが、利用者からみての際をまとめた。
項目 | ECS Exec | SessnManager |
---|---|---|
AWS CLI | 必要。 | 必要ではない。 |
AWS Consoleからのサービス設定 | できない。 | できる。 |
AWS Consoleからのセッションの開始 | できない。 | できる。 |
SSM Agent | ? | Dockerイメージの中に梱包し、コンテナ起動時に起動させておく。 |
Session Manager plugin | 必要。 | 必要ではない。 |
アクティベーションID | 必要なし。 | 事前に生成し、環境変数などで渡す。SSMAgentの起動時に指定する。 |
アクティベーションコード | 必要なし。 | 事前に生成し、環境変数などで渡す。SSMAgentの起動時に指定する。 |
インスタンスティアの切り替え | 必要なし。 | スタンダードからアドバンスドに切り替える必要がある。 |
起動時に必要な情報 | クラスタ名、タスクID、コンテナ名 | インスタンスID |
環境
以下の環境を前提とする。
macOS
sw_vers
ProductName: macOS ProductVersion: 11.2.3 BuildVersion: 20D91
Homebrew
brew -v
Homebrew 3.0.10 Homebrew/homebrew-core (git revision 7b6bcedba2; last commit 2021-04-01) Homebrew/homebrew-cask (git revision b3cd76ab00; last commit 2021-04-01)
実行までの流れ
コンテナに入るまでにはいくつかの情報を取得する必要がある。全てAWS Console上で確認できる。ここではAWS CLIを使用し、それらを探しだす方法を示す。必要な情報は、クラスタ名、タスク名、コンテナ名だ。これらを取得するためには、それぞれにコマンドを実行する必要がある。またその場合、それらのコマンドを実行できる権限を持っていることが前提となる。
必要な情報 | 取得するコマンド |
---|---|
クラスタ名 | aws ecs list-clusters |
タスク名 | aws ecs list-tasks |
コンテナ名 | aws ecs describe-tasks |
まずはクラスタ名を取得する。ここではクラスタの一覧を取得し、目的のクラスタを探す。
クラスタを見つけたら、クラスタ内で実行中のタスクの一覧を取得する。どのタスクを対象にするかは、必要に応じて決める。
タスクを見つけたら、そのタスク内で実行中のコンテナを探す。タスクの情報を取得することで、コンテナの情報も探すことができる。
クラスタ名、コンテナ名はあらかじめ決っているため、探す必要がないかもしれない。一方タスク名は動的に決められるため、都度確認する必要がある。
必要な情報がそろったら aws ecs execute-command
でコンテナに入ることができる。
aws ecs execute-command --cluster sample --task 12334567890abcdef1234567890abcde --container mycontaineer --interactive --command "/bin/bash"
ECS上で作業をするためのツール
ecsでの作業を補助するラッパーツールもいくつかある。
ecskはどうやってファイルのコピーを実現しているのか?
ecskにはコンテナとローカルの間でのファイル転送を実現している。 aws ecs execute-command
には、そのような機能はないため、どうやって実現しているのか気になった。
この点についてはREADME.mdにも記載されているのだが、S3に一時的にアップロードし、そこからダウンロードするという形で実現していた。コードの一部を抜粋する。
ecsk/pkg/store/s3.go
には、ここで呼び出しているDownloadやら、Uploadやらの関数が実装されている。内部では github.com/aws/aws-sdk-go-v2/service/s3
を用いて、S3とデータのやりとりをしていた。
aws ecs execute-commandのセッションを維持させる
aws ecs execute-command
を用いてECS上のコンテナに接続し、暫く放置すると接続が切断されてしまう。それを防ぐ為のEmacs Lispを書いた。
;;; keep-alive-session --- Keep Alive for AWS ECS Exec. -*- lexical-binding: t -*-
;; Copyright (C) 2024 TakesxiSximada
;; Author: TakesxiSximada <[email protected]>
;; Maintainer: TakesxiSximada <[email protected]>
;; Version: 3
;; Package-Version: 20240319.0000
;; Package-Requires: ((emacs "29.1"))
;; Date: 2024-03-19
;; This file is not part of GNU Emacs.
;;; License:
;; This program is free software: you can redistribute it and/or
;; modify it under the terms of the GNU Affero General Public License as
;; published by the Free Software Foundation, either version 3 of the
;; License, or (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; Affero General Public License for more details.
;; You should have received a copy of the GNU Affero General Public
;; License along with this program. If not, see
;; <https://www.gnu.org/licenses/>.
;;; Code:
(defgroup keep-alive-session nil
"String to send to maintain session"
:group 'lisp
:group 'extensions)
;;;###autoload
(defcustom keep-alive-session-event " "
"String to send to maintain session"
:group 'keep-alive-session
:type 'string)
(defvar keep-alive-session-process nil)
(defvar keep-alive-session-timer nil)
(defun keep-alive-session-send-event ()
(process-send-string keep-alive-session-process
keep-alive-session-event))
;;;###autoload
(defun keep-alive-session ()
(interactive)
(setq keep-alive-session-process
(get-buffer-process (current-buffer)))
(setq keep-alive-session-timer
(run-at-time 1 t #'keep-alive-session-send-event))
(set-process-sentinel keep-alive-session-process
#'keep-alive-session-stop))
;;;###autoload
(defun keep-alive-session-stop (&optional process event)
(interactive)
(cancel-timer keep-alive-session-timer))
(provide 'keep-alive-session)
;; keep-alive-session.el ends here