こんにちは、普段PRTIMES STORY(以下STORY)の開発リーダーをしている岩下(@iwashi623)です。
以前ECSのマルチステージング環境を設計・実装した記事を書きました。

こちらのマルチステージング環境をSTORYに導入したおかげで、開発フローのボトルネックが解消され、大きいプロジェクトが進行している期間にも小さな変更をステージング環境でQA→リリースできるようになりました。
ところが、こちらのプロジェクトを進行中に、実装したマルチステージング環境では太刀打ちできない問題が見つかりました。CloudFrontの設定によって、PR TIMESに導入されていたマルチステージングとの噛み合わせが悪くなっていたのです。
本記事ではステージング環境のCloudFrontディストリビューションを分割して、複数のアプリケーションのマルチステージング環境を連携させた背景と方法について述べていきたいと思います。
前提
発生した問題について述べる前に、PR TIMESとSTORYのマルチステージング環境について簡単に説明します。
STORYのマルチステージング(ECS)
以前紹介したマルチステージングのざっくりとした概要は以下です。
- 通常ステージング環境ドメインは
story-dev.example.com
である。 - 開発者は個人のステージング環境
hoge.story-dev.example.com
というサブドメインを作成して使用する。 - 前もって
hoge.story-dev.example.com
のためのALBのリスナールールやターゲットグループを作成しておく。 - GitHub Actionsを使用して、任意のタイミングで
hoge.story-dev.example.com
に対応するECSサービス・タスクを作成する。

上記の設定をすると、ALBに直接来たリクエストを、ALBのホストベースのルーティングを使ってそれぞれのECSへとルーティングするといったものでした。
PR TIMESで既に動作してたマルチステージング(EC2)
PRTIMES STORYとは別に、PR TIMESのステージング環境ではApacheのVirtualDocumentRoot
を使用したマルチステージング環境が運用されていました。

PR TIMESのマルチステージングの概要は以下です。
example.com
という通常のステージングドメインと環境が存在する。hoge.example.com
という環境でhogeさんがデプロイしたアプリケーションを実行できる。- リクエストは通常のステージングと同じ経路(CloudFront→ALB)をたどって、通常のステージングと同じEC2へ到達する。
- リクエストのドメインに応じて、ドメインと同じ名前のディレクトリにあるアプリケーションコードが実行される。
既存マルチステージング環境の問題が発覚したプロジェクト概要
ざっくり説明すると、PR TIMESのサーバーで動作しているアプリケーションの一部となっていたSTORYのコードを、STORYサーバーのアプリケーションに移植させるといったものです。

移植前
ドメイン | prtimes.jp | prtimes.jp/story | admin-story.prtime.jp |
対応サーバー | PR TIMESサーバー | PR TIMESサーバー | STORYサーバー |

移植後
ドメイン | prtimes.jp | prtimes.jp/story | admin-story.prtime.jp |
対応サーバー | PR TIMESサーバー | STORYサーバー | STORYサーバー |

発生した問題
以下はPR TIMESとSTORYのステージング環境で使用しているドメインとサーバーの対応表です。
1 | 2 | 3 | 4 | 5 | 6 | |
ドメイン(+ パス) | example.com | example.com/story | hoge.example.com | hoge.example.com/story | story-dev.example.com | hoge.story-dev.example.com |
環境 | PR TIMES 通常ステージング | PR TIMES 通常ステージング | PR TIMES マルチステージング | PR TIMES マルチステージング | STORY 通常ステージング | PR TIMES マルチステージング |
対応サーバー | PR TIMES サーバー(ALB/EC2) | PR TIMES サーバー(ALB/EC2) | PR TIMES サーバー(ALB/EC2) | PR TIMES サーバー(ALB/EC2) | STORY 通常ステージングALB/ECS | STORY マルチステージングALB/ECS |

