スポットインスタンスを用いたサービスの平均故障間隔(MTBF)を定量的に評価するはじめにスポットインスタンスの中断条件インスタンスプールに注目スポットインスタンスのみで安定したサービスを提供するには実測値を元に故障率を計算プール数を増やすために最後にはじめにこんにちは、IT基盤部の天野です。AWSやGCPを用いたゲームインフラを担当しています。DeNAが運用している大型ゲームでは、ステートレスなサーバにスポットインスタンスを使用しています。スポットインスタンスはAWSに中断(=shutdown)されることがある代わりに、コストを大幅に抑えることができるインスタンスです。利用し、さらに負荷が増える部分で万が一落とされても問題ない範囲をスポットインスタンスで運用することが推奨されていたりします。web、memcached、worker等のサーバにおいて、ほとんどのリソースをスポットインスタンスで運用し、それでいてサービスは絶対に落ちない自信を持っています。スポットインスタンスを本番環境に利用し始めてからもう1年以上経ちますが、まだスポットインスタンスが原因でサービス影響を出したことはありません。今回はその自信の根拠となった理由や、スポットインスタンスの可用性について紹介していきます。スポットインスタンスの中断条件はじめにスポットインスタンスの中断条件についておさらいしておきましょう。スポット料金が入札価格を上回ったときAWS側でインスタンスの需要が高まったとき1.の入札価格を上回ったときですが、これが原因で中断されることは、ほぼありません。言いますのも、2017年12月以降は価格変動が緩やかになり、それ以降はスポット価格がオンデマンド価格以上に上がることを見かけなくなりました。そのため、入札価格をオンデマンドインスタンスと同額(デフォルト値)で入札しているかぎりは、これが原因で中断される可能性は、過去の実績に照らして極めて低いです。2.のインスタンス需要が高まったときは、DeNAの環境でも頻繁に中断されているのを検知しています。これは時間指定でスポットインスタンスを使うスポットブロックであっても、同様に中断されます。検証では入札価格を10倍にしていようが、オンデマンド価格と同じにしていようが、同じ頻度で中断されていますので、中断対象を決定するロジックに入札価格は関係ないようです。インスタンスの稼働時間も関係なく、完全にランダムに対象が決定されているように見えています。インスタンスメタデータでそのことを検知することができます。インスタンスプールに注目AWSによるとインスタンス需要はAZ毎、さらにインスタンスタイプ毎に別々に管理されており、その単位をプールと呼んでいます。同一インスタンスファミリーであってもインスタンスのサイズが異なれば別のプールになります。別プールですので、インスタンス需要は別々に管理されています。他のユーザが特定のインスタンスタイプを大量に使用してリソース不足になったとしても、AZ毎の残リソースには偏りがあるようで、スポットインスタンスが中断され始めるタイミングにはわずかに差が生じます。複数のプールを混ぜて使用すれば、そのわずかな差により、同時に中断されるリスクは減り、可用性は高まります。以下の図は2019年1月2日のプール毎のスポットインスタンスの台数を示しています。自然に中断されるのに任せて何も操作はしていません。赤紫色で示したインスタンスが中断されるという具合に、わずかに時間をずらしつつインスタンスが減っているのがわかると思います。スポットインスタンスのみで安定したサービスを提供するにはこのように中断されるスポットインタンスですが、これを用いて安定したサービスを提供する方法を紹介していきます。ここでは、スポットインスタンスのみを用いてサービスを提供した場合の故障率について計算してみます。サーバの運用では、突発的な負荷の増加やインスタンスの故障に備えてある程度のリソースを残しておくのが普通です。台数を増減させたりするのではないでしょうか。仮に目標のCPU使用率を50%に設定したとしましょう。その場合、たとえ中断されたとしても、そのリソースが半分以下にならなければ、サービスに影響が発生しないことになります。(計算を簡単にするために、突発的な負荷の増加や故障が、スポットの中断と同時に発生するという不幸はここでは考えないようにします)あるスポットインスタンスが中断されても、新しいインスタンスは数分あれば起動してきますので、その起動してくるまでの間の数分間にインスタンス台数が半数を割り込むことが無ければ、サービスは安定して提供できることになります。実測値を元に故障率を計算ここからは、プール数と故障率の関係について、実測値を元に統計的な計算を試みようと思います。DeNAで使用しているリージョンで、スポットインスタンスが比較的多めに中断された期間を紹介しましょう。ここで紹介している数値は使用されるインスタンスタイプや時期、リージョン毎に異なると思われるので、この数値をそのまま信用せずに各自でデータを取得するのがよいでしょう。・ニューイヤーセールここから統計的な数値を出すために、モデル化を試みます。これらの期間を1時間毎に区切り、その中でインスタンスがすべて中断されたプール数を数えていきました。枯渇したプール数を、使用していたプール数で割ることで、1プールあたりの枯渇確率を求めます。確率でプール枯渇が発生しうるという結果になりました。同じインスタンスサイズであれば同時に枯渇しやすいという傾向はありましたが、概ね独立していました。この数値を前提に、プール数別の故障率を計算していきましょう。目標CPU使用率が50%の場合、8プール中4プールまでは同時に枯渇しても問題なし、5プール以上が同時に枯渇したら故障(=サービス影響発生)として、捉えることができます。独立した複数の事象が同時に発生する確率は二項分布で計算可能です。今回の場合は15%の確率で発生する事象が8個中5個以上、同時に発生する確率を求めればよいことになります。求めることができますので、お手元で実施される場合はこれを利用するとよいでしょう。これを8個中6個の場合、8個中7個の場合、8個中8個の場合を足し合わせたものが、今回求めたい確率です。DeNAで1年間スポットを運用して、ここで数えたような複数プール枯渇が発生した回数は年間30回程度でした。いう形で計算可能です。目標CPU使用率50%における、プール数別の平均故障間隔(MTBF)を計算しましたので、以下に示します。いったように、インスタンス台数や重要度も天秤にかけながら個別に調整しています。これらの数値を実測値に基づき定期的に見直し、どの程度の比率までスポットインスタンスを用いても問題ないかをチェックしながら運用しています。ちなみにリソース枯渇は2019年後半から比較的少なくなってきました。復旧時間も含めて計算すれば可用性の数値も出せますが、オートスケールを使用している場合は即座にインスタンスが足されて10分程度でサービスが復旧しますので、可用性としての数値は非常に高くなってしまいあまり意味をなさないので、ここでは割愛します。プール数を増やすための工夫として、大きさの異なるインスタンスタイプを混ぜて使用しています。具体的には、C5.2xlarge、c5.4xlarge、c5.9xlargeのインスタンスに、それぞれIPアドレスを1つ、2つ、4つ付与し、そのIPアドレス宛に負荷分散することで、プール数を増やしつつもインスタンスに均等に負荷を与えるような仕組みを作って運用しています。このような仕組みを整えれば、旧世代のインスタンスを混ぜなくとも、プール数20は比較的容易に達成できます。グループだけではその実現は難しいので、多少の独自実装が入ってしまいますが、それこそがエンジニアの腕の見せ所でしょう。最後に本日はスポットインスタンスを用いてサービス提供した際の平均故障間隔についてご紹介しました。エンジニアは新しい仕組みを導入するときに、その影響を関係各所に説明し、同意を得た上で推進することがあると思います。この記事がそういったことの一助になれば幸いです。おいて、クラウドコスト削減の実践をテーマに登壇させていただく予定です。ここでは書ききれなかったコスト削減の手法について紹介しますので、こちらも是非見にきてください。