Plex JobのバックエンドをHerokuからGCPに移行しました

はじめに

こんにちは、Plex Job開発チームの種井です。

先日公開された、池川さんのブログ「HerokuからGCPへのインフラ移行 〜ダブルライト検証編〜 - PLEX Product Team Blog」でも紹介がありましたが、Plex Jobでは昨年から今年の1月まで約8ヶ月ほどかけてバックエンドのシステムをHerokuからGCP(Google Cloud Platform)に移行しました。 順番は前後しますが、今回は移行に至った経緯や完了するまでの取り組みについて、ざっくりと全体像について、お話しできればと思っております。

インフラ移行に至った経緯

弊社では

  • 使われるかどうかわからない段階での作り込みを避ける
  • 限られた人数でまずはアプリケーションの開発に注力するため

MVP段階のプロダクトに関してはHerokuを使用して運用を行うという方針があります。

Plex Jobはありがたいことに求職者様や企業の採用担当者様をはじめ、社内外の多くの利用者様にお使いいただけるところまで成長しました。 それに伴い、よりバックエンドシステムとしての可用性や堅牢性が求められるフェーズに差し掛かっていること、また以下のような直近の技術的な課題の解消も兼ねてバックエンドシステムをHerokuから移行する運びとなりました。

  • Herokuのリクエスト時間制限
  • バックエンドが物理的に遠い

Herokuのリクエスト時間制限

Herokuにはリクエストの処理を完了するまでにかかる時間が30秒以上かかるとHerokuルーターにより強制的にリクエストが切断される制限が設けられています。 このまま放置すると、Web Dynoはそのまま処理を継続しますが、レスポンスはクライアントに返却されることはないため、アプリケーションサーバー側でタイムアウトさせて処理を中断させることになります。(Plex Jobでは25秒に設定していました)

25秒以上かかるHTTPリクエストにそもそもの問題はありますが、とある要件からどうしても大量のレコードに対して複雑な条件で検索をかける必要のある機能があり、設計やクエリの見直しを行いつつも一旦はタイムアウトまでの時間に余裕を持たせたいという事情がありました。

devcenter.heroku.com

バックエンドが物理的に遠い

HerokuのCommon Runtimeでは、DynoやHeroku PostgreSQLインスタンスを建てられるリージョンはUSもしくはEUに限られます。 利用者や開発者は基本的に日本国内のユーザーを想定しているため

  • ページを表示するまでに必要なデータの取得に時間がかかる(読み込みがもっさりする)
  • 開発者が運用業務で行うデータパッチや集計などに時間がかかる

など、クライアントとデータソースの距離がリージョンをまたいで、物理的に離れていることによるネットワーク起因の課題がありました。 また、ユーザー環境に対してサーバーレスポンスが早くなることで、SEO対策上重要となるサイトの表示パフォーマンスの改善も見込んでいました。

移行までにやったこと

移行までに取り組んだことを簡単にまとめておこうかと思います。 大まかには以下となります。

  • 移行計画と移行先の検討
  • IaC(Infrastructure as code)によるGCP上へのインフラ構築
  • アプリケーションの負債の返却と無停止移行に向けた検証
  • 移行作業に向けた準備

移行計画と移行先の検討

まず最初に移行計画を引きました。 SREとして顧問をしてくれているメンバーが現状の構成と課題に基づいて、移行対象と移行までにすべきことを洗い出してくれました。 移行先の選定を含め、移行にあたってどこから何を決めるべきかが明確になりましたし、途中検証を重ねて計画を変更することになった場合でも想定される作業の見通しを立てることができ、プロジェクト進行中の指針となりました。

移行先のプラットフォーム選定

移行先のプラットフォーム選定に関しては、Plex Jobだけでなく今後全社的に使用を推奨するものとして検討を行いました。 AWSやHeroku Private Spaceなどが選択肢として上がりましたが、元々社内のいくつかのシステムがGCPで運用されていること、また複数のサービスでFirebaseやBigQueryなどをすでに使用していることもあったため、社内で技術スタックを統一する意味合いからGCPを選択することにしました。

なぜGKE Autopilotなのか?

GCPで提供されている各サービスを比較検討を行った上で、移行先のプラットフォームやサービスを決めました。

前提として、移行元であるHeroku環境ではアプリケーションのランタイムはContainer Stackで運用されていたこともあり、あえてVMではなく、Cloud RunやGKE(Google Kubernetes Engine)をはじめとしたサービスを使用するところから検討をはじめました。

その中でも

  • 運用コスト
    • GKE: 社内にk8s(Kubernetes)のクラスタ運用に関する知見がない状態でNodeの管理を行うことは極力避けたい
  • Datadogとの互換性
    • Cloud Run: 計画当時はまだ正式版が公開されていませんでした
  • Terraformとの責務分離
    • Cloud Run: Cronや非同期タスクを実行するためにGCPのSchedulerやTasksのようなサービスを組み合わせて使用する必要があるため構成の管理が分散してしまう
      • k8sの場合、エコシステムにのっかりることで、k8sの構成ファイルで一元管理することができます。開発者がTerraformやGCPのリソースを極力触る必要がなく、なるべくコンテクストスイッチも少なくて済むと考えました。

