🌈

ECSで好きなだけブランチ別の環境を作る mirage-ecs - fujiwara-ware 2024 day 20

2024/12/20に公開

この記事は fujiwara-ware advent calendar 2024 の20日目です。

mirage-ecs とは

https://github.com/acidlemon/mirage-ecs

mirage-ecs は、Amazon ECS で好きなだけブランチ別の環境を作るためのツールです。

「ブランチ別の環境」とは、例えば以下のようなものです。

  • main ブランチのコードをデプロイした URL main.example.com
  • feature/xxx ブランチのコードをデプロイした URL xxx.example.com
  • fix/yyy ブランチのコードをデプロイした URL yyy.example.com

多くのメンバーがいるチームで開発をしていると、それぞれのメンバーが作業をしているブランチごとにデプロイされた環境がほしくなります。そのような環境を手動で作るのは大変ですが、mirage-ecs を使えば簡単に作ることができます。

なぜ作ったのか

筆者が関わっていたプロジェクトでは、数十人のチームでメンバーが同時平行で開発や運用をしていました。効率的に仕事を進めるためには、それぞれが作業しているブランチで確認できる環境が必要です。

例えばデザイナーが更新した画像を実アプリケーションで確認したいこともありますし、ディレクターやゲームデザイナーが作成したマスターデータ(例えばステージの配置情報)を実機で確認したいこともあります。これができるかできないかでは、開発のスピードが大きく変わります。

エンジニアの手元では開発中のコードを動かしてサーバーを起動できますが、エンジニア以外のメンバーに手元でサーバーを動かせというのは無理があります。

つまり、なんらかの方法でブランチごとに環境を作る必要があります。素朴に実装する場合、それぞれのブランチごとに IaC で環境を作ることになりますが、これは大変です。それぞれのブランチごとにクラウド上に別々に環境を作ると、当然ながら大きなコストがかかります。

mirage-ecs は、このような状況に対応するために作られました。

元々は acidlemon さんが作った mirage というツールがありました。mirage は1台のマシンの上で Docker コンテナを環境として起動して動作するものでしたが、その Amazon ECS 版として筆者が開発したものが mirage-ecs です。

https://techblog.kayac.com/mirage_for_docker.html

動作原理

mirage-ecs は Amazon ECS 上で Web アプリケーションとして動作します。この Web アプリケーションは、Web UI を持ち、フォームから環境名とブランチ名を入力すると、それに対応した ECS タスク を作成します。

そして環境ごとに起動した ECS タスクに対して URL を割り当てます。この URL は ECS タスクの Private IP に対して mirage-ecs が reverse proxy を動的に設定することで実現されます。

例: (サブドメインとブランチ名の対応は任意です)

  • 環境名: foo (ブランチ名: feature/foo) foo.example.com
  • 環境名: bar (ブランチ名: feature/bar) bar.example.com
  • 環境名: baz (ブランチ名: feature/baz) baz.example.com

*.example.com に対してのリクエストは全て mirage-ecs が受け、適切な ECS タスクに転送します。

起動される ECS タスク側の処理

mirage-ecs から起動される ECS タスクには SUBDOMAIN, GIT_BRANCH という環境変数が渡されます。ECS タスクはこれらの環境変数を使って、適切なブランチのコードで起動するように作っておく必要があります。データベースをインスタンスを共用している場合、SUBDOMAIN によって使用するデータベースを切り替えることで、環境ごとにデータを分離する必要もあるでしょう。

タスクが使用するリソースの設定に mirage-ecs は関与しないため、起動するタスクが環境変数を元に適切な処理を行う必要があります。

追加で環境に渡したい値がある場合は mirage-ecs の設定ファイルで定義することで、フォームから入力できるようになります。

例えば下記の設定をすると、Web UI から foo という名前のパラメーターを入力できるようになり、入力した値は ECS タスクに FOO という環境変数で渡されます。

parameters:
  - name: foo
    env: FOO
    description: "foo parameter"

便利な機能

mirage-ecs にはいろいろな便利な機能があります。

ECS 関連の設定を自動設定

ECS タスクを起動するためには、VPC サブネット、セキュリティグループなどの設定が必要です。これらの設定は個別に設定ファイルに記述することもできますが、省略された場合は mirage-ecs 自身が動作している設定を流用して、各環境のタスクを起動します。

tracer でログを見る

mirage-ecs は tracer が組み込まれています。環境ごとのタスクが上手く起動しない場合、tracer で把握したログを Web UI から確認することができます。

tracer については、このアドベントカレンダーの5日目で紹介しています。

https://zenn.dev/fujiwara/articles/fujiwara-ware-2024-tracer

一定期間アクセスがない場合に自動削除

mirage-ecs から起動した ECS タスクは一定期間アクセスがない場合に自動的に削除するように設定できます。

mirage-ecs がリクエストを proxy する際には、環境ごとのアクセス数を CloudWatch に記録しています。その値を参照し、一定時間内に一度もアクセスがない環境の ECS タスクを停止します。コスト削減のために便利な機能です。

とはいえ、アクセスがなくても保持したい環境もありますよね(お客様向けのデモ環境など)。その場合は、特定の環境を自動停止の対象から除外することもできます。

除外設定は環境名、ECS タスクのタグなどを元に柔軟に設定できます。

purge:
  schedule: "13 4 * * ? *" # 毎日4時13分に停止処理を実行 (EventBridge互換のcron式)
  request:
    duration: 86400 # 1日以上アクセスがない場合に停止
    excludes:
      - foo # foo, bar という環境は停止しない
      - bar
    exclude_tags:
      - "branch:preview" # preview というタグがついている環境は停止しない
    exclude_regexp: "^(foo|bar)" # 正規表現で指定することもできる

API 対応

mirage-ecs は Web UI のみではなく、API でも操作できます。これによりチャットボットや CI/CD ツールなどからも環境の起動や停止を操作できます。

筆者の関わっていたプロジェクトでは Slack から環境を操作するためのボットを作成し、Slack のメッセージ経由で環境を作成したり削除したりすることができました。Web UI よりも手軽に操作できるため、日常的に使われるインターフェースでした。

他のプロジェクトでは、GitHub Actions のワークフローから環境を作成する運用をしていました。PR 単位で環境を作成し、PR がクローズされたら環境を削除するという運用も可能です。

まとめ

mirage-ecs は、Amazon ECS で好きなだけブランチ別の環境を作るためのツールです。Web UI や API から環境名とブランチ名を入力するだけで、簡単に環境を作って独立した URL を割り当てることができます。

ちょっと複雑なツールなので、実際に運用するまでには少し手間が掛かるかもしれません。運用が始まれば開発の効率が大幅に向上することでしょう。筆者が勤務しているカヤック以外でも、例えばはてなさんでも mirage-ecs を検討しているようです。

https://developer.hatenastaff.com/entry/2024/10/23/205543

それでは、明日もお楽しみに!

参考資料

https://techblog.kayac.com/mirage-ecs-at-qwan

https://speakerdeck.com/fujiwara3/yapc-hiroshima-2024

Discussion