読者です 読者をやめる 読者になる 読者になる

Mercari Engineering Blog

We're the engineers behind Mercari. Check out our blog to see the tech that powers our marketplace.

大人のスタートアップは大人のリリースができる。そう、ChatOpsならね。

このブログをご覧のみなさま初めまして。@siroken3です。メルカリではインフラチームに所属しており、リリースの仕組み構築を担当しています。

メルカリのリリースについて

メルカリではカスタマーサポートから受け取る改善要望、プロダクトとしてまだやれてないことなど多くのタスクがあり現在も継続して開発とリリースが行われています。

Issue管理はRedmine、ソースコードのリポジトリはGitHub privateを使用しています。Pull Request(以下PR)でのコードレビューを実施、masterブランチへマージされたものをリリースするのが基本的なフローです。

一方、1年前まではリリース頻度は週1回のリリース日を決めて実施していましたが、この1年で大きく変わりました。現在では日本版とUS版を合わせて10回〜30回/日の頻度でリリースしています。この記事では大きく変わったメルカリのリリースフローの歴史をご紹介したいと思います。

週1リリース時代

約1年前は週に1回リリースする曜日が決まっており、リリース前のコードフリーズ、QA担当でのチェックを経て前回から1週間分に完了したIssue全てまとめてリリースするフローをとっていました。それ以外の緊急を要する事案は「緊急リリース」であり、リリース日以外にも実行可能としていました。

しかし、会社のメンバーが増えてくるにつれて開発、企画者が増えたので実現可能な仕様が増え、さらに他社との連携事案が増えてきたことにより以下の課題がでてきました。

  • チェックすべき仕様が多すぎてリリース前QAにかける時間が足りない
  • 各種事情で次回リリース日まで待ちきれず緊急リリース頻発

無理やりQAを間に合わせるのは大人のスタートアップを標榜する私達としてはよろしくない状態です。余裕をもって運用し、かつ高いサービス品質を実現したいところです。 quest.job-q.me

ちなみに当時のリリース方法は担当者がデプロイサーバにsshログイン、Githubから取得したソースを rsync で全サーバにデプロイというオーソドックスな方法*1です。

方針転換

1度に確認する仕様が多すぎるなら分割しよう!ということでIssue毎にリリースしてもよいことにしました。そして次回リリース日まで待ちきれない問題は毎日リリースすることで解消しよう!になりました。(ただし休前日は避けるようにしています)。しかし、リリースに求められる要求が増えてきました。

  • カスタマーサポートチームにいつどんな機能がリリースされるか周知しておく必要がある
  • 大人の事情で、限られたデプロイ担当メンバーしか本番サーバにログインできなくなった
  • レビュー済みのPRであることを示すために LGTM ラベルをつける
  • プロジェクトマネージャにRedmineのIssueのステータスをリリースOKにしてもらわないと原則リリースできない
  • 担当した開発者はリリース時に立ち会って動作確認する必要がある

これらの要求を満たすため、新たにリリース運用を開発しました。具体的には以下のような運用となりました。

  1. 開発担当がホワイトボードにリリースしたい時間帯に対応するIssue番号を書いた付箋を貼って予約
  2. 各時間帯でデプロイ担当がIssueのステータスを確認
  3. デプロイ担当は担当開発が在席していることをSlackで確認してデプロイサーバからplaybookを叩く

当時使用していたホワイトボードの写真がこちらです。

f:id:siroken3:20151014165647j:plain

これで1日に最大10回程度のリリースが可能になりました。しかし、依然課題が残りました。

  • USオフィスのメンバーがリリース内容をすぐに知ることができない
  • 「あるIssueをいつリリースしたか」の追跡調査しにくい
  • リリース担当ぐったり

そしてChatOps

特に3番目の課題は深刻です。そこでSlackが提供しているBot Integration機能とGoogle カレンダーを使用して ChatOps 環境を構築しました。ChatOps自体に関する解説は他のサイトにお譲りする*2ことにします(!?)。

さて、メルカリでリリースの仕事をするBotはGoBold(ごーぼーるど)さんと呼ばれています。Botの開発といえばHUBOTがよく使用されますが、当時Slackと連携するためのadapterである hubot-slack がSlackとの通信にGlobal IPを必要としているので見送りました。

その代わりSlackのReal Time Messaging APIを採用してSlackからのメッセージをWebSocketで受信する方式を採用しました*3。開発はnode.jsを使っており、メルカリ内製のRedmine連携ライブラリ、Google カレンダーとの連携にgoogleapisを使用しています。このGoBoldさんは以下の仕事をします。

  • Google カレンダーをチェックして予定を登録した開発者にリマインド
  • IssueがリリースOKになっているか,PRにLGTMラベルがついているかチェック
  • PRをmasterブランチへマージ,本番環境サーバへデプロイ
  • リリース完了後Google カレンダー / New Relic の deployment にリリース記録を残す

GoBoldさんが働いている様子を下図に示します。(GoBoldさんのアイコンはなんとなく自重) 。

f:id:siroken3:20151015140355p:plain

リリース結果は下図のようにGoogle カレンダーで一覧できますし、過去のリリースを日時を検索条件にして探すこともできます。

f:id:siroken3:20151014213719p:plain

またNew Relicにも記録していますので特定のリリースからレスポンスタイムが向上した/エラー率が上昇したなどの情報を得ることができます。まとめると現在のサーバサイドのリリースフローは以下のようになります。

f:id:siroken3:20151015104353p:plain

まとめ

こうして様々な要求を満たしつつ、リリースをあとから確認できる仕組みができ大人っぽいリリースになってきたかなと考えています。なによりBotなので疲れることなく稼働してくれるのでチェックと記録が当たり前になってしまうのは大きいです。

PHPカンファレンス2015でメルカリのエンジニアリングについて発表してきました - 考える人、コードを書く人で紹介されたデプロイ時のゼロダウンタイム化を実現したことを皮切りに、今後はデプロイサーバからのpushによる配布方式を各サーバがpullする方法に変更するなど、安全でスケールアウトしやすい仕組みにしたいと考えています。

*1:一連の手順はansible playbookで記述しています

*2:例えば https://event.atmarkit.co.jp/events/4414b2d5f0f74e43f7947d7ba7a581b6/atmarkit_report

*3:しかし現在はhubot-slackもRTM APIに対応しているようです