バイセル Tech Blog

バイセル Tech Blogは株式会社BuySell Technologiesのエンジニア達が知見・発見を共有する技術ブログです。

ヘッダー画像

リリース頻度を上げるためにDevOpsとしてやった4つの取り組み

はじめに

こちらは バイセルテクノロジーズ Advent Calendar 2022 の 7 日目の記事です。前日の記事は柴田さんの「ast(抽象構文木)でgoの構造体の定義を検証するツールを作った話」でした。

こんにちは。バイセルテクノロジーズ テクノロジー戦略本部 開発 1 部のDevOps担当の市田です。 弊社では買取管理システムGYROというサービスを開発・運用しています。この記事ではGYROでのリリース頻度を上げるためにやったことを紹介します。

背景

GYROでは定期リリースを行っており2週間に1度の頻度でリリースをしていました。 しかし、2週間に1度のリリースではユーザーへの価値提供が遅れてしまうので頻度を上げたいと考えていました。 定期リリースになっている理由はリリース作業に時間がかかっており、頻繁に作業すると大変だからということでした。 そこでリリース作業を高速化することで作業負担を軽くしてリリース頻度を上げることに取り組みました。

以下はGYROのリリースの流れです。

  1. Slackからリリースコマンドでリリース対象リポジトリを指定して実行
  2. Cloud Functionsが呼ばれてtagをつけてリリース対象リポジトリ(GYROはマイクロサービス)へpublish
  3. tagのpublishをCloud Buildが検知しDocker ImageをbuildしてContainer Registryへpush
  4. Container RegistryへのpushをSpinnakerが検知しデプロイ実行

リリースフロー

作業者にとって負担の大きい作業の聞きこみや、CI/CDの中で時間がかかっている箇所を調査した結果、以下がリリース作業のボトルネックであることが判明したため改善することにしました。

  • Spinnakerでのデプロイに時間がかかっている
  • Spinnakerでのデプロイが実行される前のCloud Buildで時間がかかっている
  • リリースコマンド実行だけではリリースが開始されず、追加の作業が必要になっている
  • ユーザー数が少なくなる夜までリリース作業が始められない

取り組んだこと

Spinnakerによるデプロイの高速化

GYROで最もデプロイに時間がかかっているリポジトリではデプロイに1時間12分かかっていました。 原因はSpinnakerのバージョン1.22.6が生んだバグでした。そこでバージョンを1.23.7に上げることで高速になり、5~10分という約1/12の時間でデプロイが終わるようになりました。 バグの内容は、デプロイの1stepごとにForce Cache RefreshというTaskが毎回実行されており、それに常に12分かかっていたことです。 GYROの一番遅いリポジトリではデプロイに6step存在しているので、12 * 6 = 72分(1時間12分)かかっていました。

参考

リリース時のCloud Build高速化

リリースフロー

リリースは上記の図のようにtagをpublishすることで動きます。 そのリリースの流れの中でCloud BuildのCIが動いてDocker Imageのbuildを行いContainer Registryにpushします。 以前は、CIでlintのチェック(Rubocop)・脆弱性のチェック(Brakeman)・テスト実行(RSpec)が実行されていました。 tagのpublishではコードは変わらないのでこれらは不要であり削除することで、一番遅いリポジトリではリリース時のCIが15分 → 5分になりました。

リリース作業の自動化の拡張

リリース作業の一番初めはSlackのコマンドを実行します。Slackのコマンドを実行するとdraftのtagが作られてそのtagのリンクがSlackに表示されます。そのリンクを開いてpublishすることでリリースが動きます。 GYROはマイクロサービスなので複数リポジトリをリリースするときはリポジトリの分だけその作業をする必要があり時間がかかっていました。 そこでtagをdraftで作らず直接publishするように修正しました。

リリースコマンド

tagの作成はSlackコマンドからCloud Functionsを呼び出し、その中でGitHub Releases API(POST /repos/{owner}/{repo}/releases)を実行することで実現していました。そのため、リクエストボディのパラメータのうちの1つで、tagをdraftで発行するかどうかを制御していた「draft」をtrueではなくfalseにして送るようにすることで、手動でtagをpublishをする工程を省くことができました。その結果、Slackコマンドを実行するだけでリリースできるようになり、リリース作業にかかる時間を数分削減できました。

リリース時間を夜から日中に変更

また、技術的な修正は行なっていないのですがリリース時間の変更もしました。 今までは、リリースに漠然とした不安がありユーザーが少なくなった夜(21時以降)にリリースを行っていました。 21時にリリースを開始する予定を立てていたのですが、ユーザーの作業が長引いたときは作業が終わるまで待ってからリリースを行っていたので22時台にリリース開始する時もありました。 そこでリリースについて話し合い、データベースのmigrationの修正がない場合は業務時間内にリリースするように変更しました。 よって、migrationの修正がない場合は夜まで待機する必要もユーザーの作業が終わるまで待つ必要も無くなり、リリース完了までの待機時間が大幅に短くなりました。

まとめ

上記の変更により、1回あたりのリリースまでの時間を約4時間削減することができました。 結果として、リリース作業時間の短縮やリリース時間の前倒しによってリリース作業の負担が減り2週間に1度の定期リリースではなくリリース可能になったら随時リリースする運用に変えることができ、実際に1週間に2回のリリースをすることができました。

リリース頻度

Before After 比較
1回あたりのリリース作業時間 90分 15分 83%短縮
2週間あたりのリリース頻度 2回 4回 200%に増加

また、今回のリリース頻度を上げるための作業でSpinnakerやCloud Functionsなど普段触らない技術を触ることができました。 リリース頻度を上げることで結果も出せますし、技術力の向上にもつながるのでぜひ真似してみてください。

おわりに

今回のように少しの修正で作業を高速化できることはよくあります。 tagを使ってデプロイをしているプロダクトでは同じようなCI高速化やGitHub Releases APIを用いた自動化ができないか検討したり、Spinnakerの同じバグが発生しているプロダクトでは参考にしてアップグレードしてみたりするなど、自分のプロダクトで改善できるところがないか確認してみてください。また、ユーザー数が少ない夜に何となくリリース時間を設定しているプロダクトもあると思いますが、本当に夜でないといけないのか再検討して日中にリリースでいいとなるとかなり作業負担が減るので検討の価値は大いにあると思います。

最後にBuySell Technologiesではエンジニアを募集しています。興味がある方はぜひご応募ください。

hrmos.co

明日の バイセルテクノロジーズ Advent Calendar 2022 は藤井さんによるWebComponentで始めるUIコンポーネントの共通化です。そちらもぜひ併せて読んでみてください。