【待望】コンテナデバッグが捗る!ECS-optimized AMIにSSMエージェントがプリインストールされるようになりました

ECS(on EC2)環境において、不要な踏み台サーバをなくすことができる便利なアップデートです。
2020.02.17

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

「やっぱり…タスクが変な動きしてる時、Dockerコマンド使いたくなるやん。それが人間ってもんやん…」

ECS(on EC2)の環境で、コンテナが妙な起動をしているとき、そのホストインスタンスにログインしてDockerコマンドで原因追求することを日常のオペレーションとして実施されている現場多いと思います。Fargateではできない、docker execを利用した調査、捗りますよね。そんな皆様に待望のアップデートです。

AWS Systems Manager Agent を Amazon ECS 用に最適化された Linux 2 AMI にプリインストール

SSMエージェントがプリインストールされるということは、セッションマネージャーが使えるということです。ということは、ホストインスタンスログインのための、踏み台サーバの設置、セキュリティグループの開放、SSHキーの管理などが全て不要になるということです。

めっちゃ楽やん…!!

  ( ゚д゚) ガタッ
  /   ヾ
__L| / ̄ ̄ ̄/_
  \/   /

SSMエージェントのプリインストールでなにが嬉しいのか?

一言、ECS(on EC2)の環境において、Dockerコマンドのためだけに踏み台サーバーを用意する必要がなくなる点です。

通常、コンテナを格納するEC2インスタンスはセキュリティ上の観点からプライベートサブネットに配置するのが普通です。ただそういう構成の場合、コンテナに異常が発生したときにホストインスタンスにログインしてDockerコマンドを使おうとしても、別途パブリックサブネットに踏み台サーバーをおいてそれ経由でSSHログインするなどの手間が必要でした。

それを解決するのがSystems Managerで提供されているセッションマネージャーという機能で、これを使うとプライベートサブネットに配置したEC2インスタンスに対してログインが可能で非常に便利!なのですが、そのためにはEC2インスタンス内にSSMエージェントが必要となります。

通常のEC2インスタンスで使うAMIなどはデフォルトでこのSSMエージェントが最初からインストールされているため、ロールのみ設定すれば即セッションマネージャーを利用したログインが可能でした。しかし、ECS-optimizedインスタンスには、このSSMエージェントがインストールされていませんでした。

SSMエージェントのインストールにはSSHログインが必須です。なので従来は以下の手順を踏んでました。すごい冗長ですよね。

昔の手順(9つ)

  1. ECS-optimizedインスタンスの起動
  2. 踏み台サーバの設置
  3. セキュリティグループの設定
  4. 踏み台経由でSSHログイン
  5. SSMエージェントのインストール
  6. EC2へのIAMロール設定
  7. セッションマネージャー経由でのログイン
  8. 不要なセキュリティグループの破棄
  9. 不要な踏み台サーバの破棄

今の手順(3つ)

これが、ECS-optimizedインスタンスにSSMエージェントがプリインストールされることで、このような手順になります。手順が一気に減ります。

  1. ECS-optimizedインスタンスの起動
  2. EC2へのIAMロール設定
  3. セッションマネージャー経由でのログイン

最高じゃないですか!やっほぅ!

ECSのタスクがうまく起動しなかったり、コンテナの挙動が不明でDockerコマンドを使ってコンテナの調査をするのは、ECS(on EC2)の環境において非常によくあるオペレーションだったと思いますが、そのための手間が減るのは運用上非常にメリットがあります。

SSMエージェントがプリインストールされたECS-optimized AMIの仕様

Amazon ECS-optimized AMIの仕様は、こちらの公式ドキュメントにまとまっています。

Amazon ECS-optimized AMIs - Amazon Elastic Container Service

すでに、全ての商用リージョンで、SSMエージェントがプリインストールされたECS-optimized AMIを利用可能です。要件としてはECSエージェントバージョンが1.36.2が必要となります。

このバージョンは、Systems Managerのパラメータストアに格納されています。格納されているメタデータはRetrieving Amazon ECS-Optimized AMI Metadataにまとめられていますが、以下のコマンドで最新版のAMIIDとECSエージェントバージョンが取得できます。

2020年2月16日に、東京リージョンの最新版ECS最適化AMIの情報を取得した結果です。

