Misoca メンテナンス画面の裏側

Misoca の開発をしている id:mizukmb です。

先日、Misocaでは軽減税率8%の入力、および区分記載請求書の形式に対応しました。今回のリリースはシステム全体に関わる大規模なものとなったため、リリース作業中の時間はWeb・API・iOS/Androidアプリ全てのサービスを停止し、メンテナンス中としていました。

これまでMisocaではサービスを長時間停止させたメンテナンスやリリースをほとんど実施しておらず、メンテナンスモードを簡単に切り換える機能はありませんでした。加えて、今回のリリース作業の時間においては、下記を実現する必要がありました。

  • 一般ユーザからはMisocaサービスにアクセスさせたくない(メンテナンス中として見せたい)
  • 開発者など、特定の条件を見たすユーザの場合は、メンテナンス中でも本番環境にアクセスして動作確認ができるようにしたい
  • 外部連携するシステムによっては、メンテナンス中でもアクセスを止めたくない

そこで、今回のリリースに合わせて上記の要件を満たすメンテナンスモード機能を実装しました。本ブログでは、メンテナンスモード機能の紹介や、実際のメンテナンス画面などをお見せしていきたいと思います。

メンテナンスモードの仕様

メンテナンスモードの有効・無効の切り換え方法として以下の2パターンを用意しました。

  • スケジュール実行による有効・無効の切り換え
  • 手動による有効・無効の切り換え

メンテナンスモードの状態は上記2パターンをORで判定しています。ですので、どちらかが有効になっていればメンテナンスモードになりますし、どちらも無効にならない限りはメンテナンスモードは停止しません。

こうした仕組みにした理由は、メンテナンスの時間を延長した場合にスケジュールの時間を変更するよりも簡単にできるようにするためです。

また、メンテナンスモードの状態管理はRailsアプリケーションに持たせています。調査の段階では、ロードバランサで制御する方法も検討しましたが、先に述べた要件を満たすためには、現行のシステムでは実装コストが非常にかかるということが分かったので、Rails内で制御する方法に決定しました。1

設定方法

スケジュールの設定

メンテナンスモード設定用のYAMLファイルに時間を書きます。デプロイすると、指定した時間内はメンテナンスモードが有効になります。

開始・終了時間の設定は2つ以上設定できないようにしました。メンテナンス自体は頻繁に行われるものではないため、高機能にさせすぎず実装をシンプルに保つためです。

# メンテナンスモードの有効・無効を設定する
# `start_time` `end_time` に記述する日時のフォーマットは以下の通り。タイムゾーンはJSTとする
#   YYYY/MM/DD hh:mm:ss
production:
  start_time: 2019/06/18 05:00:00
  end_time: 2019/06/18 06:00:00

手動の設定

手動のON/OFFはThorタスクを使うようにしました。誤って使われないように、こちらの機能は実行できる権限を持つ人を限定しています。

特定ユーザのアクセスを許可するための設定

メンテナンス中に開発者を含む特定ユーザがアプリケーションにアクセスして動作確認できるように、ホワイトリスト方式でアクセスを許可するIPアドレスやHTTPヘッダを指定できるようにしました。

# メンテナンスモードの有効・無効を設定する
# `start_time` `end_time` に記述する日時のフォーマットは以下の通り。タイムゾーンはJSTとする
#   YYYY/MM/DD hh:mm:ss
production:
    (snip)
    ips: ['XXX.XXX.XXX.XXX', 'YYY.YYY.YYY.YYY']
    header:
      name: 'X-Foo-Bar'
      value: 'value'

これにより、前述の

  • 開発者など、特定の条件を見たすユーザの場合は、メンテナンス中でも本番環境にアクセスして動作確認ができるようにしたい
  • 外部連携するシステムによっては、メンテナンス中でもアクセスを止めたくない

を実現しました。

実際の様子

f:id:mizukmb:20190702145424p:plain
メンテナンス画面

全てのページで上記画面を表示するようにしました。メンテナンス情報は別ページを見てもらうようにリンクを貼っています。サービスによってはツイッターの公式アカウントを載せているところもあるみたいです。速報値を伝えるためにこうした情報は外に置いておくことが重要だと思います。

HTTPステータスコードは 503 Service Unavailable を返しています。

おわりに

メンテナンスモードの仕組みについて紹介しました。調査の段階で得た気付きとして、他サービスのメンテナンス画面を調べようとしてもそんな都合良くメンテナンス中のWebサービスは見つからないということです。Herokuがメンテナンスモード機能2を提供しているため、社内のHeroku上で動いているサービスをメンテナンスモードにして参考にしていました。

採用

Misocaのサービスをメンテナンスしてくれる人を募集しています。

recruit.misoca.jp


  1. 根本原因を解決することも検討しましたが、一旦スコープから外しました

  2. https://devcenter.heroku.com/articles/maintenance-mode