【インターン参加記】GitHub Actions Self-Hosted Runnerによる負荷試験環境構築の自動化

こんにちは、尾上寛弥です。この1ヶ月間 RECRUIT Internship for Engineers, Data Specialists 2023 に参加し、『スタディサプリENGLISH』のSREチームで働いていました。

今回は自分が取り組んだ、GitHub Actions Self-Hosted Runnerによる負荷試験環境構築の自動化について、インターン中の体験も含めて紹介します。

背景

『スタディサプリENGLISH』では新機能を追加する際などに必要に応じて負荷試験を実施しています。想定されるアクセスを見積もった上で負荷試験を実施することによって、実際に大量のアクセスがあった際に不具合が生じるリスクを減らしたり、必要なリソース量を計測してコストを削減したりすることができます。

『スタディサプリENGLISH』では本番環境やステージング環境のほかに、開発やQAに用いるための開発環境があらかじめ複数用意されています。負荷試験は開発環境のうちの一つを利用し、DBを試験専用のものに入れ替えて実施します1)DB以外の性能が開発環境相当であるという問題は今後の課題です。。またそれぞれのリソースはKubernetesやTerraformによって管理されており、Pull Requestベースで変更を反映できるGitOpsで運用しています。

今までは負荷試験を実施するために、以下の事前準備を手作業で実施する必要がありました。

  • 負荷試験DBの準備
  • 全マイクロサービス・Jobの接続先DBを負荷試験用のものに変更
  • 負荷試験を実行するPodの作成

一連の作業は特にKubernetesやTerraformといった技術に詳しくないアプリケーション開発者にとっては難しい作業となっていました。またDBに接続するマイクロサービスやJobはたくさん存在するため、接続先DB変更の取りこぼしが発生する可能性がありました2)RDSクラスタとしては一つですが、マイクロサービスごとに使用するデータベースが分離されています。。さらに負荷試験終了後にはこれらの変更を元に戻し、DBなどで無駄なコストが発生することを防ぐ必要がありました。

こういった手間のかかる複雑な作業なしにほぼ自動で負荷試験を実行できるようにすれば、アプリケーション開発者はもっと簡単に負荷試験を実施することが可能になります。

やったこと

いくつかのパラメータを指定すれば環境構築・試験実施・結果通知までほぼ自動で実行してくれるGitHub Actions Workflowを実装しました。

overview

アプリケーション開発者から見た負荷試験実施の流れは以下となります。

  1. 試験シナリオを実装
  2. 試験用DBを作成するWorkflowを実行→変更をmerge
  3. 全マイクロサービスの接続先DBを試験用DBに変更するWorkflowを実行→変更をmerge
  4. 試験実施Workflowを実行
  5. Slackに通知されたS3のURLから試験結果レポートを閲覧
  6. 2,3の変更をRevert(期限を超えるとSlackでアラート)

社内別プロダクトでも似た仕組みが用意されているため、 スタディサプリProduct Team BlogのGitHub Actions Self-hosted Runner と Gatling による負荷試験 もご覧ください。

それぞれの流れについて以下で詳しく説明します。

試験シナリオ実装

開発者はまずGatlingを用いて負荷試験用のシナリオを所定のレポジトリで実装します。

GatlingはScalaで試験シナリオを書くことができる負荷試験ツールで、リッチなUIを持つ結果レポートを提供してくれます。負荷試験ツールは他にもK6, Locust, Apache JMeter/Benchなどがありますが以下の理由からGatlingを選択しています。

  • 今までの負荷試験で採用実績がある
  • アプリケーションと同様にScalaで書けるので馴染みやすい

なお他のツールを利用したい場合は、負荷試験実施Workflowをツールごとに用意することで対応可能です。

DB作成

次に負荷試験専用のDBを作成します。DB作成Workflowは、以下のパラメータを元にRDS等のAWSリソースを追加するPull Requestを作成します。

  • RDSクラスタ名
  • スナップショット名
  • インスタンスクラス
  • MySQLバージョン
  • 削除通知日(後述)

負荷試験用DBに関連するTerraformリソースはモジュール化されているため、モジュールのコードを生成するだけで必要なリソースを作成できます。

意図しない変更を防ぐため、Workflowが作成したPull RequestをSREがレビューしたのちapplyとmergeをします。

接続先DB変更

さらに全てのマイクロサービスやJobの接続先DBを新しく作成したDBへ変更します。接続先DB変更Workflowは、以下のパラメータを元にPodが使用するDBの接続先・ユーザー名・パスワードを変更するPull Requestを作成します。

  • RDSクラスタ名
  • 変更する環境
  • DBのユーザー名・パスワードを格納したAWS Secrets ManagerのSecret名

