ECS FargateにSSMでSSH接続する

はじめに
ECS Fargateで動いているコンテナにSSMでSSH接続する必要が出たので、このスクラップに手順や詰まった箇所のメモなどを記録しながら実践していきます
参考

SSM(Session managerとは??)
Session Manager はフルマネージド AWS Systems Manager 機能です。Session Manager を使って、Amazon Elastic Compute Cloud (Amazon EC2) インスタンス、エッジデバイス、オンプレミスサーバー、仮想マシン (VM) を管理できます。インタラクティブ・ワンクリック ブラウザ ベースのシェル、または AWS Command Line Interface (AWS CLI) を使用できます。Session Manager は安全かつ監査可能なノード管理を実現し、インバウンドポートを開いたり、踏み台ホストを維持したり、SSH キーの管理したりする必要はありません。また Session Manager はマネージドノードの制御されたアクセス、厳格なセキュリティプラクティス、ノードアクセス詳細がある完全監査可能なログを要件とする社内ポリシーの尊守を実現しつつ、エンドユーザーが簡単なワンクリック・クロス プラットフォームアクセスによってマネージドノードの使用を実現します。
プラグインのダウンロード
筆者はUbuntuを使用しているので、以下の公式ドキュメントに沿って行う
- Session Manager プラグイン deb パッケージをダウンロード
$ curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/ubuntu_64bit/session-manager-plugin.deb" -o "session-manager-plugin.deb"
- インストールコマンドを実行
$ sudo dpkg -i session-manager-plugin.deb
- 不要になったインストール用ファイルの削除
$ rm -rf session-manager-plugin.deb
- インストール確認
$ session-manager-plugin The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.

ECS(Fargate)のコンテナに接続する
- ECSExecの有効化
$ aws ecs update-service --region ap-northeast-1 --cluster クラスター名 --service サービス名 --enable-execute-command
最後に"enableExecuteCommand": trueと表示されていれば有効化できている
もしも、下記エラーがでた場合はタスク定義のロールに誤りがあります。タスク定義のタスクロールを「ecsTaskExecutionRole」に変更してみてください。"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."
SSMを利用しコンテナに接続する
- 以下を実行
aws ecs execute-command --region ap-northeast-1 --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-execute-command-XXXXXXXX
/app # ←プロンプトが返ってくれば接続成功
- 筆者はこのタイミングで以下のエラーに遭遇
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.
- タスクに割り当てられているロールを確認
しかし「ecsTaskExecutionRole」になっている - サービスの再起動
ドキュメントを再度確認すると、既存のタスクには適用されないようなので、タスクを一度「停止」⇒「サービスの更新」で再起動します。
まだエラーが続くので再調査したときろ、以下のアクセス権限に対して許可が必要そうだったので追加する
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssmmessages:CreateControlChannel",
"ssmmessages:CreateDataChannel",
"ssmmessages:OpenControlChannel",
"ssmmessages:OpenDataChannel"
],
"Resource": "*"
}
]
}
作成したポリシーをECSタスクロールに追加で割り当てます
これらの変更がタスクレベルで伝播される際に遅延が起きる場合があります。そのため、タスクロールにポリシーを添付した後、しばらく待ってから、 execute-command コマンドを実行してください。
- コマンドの再実行
$ aws ecs execute-command --region ap-northeast-1 --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-execute-command-euqddvvhdxj5vmx67aa6aylh64
/var/www/html #

メンテナンスモードに入れてコマンドをテストする
実際にコマンドが動作するかテストします
筆者の環境はLaravelなので、以下のコマンドで行います
- サーバーを停止
$ php artisan down
- ブラウザでアクセスし、メンテナンスモード(503)になるか確認する
- 確認できたら再起動
$ php artisan up

execute commandを無効化する
セキュリティのため、作業が終わったら以下のコマンドでexecute command
無効化しておきます
$ aws ecs update-service --region ap-northeast-1 --cluster クラスター名 --service サービス名 --disable-execute-command
実行したら下の方へいき、"enableExecuteCommand": false
になっていれば完了

さいごに
アクセス権限が足りずに接続できなかった部分が詰まりポイントでしたが、無事接続できました