OpenWork Tech Blog

社員クチコミサービスを運営しているオープンワークエンジニアによるテックブログです。

ECS Fargate Spot + Terraform でコストを考慮した開発 Web サーバーを作る

インフラチームの小川です。最近、なぜか不良のグループと喧嘩することになって、負ける夢をみました。夢の中くらい強くありたい。

AWS 上で開発環境 Web サーバーを構築した話です。

背景

  • 修正中の Web アプリを複数人で動作確認したいといったニーズがある
    • すなわちローカル開発環境ではダメ
  • 常設の開発環境を EC2 でいくつか用意しているが、需要と供給のバランスがとれないときがある
    • 時間帯によってはサーバー利用の順番待ちが発生することがある。逆も然り
  • Web アプリのコンテナ化を進めているので、うまく課題を解決したい

要件

  • 必要なときに作って、いらなくなったら消せる環境
  • 環境の bash にログインできる
  • Terraform で作る
  • できれば安め

構成図

f:id:openwork_engineer:20210326144412p:plain
構成図

terraform 構成

app
├── modules
│   ├── ecr
│   ├── ecs
│        :
├── sharing
│   ├── base
│   │   ├── main.tf
│   │   ├── variables.tf
│   │          :
│   └── task
│       ├── main.tf
│       ├── variables.tf
│              :
├── stg
└── prd

※ 社内で共用環境と呼んでいる関係で sharing というネーミングになっています

リソースが共通かどうかで tfstate を分けています。

  • 各環境で共通で利用するものは base
    • ECS Cluster, ECR, ALB など
  • 環境個別のリソースは task
    • ECS Service, Task Definition, Listener Rule など

構成要素

Fargate Spot

運用負荷やコストの削減目的で Fargate Spot を利用しています。Spot にすることで Fargate の料金を最大 70% 削減できます。
ただし Spot なので突然の終了が起こりえます。ECS Service がいい感じに生き返らせてはくれますが、それでも多少のダウンタイムが生じてしまいます。そこで EventBridge 経由でリタイアメント通知を受信し、Spot が終了してしまう前に新しい Task を起動させる Lambda を用意する予定です。(予定)

ロードバランサー

環境ごとにロードバランサーを作成するとコストがかさむので、以下のようにロードバランサーは 1 台のみにします。

  • 共通のロードバランサーのもと、リスナールールおよびターゲットグループを環境分用意
  • ドメインベースのルーティングルールを作成し、アクセス先ドメインによって振り分ける

SSM Session Manager でログイン

Fargate のコンテナに Session Manager でログインできるよう、SSM Activation を仕込んでおきます。

  • 環境構築 (terraform apply) 時に Activation 作成
  • 得られた Activation ID/Code を SSM Parameter Store に書き込む
  • コンテナ起動時のエントリポイントで Parameter Store から ID/Code を取得して ssm-agent を立ち上げる

※ 記事を書いているあいだに ECS Exec が登場しました。Activation を管理しなくてよいので基本はこちらを使ったほうがよいですね。
https://aws.amazon.com/jp/blogs/news/new-using-amazon-ecs-exec-access-your-containers-fargate-ec2/

タグプッシュで環境構築

特定の prefix からはじまる git の tag が GitHub に push されると、環境構築が自動で開始されるようになっています。

  • CodeBuild のビルド開始条件の HEAD_REF を refs/tags/share.+ とする
    • share からはじまるタグがビルドトリガーとなる
  • CodeBuild でコンテナビルド/ECR Push/terraform apply の実行
  • Slack へ完了通知
git tag 'share-INF-1234'
git push origin 'share-INF-1234'

f:id:openwork_engineer:20210326144443p:plain
CodeBuild でビルド開始

f:id:t_ogawa:20210330124649p:plain
環境ができると Slack 通知

ある一定日数経ったら自動破棄

自由に環境構築できる一方、破棄を適切に行わないと結果的にコストがかさみます。
CodeBuild CLI を叩くことにより環境破棄ができるようになってはいますが、場合によっては破棄忘れが起こりえます。そこで環境構築時に「1 週間経ったら環境破棄する CodeBuild を叩く」ような EventBridge を作成するようにしています。
EventBridge の cron を、ちょうど一週間後となるように terraform の timeadd で算出して設定した上で作成しています。

まとめと今後の課題

  • GitHub にタグプッシュするだけで開発用の Web サイトが作成される仕組みを構築
  • 今後の課題
    • コンテナのビルドに時間がかかっている。ビルドキャッシュが最大限に効くように改修が必要
    • IDE からリアルタイムに環境上のソースを編集することができない。EFS などをうまく使えば実現は可能か

なお先日、本番環境でも Web アプリのコンテナ移行を行いました。なかなか手強かったので近々記事にできればと思っています。問題もまだまだあるので、コンテナの課題解決をガンガンやってみたい方はぜひカジュアル面談を。
https://vorkers.jp/recruit/job