WorkflowはDB接続先を置き換えます。まずはmanifestから現状のDB接続先を取得します。DB接続先は全てのマイクロサービスで同じ形式の環境変数を用いて設定しているため、機械的に取得することができます。次にDeployment, Job, CronJobの一覧を取得します。そしてそれぞれについて、DB接続先を指定したRDSクラスタのものに置き換えます。

さらにDBのユーザー名・パスワードも置き換えます。これらの値はAWS Secrets Managerによって管理されており、KubernetesクラスタからはExternalSecretを用いて参照されています。まずmanifestからDBのユーザー名・パスワードを設定しているExternalSecretの一覧を取得します。そしてそれぞれについて、Secret名を指定したものに置き換えます。

以上の処理をシェルスクリプトで実装しました。manifestから値を取得する処理はKustomizeやgrep、yqを利用しており、値を置換する処理はKustomizeのpatchを当てることで実現しています。

DB作成と同様に、Workflowが作成したPull RequestをSREがレビューしたのちmergeします。

試験実行・結果通知

そして負荷試験を実行します。試験実行Workflowは、以下のパラメータを元に負荷試験を実施して結果をSlackに通知します。

  • 試験シナリオのクラス名
  • 環境変数を記述したファイルのパス
  • 実行するRunner

『スタディサプリENGLISH』では、KubernetesクラスタにデプロイされたGitHub Actions Self-Hosted Runnerを利用しています。異なる性能のRunnerをいくつか用意しているため、選択されたRunner上で環境変数を読み込んでGatlingを実行します。

Gatlingを実行するとHTMLの結果レポートが生成されるため、それをS3にアップロードします。その後Slackに結果レポートをダウンロードするためのコマンドが通知され、開発者はそのコマンドで結果レポートをダウンロードして閲覧することができます。

notify-result
results

試験DB削除を促すアラート

試験終了後は、マイクロサービスやJobが接続するDBを戻した上でDBを削除する必要があります。特に本番相当のDBを試験に使用している場合は、削除し忘れるとかなりの無駄なコストが発生します。

そこで前述の通りDB作成Workflowで削除期限日を指定し、この期限を超えるとSlackに通知するようにしています。

notify-deletion

削除期限日はTerraformのコードにコメントとして書かれており、平日に毎日実行されるWorkflowがこのコメントを見て期限を判断して通知します。期限日を伸ばしたい場合は開発者がコメントを書き換えることで対応します。

今後の改善

今回は時間の都合上取り組めませんでしたが、試験実施・結果分析をよりやりやすくするための改善点として以下のものがあります。

  • DB作成Workflowと接続先DB変更Workflowをまとめる
  • CloudFront等を用いてS3を社内に静的ホスティングし、URLから簡単に試験結果レポートを見られるようにする
  • Gatling以外の負荷試験ツールも容易に使えるようにする

また他にはマイクロサービスやPodの性能が開発環境相当のままであるという課題があります。指定した性能の環境作成も併せて自動化できれば、より適切に必要な性能を計測できます。

インターン中の体験

オフィス

基本的にリモート勤務でしたが、期間の3分の1ほどは交通費とホテルを手配していただいて東京のオフィスに出勤しました。チームメンバーがいる九段下オフィスで主に勤務し、必要に応じて本社のグラントウキョウサウスタワーにも行きました。九段下オフィスは最近新しくできたオフィスで、少し変わった建物ですが綺麗で快適です。(九段下オフィスについて詳しくはこちら)

東京にいる間は社員さんや他のインターン生とランチや懇親会でたくさん交流できました。

RECRUIT ISUCON

インターン期間中にちょうど社内ISUCON(RECRUIT ISUCON) が開催されました。 3) 「ISUCON」はLINE株式会社の商標または登録商標です   

もともとISUCONに興味があり過去問を解いたりしていたので、他のインターン生を誘って3人チームで出場しました。

結果は40チーム中5位で入賞しました。全員ISUCON初参加でしたが、一日楽しく開発できた上に想像以上の好成績を残せて大満足です。

まとめ

GitHub Actions Self-Hosted Runnerを使って、Kubernetes上で負荷試験を実行する環境構築の自動化について解説しました。今回のインターンを通じて業務や技術、リクルートについてたくさんのことを学べ、とても充実した1ヶ月を過ごせました。

学生の皆さんはぜひリクルートのインターンをチェックしてみてください。
https://www.recruit.co.jp/employment/students/engineers/event/

脚注

脚注
1 DB以外の性能が開発環境相当であるという問題は今後の課題です。
2 RDSクラスタとしては一つですが、マイクロサービスごとに使用するデータベースが分離されています。
3  「ISUCON」はLINE株式会社の商標または登録商標です