AppService/Functionsのメンテンスを説明
あまりここまで書いてる情報はないと思います。公式ドキュメントにもまとめて書かれてるページがなかったので、間違いを恐れずに攻めて書いてみました。また、SQLDatabaseやStorageAccount等にも通じる内容が多いので、ご参考いただければと思います。
メンテナンスが必要な理由
AppService/FunctionsなどのAzureの各サービスは、たとえば日本のデータセンター(東日本・西日本)の中に、大量のサーバが設置されていて、そのサーバの仮想環境でアプリケーションなどが構築・実行されています。
Azureユーザは、AppService/Functions上にアプリケーションをデプロイして実行されていますが、その実行されているサーバには複数ユーザ分のアプリケーションがたくさん同時に実行されています。
複数ユーザが共有して利用されているサーバでは、ひっきりなしにリソースが新規作成されたり削除されたりアプリケーションが実行されたり停止されたりするので、サーバを正常状態に保って複数のアプリケーションを正常に動作し続けるためには、日常的なメンテンスが必要不可欠となります。さらに、Azure機能をAppService/Functions にアップグレードなども繁栄していく必要があります。
なので、Azureなどのクラウドサービスが日常的にメンテナンスを行うのは当然ということを、まず理解する必要があります。
メンテナンスの種類といつ行われてるか
メンテナンスは大きく2つに分けられます。予定されてるメンテナンスと、予定外のメンテナンスがあり、それぞれ実行されるタイミングが変わります。
予定しているメンテナンス
原則、深夜などのビジネスタイム外の時間帯にメンテナンスが行われます。たとえば、ANTのサーバに関する月1定期メンテナンスのようなイメージです。
予定外のメンテナンス
メンテナンスを行わないとAzure側のサーバが正常に動作できないと判断した際に実施される、予定外のメンテナンスは必要に応じて実施されるので、時間帯に関係なく実施されます。緊急メンテナンスというわけではなく、Azure側としては想定しているメンテナンスです。
メンテナンスとは具体的に何が行われるのか
メンテナンスとひと言でいっても実際になにをやっているのでしょうか。代表的な例を紹介します。
設定ファイルの入れ替えなど
サーバ内の設定ファイルを入れ替えるだけのようなメンテナンスもあります。
Azure環境のアップグレード
機能変更や障害改修されて、AppServiceなど自体が新しいバージョンにアップグレードされます。
定期メンテナンス
たとえば、ANTサーバの月1定期メンテナンスのようなものもあります。
実行中インスタンスの負荷が上がりインスタンスを切り替え
アプリケーションが実行中のインスタンスの負荷が上がったり、何かしらの問題が発生して、Azure側がこのままこのインスタンスでアプリ処理を継続することは困難だ!と判断した場合にAzure側の判断で別のインスタンスに切り替えます。
こういった動きも、メンテナンスの一つといえると思います。
メンテナンスが行われるとどうなるのか
場合によってはインスタンスが切り替わることがある
AppService/Functionsのアプリケーションはずっと同じインスタンス上で実行されているわけではありません。これは、どの料金プランを利用していても共通の話です。更に、メンテナンス実施=必ずインスタンスの切り替えが発生するわけではないので覚えておいてください。
アプリケーション実行中にインスタンス切り替えが起こるとどうなるのか?
まず前提としては、インスタンス上でアプリケーションが処理中に割り込んで、処理を中断させてメンテナンスが実施されてしまわないような仕組みになってます。要は、キリのいいところまで処理が終わるのを待った上でメンテナンス実施してくれてます。
クライアント -> (インターネット) -> FrontEnd -> WebWorker(インスタンス)
という構成でインスタンスの切り替えが発生した際、アプリケーション自体は新しいインスタンスで起動し直されます。
また、原則直前のリクエスト処理が完了した後に新しいインスタンスへの切り替えを行っており、インスタンス切り替え完了後にFrontEndのリクエストキューに溜まっているリクエストをFrontEndから新しいインスタンスに転送されて、引き続きアプリケーションが実行されるという流れになります。
なぜインスタンス切り替えが起きるのか?
Azure側が想定しているケースの例としては、以下に記載する『Azure環境のアップグレード』の際に、アップグレードしようとしたインスタンスがアプリケーション実行中の場合は、"このインスタンスメンテナンスしたいから、別のインスタンスに移動して残りのリクエスト分を処理してね" という感じで、未処理のリクエスト処理がFrontEndに残っていても別のインスタンスに移動させられます。
Azure側が想定していないケースとしては、実行中のインスタンスで問題が発生したら、Azureが勝手に他の正常なインスタンスに切り替えて、継続してアプリケーションが実行できるようにしてくれています。
どちらにしても、アプリケーションが正常に継続実行できるようにしてくれている仕組みなので、何でインスタンスの切り替えなんて発生するんだ!などと言わないようにしましょう。
アプリケーションの待ち時間(実行されていない時間)が少し発生したのはなぜ?
それはインスタンスの切り替えが発生して、新しいインスタンスの準備が整うまでの待ち時間が発生していた可能性がありますが、これはメンテナンスでもなんでもなくて日常的なAzure
側の動作です。コールドスタートがわからない方は、説明している記事を用意してますのでサイト内検索してみてください。
そして、プラス料金発生せずに、インスタンス切り替えの待ち時間を抑止できる設定があります!
AppServiceプランを使用している場合、「AppService/Functions > 構成 > 全般設定タブ > 常時接続」
こちらの常時接続機能をONにすると、Azure側でインスタンスが常に起動されるようになるため、アプリケーション起動時の待ち時間が抑止されます。設定を確認してOFFであれば必要に応じてONにしましょう。
SQLDatabase/StorageAccount等がメンテナンス中の場合
(AppService/Functions自体のメンテナンスの話から少しずれますが、)アプリケーション処理からSQLDatabase/StorageAccount等にアクセスした際に、SQLDatabase/StorageAccount側でメンテナンスが発生していると503エラー等が発生したりします。AppService/Functionsのアプリケーションとしてできることは、SQLDatabase/StorageAccount等にアクセスしている箇所に再送(リトライ)を組み込むことです。
SQLDatabase/StorageAccount等でメンテナンスが発生することも想定した実装していないと、リトライすればSQLDatabase/StorageAccount等へのアクセスが成功していたのに・・・ということになるともったいないことになります。リトライはとても重要なポイントです。
メンテンスが行われていたのか調べる方法
そもそも、メンテナンスの定義ってどう考えてますか?と聞かれたら答えられますでしょうか。
まず、何をもってメンテナンスというのかは難しいので、その前提で以下を読んでいただければと思います。
ポータル画面で確認
残念ながら「メンテナンスが発生していたかどうか」自体を確認する方法はありません。
ただ、メンテナンスが行われていた可能性があることを確認できる確認ポイントを紹介します。
問題の診断と解決で「Web App Restarted」を利用する
AppService/Functionsの[問題の診断と解決]で「Web App Restarted」を検索すると、再起動の発生有無が確認できます。Azure側がきっかけで再起動が発生していた=メンテナンスが発生していた可能性が高い、ということがわかります。
問題の診断と解決で「CPU ...」を利用する
この画面で使用されていたインスタンスIDが確認できるので、インスタンスIDが変わっていたら、インスタンスの切り替えが発生していたということが確認できます。
MicrosoftのAzureサポートに問い合わせる
有償サポート契約が必要になりますが、MicrosoftのAzureサポートに問い合わせると、該当時間帯にメンテナンスが行われていたかどうか教えてくれます。ただ、ユーザ自身が [問題の診断と解決] で確認できる情報と同じ調査結果がもらえるだけ、という可能性が高いと思っておいた方がいいと思います。
しかし、Azureサポート側もいつメンテナンスが行われていた。という情報をもっているわけではないらしいので、Azure側がきっかけでアプリケーションを再起動した、というログを確認した=メンテナンスが発生していたのだろう。という推測をもとに答えるしかできないようです。(大事なことなのでひつこく書きますが、先程書いた「メンテンスの定義」「何が行われていたらメンテナンスなのか」が難しいということが理由です。)
先述したとおり、AppService/Functionsの[問題の診断と解決]でも「この日時にAzureがきっかけでアプリケーション再起動された」「この日時にユーザきっかけでアプリケーション再起動された」というログが確認できるので、Azure側がきっかけでアプリケーション再起動された場合は、メンテナンスが発生していたのだろう。ということはAzureサポートに問い合わせなくてもユーザ側で確認することができますので、覚えておいてください。
メンテンスの事前通知されないのか・設定できるか
事前通知もされませんし、事前通知できるような設定も用意されてません。
そもそも事前通知がされたら、どうするつもりなのでしょうか。
事前通知を受けたら、一時的にAzure側にリクエストを送信しないように制御でもするのでしょうか。
どのようなメンテナンスが存在するのかの説明にも書いたように、アプリケーション動作に影響がないレベルのメンテナンスもたくさん存在します。じゃあアプリケーション動作に影響があるレベルのメンテナンスのときだけ事前通知してほしいとでも言うのでしょうか・・・。アプリケーション動作に影響があるかどうかの判断をAzure側でできるはずがありません。
メンテナンスの多くは数秒レベルで終わることも多いので、事前通知とかいうことを考えるよりは、Azure側へのリクエスト送信処理にリトライ処理を組み込む。という対策をしたり、クラウド上でアプリケーションの可用性を維持するために必要な考え方を学んで実践した方が、有効だと思います。オンプレのときは考えなくてよかったのに・・・という気持ちはわかりますが、クラウドのメリットは無数にあるのでクラウドの恩恵を受ける代わりに、メンテナンスの発生を受け入れるということはクラウドサービスと付き合う上で必要になります。
Azureが事前通知をしない理由・・・考えても仕方がありませんので書きませんし、上記した内容でわかっていただけたかなと思います。
その代わりに、メンテナンスの影響を軽減させる方法を紹介していきますので、是非ご検討ください。
メンテンスの対策
アプリケーションを継続実行させるための対策
Azure有償サポートなどでも推奨されている対策を、4つ紹介します。
AppServiceプランのインスタンスを2つ以上で運用する
AppServiceプランを使用している場合の対策になります。
インスタンス数が1だとインスタンスが全く使えなくなる時間が発生する可能性が高まるため、インスタンスに影響するメンテナンスが発生した場合に、アプリケーションが遅延または一時停止してしまうことがあります。
容易な対策としては、スケールアウトしてインスタンス台数を2台以上にします。メンテナンスはスタンプ内のインスタンスを少しづつ順番にメンテナンスしていくので、インスタンスAはメンテナンスで使えなくなってしまうがインスタンスBはメンテナンスが行われていないため、メンテナンスによってアプリケーションが一時停止してしまう可能性を下げることができます。
ただ、これはあくまでも「メンテナンスの影響を受ける可能性を容易に下げられる対策」であることを理解いただければと思います。
docs.microsoft.com
アプリケーションを複数リージョンにデプロイして主と副で運用する
具体例でいうと、ひとつのAppServiceを「東日本リージョンにデプロイ」(プライマリリージョン)、もうひとつのAppServiceを「西日本リージョンにデプロイ」(セカンダリリージョン)をそれぞれ構築します。
そして、FrontDoorなどでアクティブなAppServiceをコントロールしてもらう方法です。
TrafficManagerで利用できないインスタンスを避ける
TrafficManagerは定期的にAppService/Functionsのエンドポイントを監視し、問題が発生したリージョンから、別のリージョンへリクエストをルーティングを行うことが可能です。
リトライ処理をアプリケーションに組み込む
これはAzure関係なく、アプリケーションに組み込まれているのが常識だと思います。基礎的で一番大事な対策です。
メンテナンスは短い時間で終わることが多いので、もう一度リトライすれば正常に進んだのに!ということが起きないように、リトライ処理を入れておくのは必須になります。
docs.microsoft.com
セーフティにアプリケーションを終了させる対策
メンテナンス発生時に、アプリケーションが中途半端な状態で強制終了させられないよう、正常にアプリケーションを終了させるための仕組みです。
GracefulShutdownに対応する
受信済みのリクエストを完了するためのタイムアウト期間を設けて、その間に安全にアプリケーションを終了させる仕組みです。タイムアウト期間のあいだにアプリケーションの後処理・DBや外部サービスとの接続を終了させて、それらが完了したらシャットダウンを行うことで、強制終了が防げてアプリケーション不整合や余計なエラー を防ぐことができます。デプロイがタイミングを意識せずに実行できるという、副産物もあります。
最後に・・・
メンテナンスに関する情報・考え方を長々と書きましたがいかがでしたでしょうか。
Azure構成とアプリケーション実装を駆使して、メンテナンスの影響が最小限になるように構成してアプリケーションの可用性の維持を目指していきたいですね。
以上です。