ECSで作業用のタスクをサクッと作るためのツールを作成した

インフラエンジニアの菅原です。

最近、バイクに念願のグリップヒーターをつけました。 これでツーリング時の手の寒さが多少楽になりそうで喜んでいます。

とはいってもなかなか出かけられないのですが…


現在私はAWS Fargateを使ったサービスをECS上に構築を進めており、日々コンテナと戯れています。

基本的にストレージ以外のコンポーネントはほとんどECSで動いているのですが、VPCのネットワーク内でちょっとした作業(たとえばネットワークの疎通確認など)をしたい場合、都度新しいタスクを起動して作業しています。 また、DBにテストデータを入れたかったり、どうしてもDBを直接操作したいことがある場合、stoneを新しいタスクを起動した上で、そのタスクを踏み台としてaws ssm start-sessionでポートフォワーディングを行い、手元から直接DBにアクセスできるようにしたりしています。

しかしそのような一時的なタスクの起動は

  1. タスク定義のディレクトリに移動する*1
  2. タスクを起動
  3. 起動したコンテナにECS Execでログイン、あるいはポートフォワーディングをする場合はaws ssm start-sessionを実行
  4. 作業後はタスクを停止

…と、なかなか手間がかかります。

imageを実行時にオーバーライドできないので、都度都度タスク定義をエディタで書き換えるのも面倒です。

アプリケーションを動かしているコンテナにECS Execでログインすることもできるのですが、稼働しているコンテナにログインしたくはないですし、そのコンテナにパッケージをインストールするのもさすがに憚られます。

かといって作業用・ポートフォワーディング用にEC2インスタンスを動かすのは、管理コストなどからやりたくはないです。

もっと簡単に作業したい、kubectl run/exec/port-forwardのようにサクッと作業用のコンテナを作りたい…

と考えてそれらをなんとかするツール、demitasを作成しました。

demitas

github.com

demitasはecspressoのラッパーで、ECSタスクの起動・ECS Exec・ポートフォワーディングを簡単にするツールです。

  • タスク定義を~/.demitas配下で一括管理する
  • 単一のコンテナの定義だけ書ける
  • すべての定義を実行時にオーバーライドできる

などの特徴があります。

使い方

まず~/.demitas配下に設定ファイルを作成します。

~/.demitas
├── ecs-container-def.jsonnet
├── ecs-service-def.jsonnet
├── ecs-task-def.jsonnet
└── ecspresso.yml

基本的にecspressoの設定と同じですがecs-task-def.jsonnetにcontainerDefinitionsがないです。 そのかわりecs-container-def.jsonnetに単一のコンテナの定義を書いています。

// ecs-service-def.jsonnet
{
  name: 'oneshot',
  cpu: 0,
  image: 'ubuntu',
  essential: true,
  logConfiguration: {
    logDriver: 'awslogs',
    options: {
      'awslogs-group': '/ecs/oneshot',
      'awslogs-region': 'ap-northeast-1',
      'awslogs-stream-prefix': 'ecs',
    },
  },
}

設定ファイルを作成したら、どのディレクトリにいてもdemitasコマンドでタスクを起動できます。

$ demitas -c '{image: "public.ecr.aws/runecast/busybox:1.33.1", command: [echo, test]}'
2021/10/30 16:52:45 hello/hello Running task
2021/10/30 16:52:45 hello/hello Registering a new task definition...
2021/10/30 16:52:46 hello/hello Task definition is registered busybox:46
2021/10/30 16:52:46 hello/hello Running task
2021/10/30 16:52:47 hello/hello Task ARN: arn:aws:ecs:ap-northeast-1:822997939312:task/hello/d51ca2de190548e2a2b8e8c9644cfab1
2021/10/30 16:52:47 hello/hello Waiting for run task...(it may take a while)
2021/10/30 16:52:47 hello/hello Watching container: busybox
2021/10/30 16:52:47 hello/hello logGroup: /ecs/busybox
2021/10/30 16:52:47 hello/hello logStream: ecs/busybox/d51ca2de190548e2a2b8e8c9644cfab1
..

すべての定義はdemitasのオプションでオーバーライド可能です。上記の例ではコンテナのイメージとコマンドをオーバーライドしています。

また、設定ファイルのディレクトリをさらに~/.demitas/db-subnet ~/.demitas/app-subnetなどと分けることで、実行時にプロファイルを指定してタスクを起動できます。

~% demitas -p db-subnet -c '{command: [psql, -c, "SELECT * FROM foo"]}'

demitas-exec・demitas-pf

demitasではさらに起動したコンテナにログインしたり、ポートフォワーディングを簡易化するためのラッパーを作成しました。

demitas-execはタスクの起動・ECS Exec・タスクの停止を行います。

$ demitas-exec -e bash
Start ECS task...
ECS task is running: 8fba2576ba3841e7aff88f4ecfb7b32b

The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.


Starting session with SessionId: ecs-execute-command-05d903fcaef0393ed
root@ip-10-0-0-18:/# echo test
test
root@ip-10-0-0-18:/# exit
exit


Exiting session with sessionId: ecs-execute-command-05d903fcaef0393ed.

Stopping ECS task... (Please wait for a while): 8fba2576ba3841e7aff88f4ecfb7b32b
done

demitas-pfはタスクの起動・ポートフォワーディング・タスクの停止を行います。

$ demitas-pf -h www.yahoo.com -r 80 -l 10080
Start ECS task for port forwarding...
ECS task is running: c16548617cab480e8fb37f195a8be708
Start port forwarding...

Starting session with SessionId: root-084c5c16763c0f36f
Port 10080 opened for sessionId root-084c5c16763c0f36f.
Waiting for connections...

Connection accepted for session [root-084c5c16763c0f36f]
^CTerminate signal received, exiting.


Exiting session with sessionId: root-084c5c16763c0f36f.

Stopping ECS task... (Please wait for a while): c16548617cab480e8fb37f195a8be708
done
$ curl -s localhost:10080 | grep title
    <title>Yahoo</title>

まとめ

kubectl run、欲しいなぁ、欲しいなぁ」とずーっと思っていたのですが、demitasでだいぶ解消されました。 いまはdocker runぐらいの感覚で作業用タスクの起動しています。

*1:ecspressoを使っています