メンテナンスモードを考える(webクライアント)
メンテナンスの目的
- ユーザーが一時的にサービス利用できないようにする
- インフラ移行によるシステムのダウンタイムが発生するため
- データの不整合を防ぐ
- 互換性の不一致によるエラーを防ぐ
- 存在しないインフラへのリンクを防ぐ
- インシデントが発生した場合、それ以上の被害拡大を防ぐ
- 開きっぱなしにするよりも一度閉じたほうがデバッグや回復作業がしやすい
- データの不整合が発生するインシデントである場合、閉じないと回復作業が大変になる
- ビジネス上や法律上の理由でサービスを一時停止しないといけない
- 年末年始休暇など
- インフラ移行によるシステムのダウンタイムが発生するため
メンテナンスの種類
- 計画的なもの
- インフラ移行においてダウンタイムが発生する
- インフラ移行においてダウンタイムが発生しない、もしくは短いが、変更リスクが高いので念の為メンテナンス期間を設ける
- 運用的な側面から停止する(年末年始休暇など)
- 緊急的なもの
- インシデントの発生
- 外部的な圧力(法的なものなど)によりサービスを一時停止せざる得ない
メンテナンスモードのレベル
- レベル1: すべてのリンクをメンテナンスページにリダイレクト(リライト)する
- レベル2: 部分的に利用可能にする
- ホーム画面のみみれる
- 他の画面も見れるが、書き込みできない
- レベル3: 裏側でメンテナンスしているが普通に使える
- 念の為ユーザーにお知らせする
- とくにお知らせしない
常にレベル3であることが理想だが、いったん技術的にもハードルが低いレベル1を考える。
メンテナンスモードの要件
メンテナンスモードレベル1の前提
- デザインとコンテンツ
- 明確にメンテナンスであることを伝える
- メンテナンス期間を伝える
- (できれば)メンテナスの現状を定期的にお知らせする
- メンテナンス期間が終わっても、画面が変わらない場合の対応策を書く
- 問い合わせ方法の提供
- 機能的側面
- メンテナンス期間中はすべてのリンクがメンテナンスページにリダイレクト(リライト)される
- メンテナンス期間が終われば、メンテナンスページから元のページにリダイレクト(リライト)される
- 自動で?
- リロードすれば?
- (必要であれば)多言語対応
- 非機能的側面
- メンテナンスページ自体がダウンしない
- SEO(検索エンジン)対応
- メンテナンスページ自体が軽快に表示できる
メンテナンスモードの辛さ
- 毎回メンテナンスのたびにメンテナンスページの中身を書き換えないといけない
- リダイレクト設定めんどい
- 終わった後のリダイレクト設定もめんどい
→ ある程度自動化できないか?
メンテナンスモードのアーキテクチャ
-
前段にLB(ロードバランサ)を噛ませてあり、LB自体にカスタムドメインが設定されている場合
- メンテナンス用の静的ページを作成し、すべてのルーティングをそちらによせる
- 302リダイレクトの場合
- メンテナンスが終わったら、メンテナンスページのアドレスから戻るようにもう一度リダイレクト設定をする必要がある
- リライトの場合
- 可能ならこちらのほうが楽
- 302リダイレクトの場合
- メンテナンス用の静的ページを作成し、すべてのルーティングをそちらによせる
-
Cloud Runなどのコンテナサービスに直接カスタムドメインを設定して運用してある場合
- メンテナンスページようのイメージを作成しておき、メンテナンス時にそのイメージをもったコンテナを展開、ルーティングさせる
-
その他いつでも
- アプリケーションコードにメンテナンスページを仕込んでおき、機能フラグによって表示をコントロールする
追記:
勘違い、リライトはそもそも同じサーバー内のコンテンツしか無理だった。同じURLで異なるURLにアクセスしてほしいときはプロキシ設定をしないといけない。
じゃあどうするか
以下を目指したい
- まずは手動によるコントロール
- 落ちたり復旧したりを監視して自動的にメンテナンスモードになるのはいいが、勝手にメンテナンスモードになるのは怖い
- メンテナンスモードへの移行、メンテナンスモードからの移行は、手動によるコントロールを
- メンテナンスモードへ簡単に入れる
- ボタン1つでいけるといいな(ただし権限がある人が)
- メンテナンスモードから簡単に復旧できる
- ボタン1つでいけるといいな(ただし権限のある人が)
- メンテナンスページの内容を簡単に修正できる
- 修正するのにイメージを再buildするとかは避けたい
実現方法考案
- メンテナンスページの内容を簡単に修正できる
- (最強) アプリケーション自体にメンテナンス機能を入れ、動的にコントロールする
- (現実的1) メンテナンスアプリケーションを作成し、中身のコンテンツを簡易的なdbで管理する(cms的なサービスも使えそう)
- (現実的2) メンテナンスページはhtml,css,jsで作成し、htmlの書き換えとデプロイをGitHub上でできるようにする
- (現実的3) コーポレートサイトや何かしらのCMSサービス上にメンテナンス情報を記載しておき、メンテナンスページではそれをiframeとかで表示させる
- メンテナンスモードへの移行
- アーキテクチャにおうじて、メンテナンスモードへ移行できる方法を確立し、手順書化しておく
- メンテナンスモードからの復旧
- なるべくメンテナンスページへのリダイレクトではなくリライト的な運用であれば、復旧が楽
例1: cloud runにサービスをデプロイしてLBを使っていない場合
- メンテナンスページを表示するイメージを作成しておく
- メンテナンスページ専用のアプリケーションパターン
- メンテナンスページにiframeでコーポレートサイト表示させるパターン
- メンテナンス時にリビジョンをメンテナンスイメージに書き換える
- トラフィックをすべてメンテナンスイメージコンテナに流す
- メンテナンスが終了すれば、もとのリビジョンにトラフィックを流し返し、メンテナンスコンテナを終了させる
例2: LB使っている場合(未検証)
LBにrewrite機能がある
- メンテナンスページを作成してCDNから配信
- メンテナンスページ専用のアプリケーションパターン
- メンテナンスページにiframeでコーポレートサイト表示させるパターン
- HTMLをGitHub上で直書き換えデプロイパターン
- トラフィックをメンテナンスページにrewriteさせる
- メンテナンスが終了すれば、rewriteの設定を削除しもとのサービスにトラフィックを流す
LBにrewrite機能がない
- 上記に加えて、redirectされた側のCDNから、本サービスにredirectし直す設定をする
- これで、メンテナンスページにアクセスしたユーザーがリロードすれば、本サービスに復帰できる
検証結果
GCSは単体で静的ホスティング機能は提供していない?おそらくLBが必要。
-> 結局LBいるんかい。お金かかるなぁ
S3はcloudfrontと組み合わせればSPAライクなルーティングができる静的ホスティングができた気がする
結局、どんなパスがきても同じhtmlを表示し続けてほしいから、SPAライクなルーティングが必須。
amplifyで構築するのが正解かも?
参考
API、Webアプリ、および、モバイルアプリは、メンテナンスモードのON/OFFのフラグを取得して動作を変えます。Webアプリはメンテナンス中の場合は、メンテナンス中の画面を利用者に表示するようにします。APIはメンテナンス中を示すエラーをフロントエンドに返却するようにしています。
まぁ確かに今後web以外のフロントエンドを考えたときに、アプリケーション自体にメンテナンスモード表示を設けるのが正しい気がしてきた。そのままの環境を使えるわけだし、新しいメンテナンスページ環境の同時接続数とか考えなくてもいいし
あとは、詳細のメンテナンス情報を別リンクにすることで、画面の変更コストを下げる
追記
Google CloudでCloud Runを使ってサービスを発展させていきたいなら、LBを置くほうがよい。
LBを置くことで
- URLが同一になるため、CORS回避できる
- IAPがつかえる
- メンテナンスページ移行が楽