aws ssm get-parameters --names "/aws/service/ecs/optimized-ami/amazon-linux-2/recommended" --region ap-northeast-1
{
    "Parameters": [
        {
            "Name": "/aws/service/ecs/optimized-ami/amazon-linux-2/recommended",
            "Type": "String",
            "Value": "{\"schema_version\":1,\"image_name\":\"amzn2-ami-ecs-hvm-2.0.20200205-x86_64-ebs\",\"image_id\":\"ami-09ab4b51b72020b66\",\"os\":\"Amazon Linux 2\",\"ecs_runtime_version\":\"Docker version 18.09.9-ce\",\"ecs_agent_version\":\"1.36.2\"}",
            "Version": 28,
            "LastModifiedDate": 1581531994.668,
            "ARN": "arn:aws:ssm:ap-northeast-1::parameter/aws/service/ecs/optimized-ami/amazon-linux-2/recommended"
        }
    ],
    "InvalidParameters": []
}

ecs_agent_versionが、1.36.2になっているところで、最新版はSSMエージェントがプリインストールされているとのことです。

ECSクラスターとECSインスタンスを最初から作って試してみる

というわけで、実際にクラスターとECSインスタンスを新規で作って試してみます。WebコンソールのECSメニューから[Create Cluster]をクリックすると、[Select cluster template]画面が表示されます。

今回は、VPC周辺とECSインスタンスを自動で作成したいので、[EC2 Linux + Networking]を選択して次へ。

[Configure cluster]画面が表示されます。とりあえずECSインスタンスがあればなんでも良いので、以下の内容で作成しましょう。下記項目以外はデフォルトで良いです。

  • Cluster name:任意の名前
  • EC2 instance type:t3.smallあたりで
  • EC2 Ami Id:東京リージョンであれば、最新版のimage_idのami-09ab4b51b72020b66が選択されていると思います
  • Key pair:[None - unable to SSH]にします。SSH使えないのは不安ですが、セッションマネージャーでアクセスするので、ここは不要です

その他項目デフォルトでクラスターを作成します。CloudFormation Stackが完了するまで、しばし待ちましょう。

作成完了したら、ECSメニューに戻り該当するクラスターの[ECS Instances]タグを開いて、インスタンスが作成されていることを確認します。

[ec2 Instance]タブに表示されているEC2 インスタンスIDをクリックしてEC2メニューを開きます。正常に作成されているでしょうか。

EC2のIAMロールの確認、SSMエージェント用のポリシー追加

SSMエージェントを使って、SessionManagerを使う場合、EC2インスタンスのIAMロールにそのためのポリシーが必要となります。

EC2インスタンスを選択状態にして、インスタンスに適用されているIAM roleを確認します。

上の手順でEC2を作成された人は、ecsInstanceRoleロールの中に、AmazonEC2ContainerServiceforEC2Roleというマネージドポリシーが含まれていると思いますが、このポリシー中にはSSMエージェント用の権限が含まれていません。

SSMエージェント用のポリシーを別でアタッチする必要があります。方法は大きく分けて2つ。

方法①:AmazonEC2RoleforSSMマネージドポリシーを割り当てる(非推奨)

AmazonEC2RoleforSSMポリシーをアタッチすることでセッションマネージャーが利用できます。が、これは非推奨です。

ポリシーのDescriptionには、以下の記述があります。将来的にこのポリシーは廃止予定で、Amazon SSMManagedInstanceCoreポリシーの利用が推奨されています。

This policy will soon be deprecated. Please use AmazonSSMManagedInstanceCore policy to enable AWS Systems Manager service core functionality on EC2 instances. For more information see https://docs.aws.amazon.com/systems-manager/latest/userguide/setup-instance-profile.html

単純に言うと、AmazonEC2RoleforSSMポリシーは、Systems Managerで利用する全般の権限が含まれているのですが、Systems Managerはその用途が非常に広いため、今回の主な用途であるセッションマネージャーの利用には権限が強すぎます。

特に、Dockerコンテナの脆弱性からホストインスタンスが乗っ取られてそこから被害を招くという事故は過去にも例があります。あなたの現場にも起こりえます。アプリケーションをインターネット公開する場合に、セキュリティ関連は非常に自覚的になっておく必要があるので、このポリシーの利用は検証用途など限られた場合のみにしておきましょう。

このあたり、弊社中川のこの記事をご参照ください。

新ポリシー AmazonSSMManagedInstanceCore がサポートされました | Developers.IO

方法②:セッションマネージャー用の最小権限のポリシーを割り当てる(推奨)

Systems Manager全般で必要になる権限ではなく、セッションマネージャーのみに絞った権限を割り当てましょう。こっちのほうがセキュリティ的には堅牢ですね。セッションマネージャー用の権限ポリシーは、下記ドキュメントを参考にしてください。

