AWS EC2/ECSへのメンテナンス接続
AWSのコンピューティング環境といえば、Lambdaなどのサーバレスなサービスを除けば、EC2やECSといった環境が主になるかと思います。
その昔にはBastion(踏み台)サーバを用意してsshする、といった構成がありましたが現代ではSystems Manager(SSM)という素晴らしいサービスにより、安全にEC2やECSにアクセスし、メンテナンスすることができるようになっています。
EC2
AWS Systems Manager Session Manager
EC2の場合はSSMのSession Managerという機能を利用することでブラウザやCLIから安全にEC2の仮想的なセッションに接続することができます。
仕組み
SSM AgentというAWSが提供しているエージェントソフトがAWSが管理しているシステムとの間でセッションを確立します。
我々メンテナンスしたい人は、AWS CLIやマネジメントコンソールを介してSession Managerに接続し、仮想的なセッションに接続することで対象サーバ上でのシェルの操作が可能となります。
従来のようなSSH
の仕組みは一切介さないため、22番ポートをインターネットに対して許可する必要もありませんし、何らかのインバウンド通信をEC2に対して許可する必要すらありません。
認証はIAMを利用して行われ、SSHのようにID, パスワード, 公開鍵認証なら秘密鍵, といったものも不要です。
通信はHTTPSで安全に暗号化された通信路で行われます。
前提条件
SSM AgentというAWSが提供しているエージェントソフトを対象インスタンスにインストールし、起動しておく必要があります。
AWSが提供しているAmazon Linux2やAmazon Linux2023のAMIには、SSM Agentがインストール済みのため、EC2を起動するだけで利用可能です。
ただし、以下のように通信路
とIAMの権限
が必要となります。
通信路
以下のエンドポイントにHTTPS(TCP443ポート)接続できる必要があります。
- ec2messages.region.amazonaws.com
- ssm.region.amazonaws.com
- ssmmessages.region.amazonaws.com
これらのエンドポイントに接続できるとはどういうことでしょうか?以下のようになります。
- EC2のセキュリティグループのアウトバウンドルールで 0.0.0.0/0 に対して HTTPS(TCP443)が許可されている
- 以下のいずれかを満たす
2-1. InternetGateway, もしくはNat Gatewayを通してインターネットと通信可能な経路がある
2-2. 上記3つのエンドポイントに対応したVPCエンドポイントがEC2の属するSubnetに作成されている
IAMの権限
EC2にIAMロールを割り当て、IAMロールに以下のIAMポリシーを割り当てておく必要があります。
AmazonSSMManagedInstanceCore
これはAmazonのマネージドポリシーです。
マネージドポリシーを利用せず自分で個別にActionを設定する場合はドキュメントを参照してください。
接続方法
マネジメントコンソールから
-
Amazon EC2 コンソール (https://console.aws.amazon.com/ec2/) を開きます。
-
左ペインで、
インスタンス
を選択します。 -
接続したいインスタンスを選択し、右上の
接続
ボタン をクリックします。 -
Connection method (接続方法)
で、Session Manager
タブ を選択します。 -
接続
ボタンをクリックします。
AWS CLIから
AWS CLIで接続したいEC2のあるAWSアカウントの認証設定は済んでいるものとします。
EC2のリスト確認
% aws ec2 describe-instances --query 'Reservations[*].Instances[*].[InstanceId, Tags[?Key==`Name`].Value | [0], State.Name]' --output text
i-1234abcd5678efgi0 test-ec2-001 running
Session Managerで接続
% aws ssm start-session --target i-1234abcd5678efgi0
ECS
ECS Execを利用することで、EC2やFargateで実行中のコンテナ内でコマンドを実行することができます。
特にFargateについてはECS Execを利用しない場合はコンテナでsshdを起動しておくしかコンテナ内に入る方法がないため、重要です。
ECS Exec
ECS Execを有効化
AWS CLIを利用します。
クラスタ一覧を取得しcluster nameを確認します。
% aws ecs list-clusters
クラスタを指定してECS Serviceのnameを確認します。
% aws ecs list-services --cluster <cluster name>
対象のECS ServiceでECS Execを有効化します
% aws ecs update-service \
--cluster <cluster name> \
--enable-execute-command \
--service <ecs service name>
ECS Execを有効化したあとに起動されたECS Taskから有効化されるため、新しいタスクを起動します
% aws ecs update-service \
--cluster <cluster name> \
--service <ecs service name> \
--force-new-deployment
ECS Execを実行
ECS ExecはECS Taskを指定して接続します。ECS Serviceに属するECS Taskのリストを確認します。
% aws ecs list-tasks --cluster <cluster name> --service-name <ecs service name>
{
"taskArns": [
"arn:aws:ecs:ap-northeast-1:123456789012:task/<ecs service name>/<task id>"
]
}
aws-cliでECS TaskのIDと、コンテナ名(例えば"app")、実行するコマンド(ここでは/bin/bash)を指定し実行します。
% aws ecs execute-command --region ap-northeast-1 --cluster <cluster name> --container <container name> --command "/bin/bash" --interactive --task <task id>
これで指定したコンテナでbashが実行され、仮想的なセッションで接続されます。
もっと簡単に
ここまで見ていただくとわかるとおり、めちゃくちゃめんどくさいですね。
k_i さんが開発してくださった ecsh
というコマンドを利用するとインタラクティブに、簡単に利用できます。
ありがとうございます。
最後に
Session ManagerやECS Execを利用することで安全にEC2やECSにアクセスすることが可能になりました。
ただファイルの転送をするにはS3を経由させないとできなかったりなど面倒な部分もあります。
今後の改善に期待しております。
Discussion