AWS EC2/ECSへのメンテナンス接続

2024/06/29に公開

AWSのコンピューティング環境といえば、Lambdaなどのサーバレスなサービスを除けば、EC2やECSといった環境が主になるかと思います。

その昔にはBastion(踏み台)サーバを用意してsshする、といった構成がありましたが現代ではSystems Manager(SSM)という素晴らしいサービスにより、安全にEC2やECSにアクセスし、メンテナンスすることができるようになっています。

EC2

AWS Systems Manager Session Manager

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager.html

EC2の場合はSSMのSession Managerという機能を利用することでブラウザやCLIから安全にEC2の仮想的なセッションに接続することができます。

仕組み

SSM AgentというAWSが提供しているエージェントソフトがAWSが管理しているシステムとの間でセッションを確立します。

我々メンテナンスしたい人は、AWS CLIやマネジメントコンソールを介してSession Managerに接続し、仮想的なセッションに接続することで対象サーバ上でのシェルの操作が可能となります。

従来のようなSSHの仕組みは一切介さないため、22番ポートをインターネットに対して許可する必要もありませんし、何らかのインバウンド通信をEC2に対して許可する必要すらありません。

認証はIAMを利用して行われ、SSHのようにID, パスワード, 公開鍵認証なら秘密鍵, といったものも不要です。

通信はHTTPSで安全に暗号化された通信路で行われます。

前提条件

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-getting-started.html

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

これらのエンドポイントに接続できるとはどういうことでしょうか?以下のようになります。

  1. EC2のセキュリティグループのアウトバウンドルールで 0.0.0.0/0 に対して HTTPS(TCP443)が許可されている
  2. 以下のいずれかを満たす
    2-1. InternetGateway, もしくはNat Gatewayを通してインターネットと通信可能な経路がある
    2-2. 上記3つのエンドポイントに対応したVPCエンドポイントがEC2の属するSubnetに作成されている

IAMの権限

EC2にIAMロールを割り当て、IAMロールに以下のIAMポリシーを割り当てておく必要があります。

AmazonSSMManagedInstanceCore

これはAmazonのマネージドポリシーです。

マネージドポリシーを利用せず自分で個別にActionを設定する場合はドキュメントを参照してください。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/getting-started-create-iam-instance-profile.html

接続方法

マネジメントコンソールから

  1. Amazon EC2 コンソール (https://console.aws.amazon.com/ec2/) を開きます。

  2. 左ペインで、インスタンス を選択します。

  3. 接続したいインスタンスを選択し、右上の接続ボタン をクリックします。

  4. Connection method (接続方法) で、Session Managerタブ を選択します。

  5. 接続ボタンをクリックします。

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

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs-exec.html

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 というコマンドを利用するとインタラクティブに、簡単に利用できます。
ありがとうございます。

https://zenn.dev/k_i/articles/3d540d31be0c0f

最後に

Session ManagerやECS Execを利用することで安全にEC2やECSにアクセスすることが可能になりました。

ただファイルの転送をするにはS3を経由させないとできなかったりなど面倒な部分もあります。

今後の改善に期待しております。

Discussion