Azure App Service の自動スケールと負荷テスト
はじめに
クラウドの代表的なメリットの1つは、オンデマンドにリソースを確保することができ、その柔軟なスケーラビリティによって、ビジネスの状況に応じて必要かつ十分な処理能力を得られること、それによって単純なコスト削減だけではなく、コストが最適化できることであると考えます。私の日々のお仕事の中で Azure に関してお客様からご相談を頂くときは、Azure といえば PaaS、PaaS といえば Web Apps (App Service)、という話になることが大変多いです。これは App Service が最初に挙げた“クラウドのメリット” を最もわかりやすく体現しているからであると思いますし、非常にうれしい気持ちになります。本記事では App Service のスケーラビリティとその内部的な仕組みを概説し、負荷の増減に応じて自動的にスケールさせる方法、およびその挙動を検証する方法(ロードテスト)についてご紹介したいと思います。
スケーラビリティ
あらためてシステムにおけるスケーラビリティとは、簡単に言えば「利用量や仕事量の変化に対して適応できる能力」のことを意味し、多くの場合以下の 2 つの手法によって実現されます。
- スケールアウト/スケールイン(水平スケーリング)
- スケールアップ/スケールダウン(垂直スケーリング)
スケールアウト/スケールインとはサーバー台数を増やす(減らす)ことを意味します。スケールアップ/スケールダウンとはサーバーのスペックを大きくする(小さくする)ことを意味します。これによってシステム全体のキャパシティを調整することで状況の変化に対応するわけです。
私はインフラエンジニアの経験がないのであくまでも想像ではありますが、物理サーバーであればその台数を増減させることは、設置場所、ネットワーク、調達等の関係からなかなか容易でないことは想像に難くありません。またマザーボードが保持する CPU やメモリのソケット数、ディスクを接続するインタフェース数の制限等から、スペックアップも限度がありそうです。もちろん仮想化技術が導入されている場合には柔軟性は高まりますが、やはり最終的には仮想マシンホスト、およびそのクラスタ全体のキャパシティに制約されます。
すなわちこういったスケール調整を実施するために、最初からそれを見越して余裕のある設計をするか、状況が変わったらそこから時間をかけて行う必要があるわけです。前者は余剰のコストが発生するリスクを、後者はビジネス機会の損失が発生するリスクをはらんでいることになります。
Azure App Service のアーキテクチャ
App Service の利用形態を非常に乱暴に説明すると、複数の利用者がフロントエンドのロードバランサを共有し、その背後で動作する Web サーバーのプールのなかから数台を占有する形になっています。
占有した Web サーバーに対してアプリケーションを配置しておくと、割り当てられた URL へのリクエストがあった際に、ロードバランサーがそのリクエストを各 Web サーバーに振り分けてくれます。この確保した Web サーバーのスペックと台数を表すリソースが、App Service プラン、そこにデプロイするアプリケーションの容れ物が Web Apps(ないしは API Apps、Mobile Apps 等)と呼ばれます
Web Apps はそれが配置される App Service プランで確保される全ての Web サーバー上で同じように動作するように構成されています。このため App Service プランの設定を変更するだけで利用者が配置したアプリケーションのスケールアップ/ダウンや、スケールアウト/インを実現することが出来るわけです。
手動スケール
Azure ポータルで手動スケール操作は非常に簡単で、下記にあるように必要なサイズを選択するか、トラックバーでつまみをドラッグするだけです。
前述の操作の結果、 Azure データセンターで事前に多数配備された空きノードのなかから割り当て(あるいは返却)が行われ、Web Apps の配置、およびロードバランサーの振り分け設定の変更が行われます。つまり前述の「余裕を持った設計とそれに伴う余剰のコスト」というリスクに関しては Azure がカバーしていることを意味します。より正確には利用者が支払う料金の中にそのリスクの担保が含まれていることになるわけですが、多数の利用者が共有して使用するマルチテナント方式のサービスであるため、1 利用者あたりの担保分を低く抑えることが出来る、と言えます。
留意事項
ただしスケーリングが容易とは言っても無制限に拡張できるわけではありませんのでご注意ください。スケールアウトの場合は Basic 、Standard、Premium といったプランに応じて、Web サーバーは最大 20 インスタンスまでという制限があります。ただしこれは複数の App Service プランを構築して、Traffic Manager 等でさらに上位レベルから負荷分散するという拡張策が可能ですので、それほど大きな制限にはならないかと考えます。一方スケールアップの場合には、最大でも CPU 4 コア と 7 GB RAM というのが各 Web サーバーの最大スペックになります。このため単一リクエストの中で大量のスレッドを消費する、メモリフットプリントが非常に大きい、といった特性を持つアプリケーションの場合には注意が必要です。
このように App Service はスケールアウト/イン方式の方が柔軟性が高いので、新規開発ないしは修正が可能なアプリケーションの場合には、この点を考慮したアーキテクチャを設計するように心がけていただくことをお勧めします。
※ ここでは割愛していますが App Service Environment という形態をご利用いただくと最大スペックや最大インスタンス数は大きくなりますが、上限があるという意味では同じです。
コストを最適化するには
App Service の基本的な料金はユーザーアクセスの有無に関わらず App Service プランで選択したサイズの単価、インスタンスの台数、稼働時間で決まります。このためアクセスが無く暇な時に大きなインスタンスを大量に並べておけば無駄な料金が発生することになります。逆にアクセスが多く忙しい時にスペックや台数が不足すれば(安くはなりますが)過負荷状態に陥り、レスポンスタイムの長期化、スループットの低下、予期せぬエラーの発生といった問題が発生します。
状況の変動具合にもよりますが場合によっては「手動スケール」アプローチでは、設定変更が間に合わない可能性もありますし、そもそもそのオペレーションにかかる人的コストも馬鹿になりません。つまりコストを最適化するためには、状況の変化に応じて「自動スケール」する方式が望ましいといえます。
ここまでのまとめ
- App Service はスケールアウト/イン方式によるスケーリングに対してより柔軟性が高い
- コスト最適化のためにはスケーリングを自動化することが望ましい
自動スケール
前述のようなスケーリング操作を自動化するには大きく分けて 3 つの要素が必要になります。
- キャパシティ不足ないしは余剰を検知するためのメトリック収集と監視
- 上記のメトリクスに基づいた App Service プランの増強(縮小)方針
- 実際のスケーリング作業
この中で最も重要かつ難しいのは「適切なメトリックの特定すること」であると考えます。これによってボトルネックの発生を検知し、またスケールアウトによってそれを緩和してやる必要があります。
ボトルネック発生を検知するには
本記事の執筆時点では、App Service は以下のメトリックに基づいた自動スケールアウト/スケールインを設定することが可能です。Web システムにおいてボトルネックを検知する上では代表的な指標値が提示されていると思いますが、これらのうち「どれが最も適切か?」はシステム特性によって大きく異なるという点にご留意ください。
- App Service Plan のメトリック
- CPU Percentage、Memory Percentage、Disk Queue Length、Http Queue Length、Data In、Data Out
- ストレージキュー
- Message Count
- Service Bus キュー
- Message Count
- その他のリソース
- 各種
例えば画像を取り扱うなどの I/O ヘビーなアプリケーションにおいては、高負荷状態になると I/O の待ちによってスループットやレスポンスタイムの悪化が発生することが予想されますが、そのような状況では CPU の使用率は低いままだったりします。当然ながらこういった特性を持つシステムでは App Service Plan の CPU Percentage というメトリックは「スケールアウトが必要な高負荷状態であること」や「スケールインが必要な余剰が発生している状態であること」を検知するためには全く役に立ちません。これを自動スケールの基準となるルールに設定すると、自動スケール機能が全く意味を為さないことになってしまうわけです。
※ ここでは紹介していませんが時刻に応じたスケジュールベースでのスケールも可能です
システム特性の把握と自動スケールの検証
前述の通り自動スケールを有効に活用するには高負荷状態におけるシステム特性の把握が必須です。またその際に自動スケール設定が適切に機能するか否かを検証する必要があるでしょう。具体的にはスケールアウト時にレスポンスタイムやスループットといった性能の改善が見られ、かつスケールの基準として選択したメトリックも軽減されていることを確認する必要があります。最大限までスケールアウトした場合にどこまでの性能が出せるのか、すなわちシステムの限界値を見極めておく必要もあるでしょう。またスケールインした際には性能劣化等が無く、またエラーなどが発生しないことも重要になってきます。
このためには具体的に Web Apps に対して大量のリクエストを発生することで高負荷状態を意図的に発生させる、いわゆるロードテスト、ストレステスト、パフォーマンステストと呼ばれるようなテストを行います。伝統的には人海戦術による F5 連打という手法もありますが、Web Apps を高負荷状態に追い込むにはなかなか難しいでしょう。現実的には Web リクエストを機械的に大量生成するためのアプリケーションと、それを大規模に行うための大量のクライアントマシンが必要になります。
Visual Studio Team Service によるロードテスト
負荷発生スクリプトを開発してマルチスレッドで駆動し、多数のクライアント PC や仮想マシンを準備して大規模な負荷を発生させる・・・、というアプローチもなかなかエンジニア魂をそそるものがありますが、ここもやはりクラウドサービスに頼っていただくことをお勧めします。Visual Studio Team Services (以下 VSTS)ではロードテストという機能が提供されており、以下のようなフレームワークが提供されています。
- テストスクリプトの生成
- 多数の負荷生成エージェントのセットアップと協調動作
- テスト対象システムのメトリックの収集
簡易的なロードテスト
ロードテストのセットアップは Azure ポータルから行うことが可能です。これによって実際には VSTS にロードテストの定義が作成されテストが実施されます。
テスト定義に設定された負荷の大きさに応じて VSTS が自動的に多数の負荷生成マシン(Hosted Agent )を用意し、それらを協調動作させることで大規模な負荷を生成させることができます。また作成されたテスト定義は再実行することが可能ですので、Web Apps やアプリケーションをチューニングして再テスト、といった一連の作業を行う上でも非常に便利です。
高度なロードテスト
Azure ポータルでロードテストを定義する際には以下のような簡易的なオプションしか設定できません。
- 特定 URL への GET リクエストの生成、あるいは、Visual Studio Web テストに定義されたリクエスト群の生成
- 特定ロケーション(米国東、米国西、北ヨーロッパ、東南アジア、東アジア、etc...)からのアクセス
- 固定数の仮想ユーザーによる一定時間の負荷生成
ただし VSTS の画面でロードテストの定義を作成ないしは編集することで、以下のようなより高度なロードテストが可能です。
- (Visual Studioを使用しない)Web テストの編集
- 段階的に仮想ユーザー数を増加させるステップロード機能
- 複数ブラウザーミックスによるアクセス
- より多くのロケーションからのアクセス
- 独自のマシンを使用したエージェント郡による負荷生成
例えば以下はステップロード機能を使用して段階的に Web Apps への負荷を増大させたロードテストの結果の画面になります。このテストによってシステムのボトルネック傾向、パフォーマンス上限値、また自動スケール時の挙動を確認することが可能です。
ここまでの紹介した内容は Visual Studio Team Services というクラウドサービスを使用していますが、統合開発環境としての Visual Studio は必須ではありません。Web ブラウザーだけでもかなりの負荷テストを行うことができます。しかし Visual Studio が使用できるのであれば、単体テスト機能やロードテスト機能を組み合わせることで、カスタムのロジックを組み込んだ高度な負荷生成スクリプトを作成し、VSTS によって管理されるエージェントで実行させることも可能です。あるいはテスト結果をエクスポートして詳細な分析を Visual Studio IDE で実施することも可能です。ロードテスト機能を最大限に活かすのであれば、是非クラウドサービスと合わせて IDE の方もご利用いただければと思います。
ロードテストによる自動スケールの検証結果
自動スケールを定義する際にスケールアクションの通知として電子メールを設定しておくと、実際にスケールアウト/スケールインが行われた際に下記左図のようなメールが送信されます。
また VSTS からエクスポートしたテスト結果データ(右図)からも、Web Apps がスケールアウトしたタイミングでレスポンスタイムが改善し、スループットが増加していることがわかります。(この図は Visual Studio を使用してテストデータを CSV としてエクスポートし、Excel を使用して集計・加工しています)
まとめ
- Azure App Service は水平スケーリング(スケールアウト/イン)が柔軟に行える
- コスト最適化を追求するためには自動スケーリングが必須
- 高負荷時のシステム特性を見極め、適切なメトリックを設定するためには負荷テストが必要
- 大規模な負荷を生成させるためには Visual Studio Team Services のロードテスト機能が有効