のような観点から最終的に上記の折衷案として、GKE Autopilotを使用することに決めました。 学習コストが高いとされるk8sですが、Autopilotである分、レクチャーを受けつつ自分たちで段階的にものにしていけるのではないか、やっていくぞというCTO石塚と私の強い意気込みもありました。

IaCによるGCPへのインフラ構築

今回の移行にあたっては、Terraformを使用したIaCの実践と今後プロジェクトが増えることを見越した権限管理の整備も目標としていました。 SREとして顧問をしてくれているメンバーにTerraformによるGCP上へのインフラ構築や権限管理をまるっと実施いただきました。 社内にIaSの実務経験のあるメンバーが不在であることから、Terraform講座を開いていただきつつPR(プルリクエスト)をベースに石塚や私も最低限運用上の構成管理ができるようにインプットを並行して行いました。 現在どのようにIaCによってインフラの構成が管理されているかについては、また別途ブログ記事として紹介したいと思います。

また、並行してk8sに関してもハンズオン形式での講座を開いて頂いたり、参考資料を元に自分達でインプットを行い運用に向けて準備を進めました。

移行に向けた検証と環境変数の整理

移行作業を進める中で、アプリケーションが参照している環境変数が多いことが課題に上がりました。というのも、定数管理で済むような値に関しても無秩序に環境変数として登録されているような状態でした。 今回の移行によってこれまで通りGUIから環境変数を気軽に登録できることはできなくなります。 よりインフラのレイヤーで管理すべきものと、アプリケーションのレイヤーで管理すべきものを分離する必要がありました。 そのため、これまで環境変数として設定されたもののうち、アプリケーション側で管理するもの、インフラ側で管理するものを分類し、アプリケーション側で管理するものに関しては、RailsのCredentials機能やSettings Gemに管理を寄せることにしました。 こちらに関しても記事1つ書ける内容なので、詳細はまた別の機会に紹介したいと思います。

また、移行の計画段階では

  1. 定期バッチの移行
  2. APIおよびWorkerの移行
  3. DBの移行
  4. 新旧DBへのダブルライト期間
  5. 旧DBの切り離し

を想定していましたが、検証によりOff SiteなDB接続のボトルネックが予想以上に大きいことがわかったので、途中で無停止での段階的移行を中止し、メンテナンスを入れる前提で、全てのバックエンドシステムを一度に移行する方法に切り替えることにしました。 これに至るまでの検証に関しては、実施内容が池川さんの記事に詳細が書かれているため、参照いただければと思います。

product.plex.co.jp

移行作業に向けた準備と実施

  • 受け入れテストの仕様書作成
  • 新ステージング環境でのQA
  • メンテナンス機能の作成
  • 移行手順書の作成
  • 移行作業のスケジューリング
  • 当日の実施

を行いました。 特に、ステージング環境でのQAを行う前の段階で、受け入れテストの仕様書を作成して本番環境を想定してテストを実施したことにより、項目のブラッシュアップや当日手順の実施がスムーズになりよかったと感じています。 また、メンテナンス機能については、VercelのEdge Configを活用することで比較的簡単に用意することができたので、こちらも別の機会で紹介できればと思います。

vercel.com

リリース後、トラフィックの多い時間帯に一部のPodがリソース不足で動作が不安定になるといった問題はあったものの、特に大きな問題もなく新しい環境で運用を開始することができました。

移行後、運用が開発チームに浸透するまでに実施した内容についても別途運用編としてご紹介できればと思います。

移行を終えて

移行を終えて以下のような構成となりました。

簡略版構成図

移行の経緯に上げた課題についてですが

  • 可用性や堅牢性の向上
    • 求人サイトの突発的なリクエスト増加にも停止時間が発生することがなくなるなど可用性の向上が見られた
    • 以前と比較してセキュリティ上の細かい要件に対応することができるようになった
  • Herokuのリクエスト時間制限
    • リクエスト時間の緩和を行うことができた
  • バックエンドが物理的に遠い
    • データパッチや集計にかかる時間が削減できた

などの効果を実感することができています。

また、現在はインフラにかかるコストの最適化や監視、可観測性の担保です。 コスト最適化の文脈でアプリケーションのパフォーマンス・チューニングにも積極的に取り組んでいきたいと考えております。

おわりに

今回、Plex Jobのインフラ移行についてざっくりではありますが、全体像をお話させていただきました。 記事中でもいくつか紹介しましたが、取り組んだ一つ一つの内容はそれぞれ1つの記事として公開できそうなものも多いため、関連記事として連載していきたいと思います。

Plex Jobだけでもコスト最適化、監視、可観測性などをはじめとした課題がありつつ、他事業部のプロダクトもGCPへのインフラ移行を控えていたりします。 このような課題にチャレンジしていただけるSREをはじめ、ソフトウェアエンジニアフロントエンドエンジニアを募集しています。

dev.plex.co.jp

少しでも興味を持っていただけた方は業務委託や副業からでも、ぜひご応募いただけると幸いです。