🕌
【ecsh】ECS execでのコンテナログインを楽にするツールを作りました
ecsh
ECS Execを使用したコンテナへのログインを対話形式で実行するツールです。
すべて対話形式で進むのでコマンドを実行するだけで使えます。
install
バイナリファイルを取得してパスの通っているディレクトリに配置すれば使えます。
Mac
$ ECSH_VERSION=0.0.3
$ curl -OL https://github.com/kishii4726/ecsh/releases/download/v${ECSH_VERSION}/ecsh_v${ECSH_VERSION}_darwin_amd64.zip
$ unzip ecsh_v${ECSH_VERSION}_darwin_amd64.zip ecsh
$ sudo cp ecsh /usr/local/bin
Linux
$ ECSH_VERSION=0.0.3
$ curl -OL https://github.com/kishii4726/ecsh/releases/download/v${ECSH_VERSION}/ecsh_v${ECSH_VERSION}_linux_amd64.zip
$ unzip ecsh_v${ECSH_VERSION}_linux_amd64.zip ecsh
$ sudo cp ecsh /usr/local/bin
作った理由
CLIでECS Execでコンテナにログインする際は以下のようにコマンドを実行しますが、実行するためにクラスター名
、タスクid
、コンテナ名
、コマンド
を指定する必要があります。
execute-commandの例
aws ecs execute-command --cluster cluster-name \
--task task-id \
--container container-name \
--interactive \
--command "/bin/sh"
都度必要なパラメータを揃えて上記のコマンドを実行するのは中々辛いので以下のようなシェルスクリプトを作って使っていましたが、雑に作っていていつか直したいなと思っていたので、勉強も兼ねてGoで作り直しました。
ECS Execを実行するために使っていたシェルスクリプト
#!/bin/bash
AWS_PROFILE=$1
AWS_VAULT_COMMAND="aws-vault exec ${AWS_PROFILE} --"
function usage() {
echo "[ERROR]: Please put the AWS profile name in the first argument."
exit 1
}
if [ -z $AWS_PROFILE ]; then
usage
exit 1
fi
select ECS_CLUSTER in $(${AWS_VAULT_COMMAND} aws ecs list-clusters --query 'clusterArns[*]' | cut -f 2 -d "/" | sed -e 's/\[//g' -e 's/\]//g' -e 's/,//g' -e 's/"//g' -e '/^$/d')
do
echo -e "Selected ECS Cluster: ${ECS_CLUSTER}"
break
done
select ECS_SERVICE in $(${AWS_VAULT_COMMAND} aws ecs list-services --cluster "${ECS_CLUSTER}" --query 'serviceArns[*]' | cut -f 3 -d "/" | sed -e 's/\[//g' -e 's/\]//g' -e 's/,//g' -e 's/"//g' -e '/^$/d')
do
echo -e "Selected ECS Service: ${ECS_SERVICE}"
break
done
select ECS_TASK_ID in $(${AWS_VAULT_COMMAND} aws ecs list-tasks --cluster "${ECS_CLUSTER}" --service-name "${ECS_SERVICE}" --query 'taskArns[*]' | cut -f 3 -d "/" | sed -e 's/\[//g' -e 's/\]//g' -e 's/,//g' -e 's/"//g' -e '/^$/d')
do
echo -e "Selected Task: ${ECS_TASK_ID}"
break
done
select ECS_CONTAINER_NAME in $(${AWS_VAULT_COMMAND} aws ecs describe-tasks --cluster "${ECS_CLUSTER}" --tasks "${ECS_TASK_ID}" --query 'tasks[*][containers][][].name' | sed -e 's/\[//g' -e 's/\]//g' -e 's/,//g' -e 's/"//g' -e '/^$/d')
do
echo -e "Selected Container: ${ECS_CONTAINER_NAME}"
break
done
select ECS_EXEC_SHELL in 'sh' 'bash'
do
echo -e "Selected Shell: ${ECS_EXEC_SHELL}"
break
done
echo -e 'Execute ECS exec'
${AWS_VAULT_COMMAND} aws ecs execute-command \
--cluster "${ECS_CLUSTER}" \
--task "${ECS_TASK_ID}" \
--container "${ECS_CONTAINER_NAME}" \
--interactive \
--command "${ECS_EXEC_SHELL}"
実装について
文字入力・キーによる選択
入力・選択部分にはpromptuiを使用しました。promptuiに関しては以下の記事を参考にさせていただきました🙏
ExecuteCommandとStartSession
CLIのようにExecuteCommand
で接続出来るのかと思ったのですが、実際にはExecuteCommand
の返り値を使ってsession-manager-plugin
でStartSession
を実行する必要があり、少しハマりました。
out, err := client.ExecuteCommand(context.TODO(), &ecs.ExecuteCommandInput{
Command: aws.String(ecs_shell),
Interactive: true,
Task: aws.String(ecs_task_id),
Cluster: aws.String(ecs_cluster),
Container: aws.String(ecs_container),
})
sess, _ := json.Marshal(out.Session)
target := fmt.Sprintf("ecs:%s_%s_%s", ecs_cluster, ecs_task_id, ecs_runtime_id)
ssm_target := ssm.StartSessionInput{
Target: &target,
}
targetJSON, err := json.Marshal(ssm_target)
// StartSession実行時の引数にJSON化したExecuteCommandの返り値を与える
cmd := exec.Command(
"session-manager-plugin",
string(sess),
aws_region,
"StartSession",
"",
string(targetJSON),
"https://ssm."+aws_region+".amazonaws.com",
)
やっていないこと
- paginationの処理
- クラスターやクラスター内のサービスが100以上という環境を扱うことが今のところないので対応してないです
- リージョンを入力ではなく選択肢から選べるようにする
- リージョンを切り替えてECS Execする機会がほぼないのでわざわざ選択方式にする必要もないなということで入力方式にしました
- ECS Execの実行可否確認
- amazon-ecs-exec-checkerのようなチェックツールがあるので見送りました
- 実行環境のsession-manager-pluginの有無確認
- amazon-ecs-exec-checkerで確認できるので入れませんでしたがこれは入れても良かったかも?
Discussion