移植のプロジェクトの目標は、PR TIMESのドメイン(本番ならprtime.jp
、ステージングならexample.com
)の/story
というパスへのリクエストをSTORYのALB・ECSで処理することです。対応表でいうと2と4のリクエストをSTORYのALBに向けたいです。
それをステージング環境で検証するためにCloudFrontのパスベースのルーティングを使用して、/story
のOriginをSTORYのALBにしようとしました。ここで問題に遭遇します。
CloudFrontにはホストベースのルーティング機能が存在しません。
そのため、同じディストリビューション内で通常ステージングとマルチステージングのリクエストを捌いていると、/story
のパスにリクエストが来た際、通常ステージングかマルチステージングのどちらかしかOriginとして選択できないということに気が付きました。

期待する挙動
せっかく個人が自由なサブドメインをPR TIMES、STORY両方で発行して各々のステージング環境にデプロイできる環境があるので、PR TIMESとSTORYのマルチステージングを連携したいなという気持ちになりました。
具体的には、hoge
というサブドメインでSTORYのマルチステージングをデプロイをしたら、PR TIMESと連携する際はhoge.example.com
というステージング環境と連携するなどのようにして、同じサブドメインの2つのアプリケーションをつなぎ合わせるイメージです。

理由としては、PR TIMESとSTORYに同時に変更を入れる必要があるプロジェクト(今回の様なプロジェクト)が始まった時にマルチステージング同士が通信できれば、通常ステージングにデプロイする必要がなくなり個人のサブドメイン環境で完結できるためです。
変更点
上記の期待する挙動を叶えるために、マルチステージングのアプリケーション側、インフラ側にそれぞれ少し変更を加えました。
アプリ側
STORYは環境変数でPR TIMESのAPIを叩くために使用するPR TIMESドメインを保持しています。こちらはステージング環境であれば.env.staging
ファイルにハードコーディングされているexample.com
というドメインです。この環境変数をアプリケーションデプロイ時にhoge.example.com
などに書き換える事ができれば、任意の環境のPR TIMESマルチステージングにAPIリクエストを飛ばせるようになります。
sed -i -e "s/PRTIMES_URL=https:\\/\\/example.com/PRTIMES_URL=https:\\/\\/${SUBDOMAIN}.example.com/g" .env.staging
こんな感じの力技で、PRTIMES_URL
という環境変数をGitHub Actionsの中で書き換えました。
こちら変更が反映されたアプリケーションコードをImageに固めてECSにデプロイすることで、ECSが連携するPR TIMESのステージング環境のドメインを変更しました。
インフラ側
CloudFrontがホストベースのルーティングができないため、どうにかならないかな〜と思っていたのですが、そもそも同じディストリビューションでリクエストを捌く必要がないのでは?と気づきました。
通常ステージングのドメインとマルチステージング用のワイルドカードのサブドメインを別々のディストリビューションに分割してしまえば、ホストごとのルーティングを考える必要がなくなります。
また、Lambda@Edgeを使うと別々のホストに対して別々のOriginを指定できるようなのですが、料金的にもメリットがないし管理が複雑になると思ったので見送りました。
やったことは以下です。
- マルチステージング用に新規のCloudFrontディストリビューションを作成
- 通常のディストリビューションとマルチステージングのディストリビューションをそれぞれ指すRoute53のレコード作成
- 通常ステージングのディストリビューションの
/story
のオリジンを通常ステージングのALBとする - マルチステージングのディストリビューションの
/story
のオリジンをマルチステージングのALBとする

こうすることで、hoge.example.com/story
のようなリクエストはSTORYのマルチステージングALBへと流れていき、ALBのホストベースのルーティングを使用してhoge用のECSへと到達するようになります。
新規のディストリビューションを作成する時に設定がIaC化されていたおかげで、ほぼコピペコードをterraform apply
するだけで作成できました(ホント便利)。
まとめ
別々のアプリケーションのマルチステージングを、上記のような方法で連携することで、移植のプロジェクトもサクサクとQA→リリースの流れを作ることができました。
上記の仕組みは先日リリースされたPR TIMES Webクリッピングβ版でも導入されており、弊社のECS環境での開発速度を向上しつつあります。
AWSを使った開発環境の構築・改善に興味がある方はぜひ下記のフォームからカジュアル面談などを申し込んでいただけると幸いです。