Adding Session Manager Permissions to an Existing Instance Profile - AWS Systems Manager

具体的には、以下のポリシーをロールに割り当てる必要があります。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssmmessages:CreateControlChannel",
                "ssmmessages:CreateDataChannel",
                "ssmmessages:OpenControlChannel",
                "ssmmessages:OpenDataChannel"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetEncryptionConfiguration"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "kms:Decrypt"
            ],
            "Resource": "key-name"
        }
    ]
}

セッションマネージャーは、操作ログをCloudWatch LogsやS3に格納することもできるので、そのあたりは利用要件に応じて適切なポリシーを設定してください。そのあたりもドキュメントに含まれています。

セッションマネージャーを利用した接続方法

ここまでで、事前準備は完了。あとは、セッションマネージャーでログインできるか確認しましょう。接続方法は何点かあります。

接続方法①:Webコンソールのセッションマネージャーから

Webコンソールから[AWS Systems Manager]の[Session Manager]を選択し、[Start session]ボタンをクリック。セッションの確立が可能なインスタンスの一覧が表示されているので、該当インスタンスを選択し、[Start session]ボタンで、インスタンスに接続できます。

もし、この段階でエラーが出た場合、セッションマネージャーの接続を確立するための権限がEC2インスタンスに不足していることが考えられるため、IAMポリシー中心に見直してみてください。

セッションマネージャーで接続した直後はユーザーがssm-userのため、Dockerコマンドが使えません。rootユーザーへのスイッチは可能なので、こんな感じでDockerコマンドを使ってみてください。

h-4.2$ whoami
ssm-user
sh-4.2$ sudo su
[root@ip-10-0-1-47 bin]# docker container ls
CONTAINER ID        IMAGE                            COMMAND             CREATED             STATUS                 PORTS               NAMES
b2aa2ea5d98e        amazon/amazon-ecs-agent:latest   "/agent"            8 hours ago         Up 8 hours (healthy)                       ecs-agent

接続方法②:EC2のConnectメニューから

こっちも簡単ですね。Webコンソールの[EC2]メニューを開き、接続するインスタンスを選択し、[Connect]ボタンをクリックします。

そうすると、EC2インスタンスに接続する方法がでてくるので、[Connection method]で[Session Manager]を選択し、[Connect]ボタンクリックで同様に接続できます。こちらのメニューはIAMロール設定直後は使えなかったりするので、その場合はしばらく待つか画面をリロードするなどしましょう。

参考:[小ネタ] EC2のコンソール画面からSSM Session接続できる様になりました | Developers.IO

接続方法③:AWS CLIから

Webコンソールを開かなくても、AWS CLIからssmのstart-sessionコマンドを使って接続できます。

参考:start-session — AWS CLI 1.18.0 Command Reference

利用方法は非常に簡単で、--targetオプションに接続先インスタンスのインスタンスIDを指定するだけ。

$ aws ssm start-session --target i-0c45bdd6943767bd0

Starting session with SessionId: 1581792443317876000-08f553e389da2430b
sh-4.2$ sudo su
[root@ip-10-0-0-230 bin]# docker container ls
CONTAINER ID        IMAGE                            COMMAND             CREATED             STATUS                    PORTS               NAMES
305283ca78f9        amazon/amazon-ecs-agent:latest   "/agent"            15 minutes ago      Up 15 minutes (healthy)                       ecs-agent

いやぁ、便利な世の中になったもんですねぇ。

管理するものを減らしTCOを下げて効率よくコンテナ環境を運用しよう!!

以上、ECS optimized-amiにSSMエージェントがインストールされたことのメリットをセッションマネージャー中心に書いてみました。

もちろん、SSM(Systems Manager)には、EC2インスタンスを管理するための機能が非常に豊富に用意されているので、今回のアップデートはパッチの適用やコマンドの一括実行などでも威力を発揮すると思います。

踏み台サーバーの用意やセキュリティグループの設定変更やSSHキーの管理が軒並み不要になるのは、TCOの削減に非常に寄与するし、セキュリティも堅牢になります。ECS (on EC2)で、今までSystems Managerを使っていなかった人は、ぜひ今回のアップデートをきっかけに、そのあたりの運用見直していただければと思います。

それでは、今日はこのへんで。濱田(@hamako9999)でした。

余談

そのうちきっと、Fargateのタスクにもセッションマネージャーでログインできるようになると、信じています。

How to run "docker exec... " command in ECS · Issue #187 · aws/containers-roadmap