サーバーサイドのリリースフローを改善したはなし

はじめに

ソフトウェアエンジニアの浦川です。
クラスターでは毎週のようにサービスへの機能追加や改善をおこなっています。合わせて、どのようにリリースしていくか、の改善も日々おこなわれています。この記事では、サーバーチームのリリースフロー改善の取り組みについて紹介できればと思います。

clusterの開発とリリースフロー

clusterには、AWSアカウントごと分離された開発環境(DEV)/ステージング環境(STG)/本番環境(PRD)という3つの環境が存在します。
ふだんはDEVで開発をおこない、リリースの際にはSTGで動作を確認、問題なければPRDへリリース、というのが基本的なリリースフローの流れです。

ソースコードはGitHub、開発タスクはJiraで管理されており、リリースフローのなかで関連するプルリクエストやチケットを集約したりステータスを更新するなど、リリースに伴う管理作業のようなものも発生します。

改善前のリリースフロー:部分最適化はされているが、全体最適化は......

サーバーチームではリリースを毎日おこなっているのですが、フローが必要以上に複雑化していることに課題を感じていました。

当時のリリースフロー (灰色の吹き出しが概ね手作業)

リリースをおこなうためのSlackのワークフローがあり、作業自体に難しいものはありません。個々の作業はスクリプト化されているものが多く指示に従って実行するだけではあるのですが、作業に必要なツール類は個々人のPCにインストールしてもらう必要がありました。
そのため、いざリリースをおこなおうとすると、初回はまずセットアップをして...ということになり、セットアップがうまくいかずサポートが必要...なケースもあったり、ローカル環境の変化で動かなくなってた...ということもあったりと、なかなかスムーズにおこなうことができず、結果として慣れた人以外が手を付けにくい状態でした。

もともとリリースフローはサーバーエンジニアが数名の時期に構築されたものをベースに、その時々で足りないステップを継ぎ足しながら運用されてきたものです。そのため、単一ステップの自動化はこまめにおこなわれる一方で、全体を通しての最適化(自動化)はされていませんでした。

また、リリースを毎日おこなうことで、サービスの機能追加や改善をなるべく早くユーザーに届けられる一方で、cluster自体の多機能化、複雑化によりSTGでの動作確認が不十分なままリリースされてしまうことがありました。そこで、リリースフローの1ステップとして「QAチームによるSTGでの動作確認」が追加されました。
QAチームのチェックが入ることでリリースへの安心感は高まりましたが、リリースフローの複雑さと全体の所要時間は大きく増加することになりました。

QAチームによるチェックが入ったリリースフロー

リリースフローの改善方針

clusterは夕方〜夜中にかけて利用ユーザー数が増加します。あまり遅い時間にリリースをおこなうと、何かトラブルがあったときに対応できるエンジニアが退勤してしまっている、ということがありえます。なるべく日中にリリースをおこなえるのが望ましいですが、リリースフローが長時間化したことにより一日で終わらせるのは難しくなりました。
そこでリリースフローを2分割し、1日目にステージング環境の更新〜QAチェック、2日目の日中に本番環境へのリリースをおこなう、というフローとしました。

これはこれで一定の改善はあったのですが、1回のリリースが2日にまたがるため、担当者が有耶無耶になってしまったり、リリースフローにさらにステップが増えてしまうという弊害もありました。

リリースフローの複雑化/長時間化の最大の要因は、毎リリースにQAチームによるチェック(client appの動作確認を含む)を実施していた点で、まずはそこを解消し、そのうえでリリースフロー全体の最適化(ステップの統廃合等)をおこなうということにしました。

動作確認が難しい「バーチャル空間内の体験」のE2Eテストを開発

サーバーリリースごとにQAチームのチェックをおこなうようになった背景としては、clusterは一人〜数人程度では"ちゃんと"動作確認するのは難しいことがあげられます。とくにinroom(バーチャル空間内)の体験に関わる部分は、実際に下記のような問題が発生したことがありました。

  • 同じイベントに参加している他者のアバターが表示されない場合がある
  • 権限(スタッフやゲスト)の変更が反映されない場合がある
  • 本来必要ない通信が発生していてサーバーが過負荷状態に陥っている
  • etc...

