コールドスタンバイで可用性を確保した負荷分散ウェブシステム

2014.08.29

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

渡辺です。

弊社では、お客様へAWSのコンサルティングを行っております。 ハードウェアを売ってなんぼではありませんから、より低コストで満足できる環境をご提案することで勝負しています。

そのためには、どのような環境を提供していけば良いかヒアリングし、適切に要件定義を行うことが大切です。 システム開発も同じですが、要件定義が綺麗に決まるかどうかが、プロジェクトが成功するかどうかのほとんどを左右します(ここでいう成功は、手戻りが発生しないなども含む)。 そこで、要件定義シリーズとして、ケーススタディ的なものを書いていきたいと思います。

今回はロードバランサを使った負荷分散システムの可用性についてです。 「多くのリクエストが来ても落ちない可用性の高いシステム」が欲しいという漠然とした要望では、本当に必要なシステムがどこにあるのかが解りません。 それは、負荷分散(処理能力)と可用性(稼動率)を同時に考えてしまうからです。 分けて考えることが大切です。

ロードバランサとウェブサーバ

今回は多くのリクエストを捌くことを前提とします。 処理能力をあげるためには、インスタンスのスペックを高くする(スケールアップ)か、複数のインスタンスを横に並べて負荷を分散する(スケールアウト)かのどちらか(もしくは両方)を行います。 今回は、より多くのリクエストを処理しなければならない可能性が高いということで、横に並べる方式を採用したとします。 つまり、ロードバランサ(ELB)と複数のウェブサーバ(EC2)で構築するウェブシステムです。

cs1

利用者のリクエストはロードバランサ(ELB)経由で、複数のウェブサーバで処理されます。 この時、ELBはデフォルト設定で、すべてのサーバに負荷が均等になるように処理を分散します。 したがって、1,200のリクエストがあったならば、理論的には600ずつ分散されて処理されます。 各サーバの処理能力が1,000リクエストであったならば、充分に余裕をもって処理できると言えるでしょう。

ELBは各ウェブサーバの死活監視を行います。 もし、片方のウェブサーバが故障して応答がなくなったならば、そのサーバへリクエストは転送しません。 したがって、片方のウェブサーバが故障しても、利用者はシステムを利用できます。

つまり、このシステムは、高負荷にも対応し、可用性の高いシステムです。

さて、本当でしょうか?

故障したケースを考える

サーバはなんらかの理由で故障する可能性があります。 これはどんな高価な壊れにくいサーバでも、可能性が低くなるだけであって、故障する可能性はゼロではありません。 したがって、故障した時にシステムがどのように振る舞うかを想定しなければなりません。

cs2

片方のウェブサーバが故障した時、ELBの機能によりもうひとつのウェブサーバのみで処理が行われるようになります。 つまり、これまで分散されていた1,200のリクエストが片方に集中し、処理能力の1,000を越えてしまいます。 すると、「システムは落ちないが利用者に満足なサービスを提供できない」、「処理能力を超えたリクエストがきたことをトリガーとしてもうひとつも故障する」といった状況になるかもしれません。

つまり、高負荷には対応していましたが、可用性は高いとは言えないシステムでした。 それではどのようにして可用性を高めたらよいでしょうか?

サーバを増やして可用性を高くする

最も簡単なのはウェブサーバの台数を3台以上にすることです。

cs3

ウェブサーバが3台になれば、1,200のリクエストは400ずつに分散されます。

cs4

1つが故障したとしても600ずつなので余裕があります。 ただし、1台故障した時にさらにもう1台故障したならば、1,200のリクエストが集中します。 したがって、闇雲に台数を増やすのではなく、どこかで落としどころを見つけなければなりません。

このケースで言えば

  • 処理能力は充分に確保するが、可用性はあまり重視しない(2台、故障はオンデマンド対応にする)
  • 処理能力を充分に確保し、ある程度の可用性を確保する(3台)
  • 処理能力を充分に確保し、高い可用性を確保する(4台以上)

と選択肢がありますね。 単純にELBで2台に分散しただけでは可用性は高くならない可能性があることが解ると思います。

もちろん、稼動しているウェブサーバの台数を増やすということは、それだけコストが増えます。 高いコストをかけてでも可用性を高めたいサービスもありますが、なるべくならばコストは下げて可用性を高めたいところです。

少ない台数で可用性を確保する

起動しているインスタンスが少なければコストはそれだけ下がります。

そこで3つ目のインスタンスを停止しておき、起動中の1台が故障したならば起動するという戦略をとることができます。 いわゆるコールドスタンバイと呼ばれるパターンです。

cs5

コールドスタンバイでは、インスタンスが起動していないためインスタンスの起動コストがゼロであることがポイントです。 EBSの利用料金などは発生しますが、インスタンスの起動コストに比べれば無視出来るほど小さな額です。 ただし、システムに障害が発生した時、インスタンスをどのように起動するかを考えなければなりません。

cs6

手動運用によるコールドスタンバイ

最も原始的な方法は手動運用です。

システム障害などをアラートとして受け取り、運用担当者が停止中のインスタンスを起動します。 問題となるのは運用担当者に連絡がつかなかったりすると、長時間起動ができないことです。 逆に夜間休日にサービスが止まっても営業時間になって復旧すればよいシステム(例えば社内チャットシステム)であれば、手動運用によるコールドスタンバイは充分に良い選択とも言えます。

死活監視によるコールドスタンバイ

なんらかのスクリプトやプログラムを組み、障害を検知した場合に停止中のインスタンスを起動する方法です。 この方法であれば属人化されないため、作業ミスもなければ、連絡がつかないこともないでしょう。 インスタンスの起動はAWS SDKやAWS CLIを利用して簡単に行うことができます。

ただし、死活監視と自動起動を行うスクリプトなどを作る必要があります。 死活監視用のサーバを別途用意することや、死活監視サーバが故障した時のことも考慮しなければなりません。 したがって、ある程度のところで落としどころを付ける必要はあります。

有人監視サービスによるコールドスタンバイ

弊社サービスのひとつであるフート24は有人監視サービスであり、障害の監視や障害時にサーバのリブートなど行うことができます。 フート24を利用すれば、有人監視よりも早く確実に、死活監視用のスクリプトを作らなくても対応可能です。

コールドスタンバイの問題点

コールドスタンバイは障害発生を検知してから停止中のインスタンスを起動します。 したがって、ある程度のタイムラグが発生します。 このタイムラグの間に致命的な問題が発生した場合や、一時的なサービス中断は受け入れなければなりません。

とはいえ、「X分程度のサービス停止は許容できる」というケースは多いかと思います。

まとめ

可用性の高いシステムを作るといっても様々なやり方があります。 コストと可用性のバランスをとり、適切なソリューションを選択することが大切です。

特にコールドスタンバイは、通常のインフラの場合はハードウェアを調達しなければいけませんが、AWSの場合は低コストでそれなりの可用性を確保できるお勧めの構成のひとつです。 弊社サービスフート24と合わせてご検討ください。