tl;dr
2022/02/17 追記: ECS Exec を利用しましょう。
こんばんは。ブログ書かなすぎてはてなブログ Pro を契約したえのかわです。
Fargate に対して SSH ログインしたい時ってありますよね。SSH プロセスを起動するのもアレなので ssm-agent を入れた運用用途の Task を起動してみました。
きっかけは Tori さんのツイートです。 実際に業務でも「EC2 レスで RDS へのログインとかどうすっかなー」と考えていたので、良いきっかけでした。
もう VPC 内で CLI 叩きたいとか RDS 繋ぎたいとか、全部コンテナイメージにバイナリ群 + ssm-agent 詰め込んで Fargate に必要なときだけデプロイするとかでいいんじゃない?
— Tori Hara (@toricls) 2019年8月29日
踏み台用の仮想マシンなくせて秘密鍵管理も要らないしお財布に優しいしなにより常駐踏み台よりもセキュアな気がする
やりたいことはこんな感じです。EC2 起動したら負け。
SSM Activation の作成
この方法は ECS Task を外部サーバとみなすため、SSM で Hybrid Activation を作成します。
$ aws ssm create-activation --description fargate-ops \ --iam-role "service-role/AmazonEC2RunCommandRoleForManagedInstances" \ --registration-limit 100000 \ --default-instance-name fargate-ops { "ActivationId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "ActivationCode": "xxxxxxxxxxxxxxxxxxx" }
出力された ActivationId
と ActivationCode
は後で利用するので控えておきます。 --registration-limit
を 100000 としているのは、ECS Task を起動する度に SSM の Managed Instances に外部サーバ(2回目)として登録されるためです。 運用時は頻繁に ECS Task の起動や停止が予想されるので Max 値(2019/09/05 現在)にしています。
SSM Parameter Store への Activation 情報登録
前の手順で出力された ActivationId
と ActivationCode
は amazon-ssm-agent の Register 時に必要となるので、SSM Parameter Store に put しておきましょう。
$ aws ssm put-parameter --name "ops-activation-id" \ --value "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" \ --type "SecureString" { "Version": 1 } $ $ aws ssm put-parameter --name "ops-activation-code" \ --value "xxxxxxxxxxxxxxxxxxx" \ --type "SecureString" { "Version": 1 }
そういえば SSM Parameter Store の Name を /Fargate/ops-activation-id
とかにしたら Fargate Task の起動が上手くいきませんでした。( エラー内容忘れた。。
Docker imageの作成 / Push
Dockerfile の中身は GitHub を見てみてください。( Star くれると喜びます
189MB
て。。PR もお待ちしています。
$ docker image ls enokawa/ssm-to-fargate REPOSITORY TAG IMAGE ID CREATED SIZE enokawa/ssm-to-fargate latest e864b10da748 42 minutes ago 189MB
ちなみにリポジトリ直下で $ docker-compose up -d
を実行するとローカルでも動作確認が可能です。その際は以下の 3 つの環境変数も設定してあげてください。僕は direnv で環境変数を設定しています。
SSM_AGENT_CODE
SSM_AGENT_ID
AWS_DEFAULT_REGION
ECR に Docker image を push します。
$ docker build -t enokawa/ssm-to-fargate:latest . $ $(aws ecr get-login --no-include-email --region <AWS_DEFAULT_REGION>) $ docker tag enokawa/ssm-to-fargate:latest <AWS_ACCOUNT_ID>.dkr.ecr.<AWS_DEFAULT_REGION>.amazonaws.com/ssm-to-fargate:latest $ docker push <AWS_ACCOUNT_ID>.dkr.ecr.<AWS_DEFAULT_REGION>.amazonaws.com/ssm-to-fargate:latest
ECS Task の起動
事前に Task Definition 内の Container Definitions で、SSM_AGENT_CODE
と SSM_AGENT_ID
を定義します。
AWS_DEFAULT_REGION
は ECS Task 内の環境変数に含まれているため設定不要です。ECS での機密情報や環境変数の扱いについてはハマコーさんの記事が詳しいです。
タスクを起動します。
$ aws ecs run-task \ --launch-type FARGATE \ --task-definition "<YOUR_TASKDEF_ARN>" \ --platform-version 1.3.0 \ --cluster <YOUR_CLUSTER_NAME> \ --count 1 \ --network-configuration "{\"awsvpcConfiguration\":{\"subnets\":[\"subnet-xxxxxxxxxxxx\"],\"securityGroups\":[\"sg-xxxxxxxxxxxxxx\"],\"assignPublicIp\":\"DISABLED\"}}"
Task が起動すると、SSM の Managed Instances 上で外部サーバとして起動した Container の情報が確認できます。InstanceId
を控えておきます。
$ aws ssm describe-instance-information { "InstanceInformationList": [ { "InstanceId": "mi-xxxxxxxxxxxxxxxx", "PingStatus": "Online", "LastPingDateTime": 1567615737.931, "AgentVersion": "2.3.701.0", "IsLatestVersion": true, "PlatformType": "Linux", "PlatformName": "Ubuntu", "PlatformVersion": "18.04", "ActivationId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "IamRole": "service-role/AmazonEC2RunCommandRoleForManagedInstances", "RegistrationDate": 1567615733.866, "ResourceType": "ManagedInstance", "Name": "fargate-ops", "IPAddress": "169.254.172.42", "ComputerName": "ip-10-0-2-100.ap-northeast-1.compute.internal" } ] }
Fargate Container へのログイン
Session Manager 経由で Fargate Container へログインします。
$ aws ssm start-session --target mi-xxxxxxxxxxxxxxxx
いい感じですね。後はお好きにどうぞ。
後片付け
ECS Task の Stop と SSM Managed Instance の Deregister を行います。
$ aws ecs stop-task --cluster sample-cluster \ --task "<TASK_ID>" $ $ deregister-managed-instance --instance-id mi-xxxxxxxxxxxxxxxx
おわりに
無事に Fargate container に Session Manager 経由でログインすることができました。踏み台や秘密鍵の用意も不要なのでセキュアかつ費用も安く抑えることが可能です。aws/containers-roadmap
の Issue でも活発に議論されているので、注目したいと思います。
個人的には、AWS が docker exec 的な API を作成してくれるのではないかなと妄想しています。aws-cli で以下のように実行できると嬉しいですね。
$ aws ecs exec --task "<TASK_ID>"
FYI
以下の Qiita 記事が参考になりました。ありがとうございました。
2020/07/06 追記
SSM の Hybrid Activation 作成ですが、有効期限が予め決まっています。 --expiration-date
オプション指定なしだとデフォルトの 24 時間、指定ありだと最大 30 日です。
@fujiwara さんの仰る通りで、Hybrid Activation を今日作ったとしても有効期限は最大で 30 日となるため、新しく Hybrid Activation を作成して Parameter Store へ put するなどの運用が必要となります。再作成用の Lambda を作る手もありますが面倒ですね。#187 の Issue を引き続き Watch することにします。
ECS taskにコンソールログインするためにSSM agent使ってみた。アクティベーションの有効期限が最大30日なので、毎月作り直す仕組みとセットでないと運用できなくて、これはダルいのでは?
— fujiwara (@fujiwara) 2020年2月4日
2022/02/17 追記
ECS Exec が発表されましたね。これ使いましょう。