こういった開発者だけで動作確認するのは難しい事象も、QAチームによるチェックによりある程度は検知可能になりました。しかし、これらをclusterのアプリ上でおこなうのは手間もかかりますし、実際に問題が検知されたときはサーバー側の問題なのかクライアント側の問題なのかの切り分けから行う必要があり、サーバーリリースをおこなうためにUnityエンジニアの調査を待たなければいけない、ということも常態化していました。

そこで、クライアントの接続をエミュレーションし、実際のサーバーインフラを利用して通信内容をチェックする専用のテスト(E2Eテスト)を開発しました。通信内容を直接検証するためclient appの挙動の影響は受けにくく、安定した検証をおこなえるようになっています。

feature flagの自動テストを増やす

もう1つ難しいのがfeature flagの運用に起因する部分です。クラスターではfeature flagを利用して機能開発しており、開発の進行によってflag状態が変化していきます。

  1. 開発スタート直後 DEV=true, STG=false, PRD=false
  2. エピックのQA中 DEV=true, STG=true, PRD=false
  3. リリースready DEV=true, STG=true, PRD=true

とくに既存機能の改修においては、flagがfalseの場合(既存の挙動の維持)をちゃんと考慮しておく必要があります。これをSTGで検証しようとすると、flagがtrue/falseそれぞれの状態で同じテストを実施することになってしまいます。

幸いクラスターのサーバーサイドにはテストコードが大量にあり、それを活かすことを考えました。基本的にCIではDEV環境相当のflag設定で検証がおこなわれていたのですが、flagだけをPRD環境の設定におきかえたCIを追加し、どちらの状態でもテストをおこなうようにしました。

こういった自動テストを増やしていった結果、サーバーリリースの際に検知される問題のほとんどがclient app起因のものや、テスト実施者の通信環境によるものだということが分かりました。

AWS CodePipelineでリリースフロー自体を最適化する

自動テストが増えてきたことで、サーバーリリースごとのQAチームのチェックは廃止できる見込みがたちました。そこで、もう1つの課題であった、リリースフロー自体の最適化に取り組みました。

すでにSlackのworkflowとして手順はある程度定まっていたこともあり、いくつかコマンド実行順序や実行権限を考えるのみで、最終的にはAWS CodePipelineを利用したものになりました。

リリースフローのなかで手作業でおこなう部分はリリース前の動作チェックだけになりました。

これまでのSlackのworkflowでの作業指示だったものがCodePipelineにより自動化され各自のローカル環境への依存はなくなったことで、安定したリリースをおこなえるようになりました。
ポイントは、プルリクエストのマージを「リリース承認」とみなして、GitHubからのイベントを受けとってApproval Stepを進めるようにしたところで、これによってCodePipelineの存在は完全に意識しなくてよくなっています。

リリースフローの改善結果:サーバーリリース所要時間をほぼ1日→2〜3時間程度に/ツールのセットアップ等のサポートが不要に

「動作確認が難しい「バーチャル空間内の体験」をE2Eテストを開発」「feature flagの自動テストを増やす」によって、1回のサーバーリリースの所要時間をほぼ1日から2〜3時間程度にまで短縮できました。また、「AWS CodePipelineでリリースフロー自体を最適化する」により事前準備等もいらなくなったことで、ツールのセットアップ等に関するサポート等も不要になりました。

今後の課題としては、簡単におこなえるようになったとはいえリリース担当者が特定の人に偏ってしまっていること、自動化したものがうまく動作しなかったときにどうなるのか? の知見が足りていないこと、が挙げられます。

このあたりについては、今後運用していくなかでうまく担当者を割り振る仕組みを整備したり、トラブル対応ドキュメントを作る/自動復旧可能なようフローを修正する、などで対応していきたいと考えています。

まとめ

クラスターのサーバーチームにおける、リリースフローに関する改善の取り組みについてご紹介しました。

リリースフローは変更による影響範囲が大きいため、いったん運用が安定してしまうと根本的な修正をおこなうことは難しく、加えてサービスの機能とも直接関連しないため、改善するにしても細かい局所的な改善を重ねがちです。
今回はそういった細かい改善を加えるだけではどうにもならん! ということで時間を取って根本的な改善をおこないました。
結果的にはCodePipelineという新しい仕組みを導入したものの、日々の運用ではまったく意識しなくて済むようになっており、今後のさらなる改善の土台を作ることができたと思います。

今回の話のように「一見地味だけど裏では実は...」みたいな改善が好きな方もそうでない方も、ご興味がありましたら是非ご応募ください。

recruit.cluster.mu