[レポート] NFX304 Capacity plan optimally in the cloud #reinvent #reinvent2022

不確実性が高いキャパシティプランニングにおいて後悔の少ない選択をするにはどうしたらいいか? Netflix 社の事例が役に立ちます。
2022.12.17

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

こんにちは。
ご機嫌いかがでしょうか。
"No human labor is no human error" が大好きな吉井 亮です。

セッション名 : Capacity plan optimally in the cloud

概要概要(機械翻訳) : AWSは何百種類ものAmazon EC2オプションを提供しており、NetflixはCPU、RAM、ディスク、ネットワークの異なる組み合わせを必要とする多数の異なるステートフルおよびステートレスワークロードを持っています。このセッションでは、Netflixがサービスキャパシティモデリングシステムを使用して、CassandraデータベースからステートレスJavaアプリケーションまで、さまざまな不確実なワークロードを実行するためにAmazon EC2を最適に利用する方法について学びます。

スピーカー : Joseph Lynch, Principal Software Engineer, Netflix
Joseph Burba, Senior Solutions Architect, AWS
Prateek Sharma, Senior Solutions Architect, AWS

レポート

Netflix がどのようにキャパシティモデリングを行うかについて、これから1時間一緒に学んでいきましょう。
AWSには多くのEC2ファミリーとインスタンスタイプがありますね。
Joey と彼のチームは、データベースシステムからステートレスJavaアプリケーションに至るまで任意のワークロードに最適なEC2リソースを選択する方法をモデル化する素晴らしいシステムを作りました。
これは彼のチームが開発した本当にクールなシステムで、皆さんもきっと楽しい時間を過ごせるでしょう。もっと学ぶことができると思います。

Outline

今日は、Netflix がクラウドでどのように最適なキャパシティプランを立てているのか、少し紹介したいと思います。
いくつかの数学に飛び込んでいきますが、難しい数学ではなく良い数学であることをお約束します。

どのように特徴付けるか?どのようにワークロードを計画するか?そして、正しい選択をしているかどうか、どのように監視するのか?
今日はモデルについてたくさん話しますが、モデルについて私が知っていることの1つは、モデルが真実であることはほとんどないということです。 しかし時には役に立つということです。

話を始める前に、オープンソースのプラグインを紹介したいと思います。

Netflix's Skunkworks GitHub

講演中、関連するコードへのリンクを少しずつ貼っていきますので、本当にコードに飛び込みたい方は、ここでも後でもどちらでもどうぞ。

さて、このトークはこの方程式を中心に展開される予定です。ワークロードのキャパシティモデルがあります。 このワークロードは、ステートレス Java アプリのような単純なものから、1秒間に数百万のリクエストを処理する Cassandra データベースのような複雑なものまであります。

このワークロード容量モデルには、ユーザーの要望が入力されています。
ユーザーは、「このような容量のデータベースが欲しい」というような情報を私たちに提供します。
そして、それをハードウェアのプロファイル(ハードウェアを説明する方法)と、そのハードウェアに対する現在の価格とライフサイクルとで構成します。
後ほど説明しますが、この情報は非常に動的で、システムを使用するユーザーによって大きく異なります。
そして、ワークロード容量モデルによって、購入する具体的なコンピューターの最適化された候補を出力することができます。

Understanding hardware

まずはコンピュートを理解しましょう。
このページを見たことがある人は?全員だと望んいます。ここは AWS re:Invent だぜ。Come on!

このページに行くと、たくさんのオプションが表示されます。
私のワークロードはコンピュートなのか、それともメモリなのか、ストレージなのか?どれを選べばいいのでしょうか?

そして、タブを選ぶと、世代やサイズ、クラス、アーキテクチャの違いなど、さまざまな問題が出てきます。
大きなコンピューターがいいのか?小さなコンピューターが欲しいですか?
人間であれば、これを見たとき、"うわー、これは選ぶべきものがたくさんあるな" と思うはずです。
で、おそらくググるだけでしょう。"みんなは何に使ってるの?"

でも、Netflix では、それはハードウェアを購入するベストな方法ではないと考えていました。

まず、このページに書かれている情報を具体化します。スクリーンショットには、「M5 よりも価格性能が15%速い」と書いてあります。
これが実際に何を意味するのかを数学的にモデル化し、再現性を持ってハードウェアを選ぶことができるように分解することができます。

そのコンピューターはいくらするのか、という質問もしなければなりません。リージョンによって価格が変わります。
リザーブドインスタンスを購入するなら、前払い、一部前払い、前払いなしを選択しなければなりません。

これは面白いと思ったのは、人間として139,000の選択肢の中から選ぼうとしていることです。
139,000もの選択肢を与えてくれるクラウドがあることは驚きですが、同時に少し怖い気もしますよね。 どうやって正しいものを選べばいいんだろう?

Hardware

分解してみましょう。

CPU、RAM、ネットワーク、ディスクの容量はどの程度なのか?

これらの CPU、NIC、ハードディスクがどれくらいの速度なのか?
現実には、すべてのCPUが同じように作られているわけではありません。ハードディスクはすべて同じ速度ではありませんし、ネットワークもすべて同じではありません。

現在のライフサイクルや価格も把握しなければなりません。
ライフサイクルは、M2 のような古いインスタンスタイプは立ち上げないといったことです。

そしてもちろん、価格も考慮します。

良いニュースは、最初の2つ (容量と速度) は測定できることです。最初の2つを科学的に測定します。そして最後の2つを提供すればいいのです。

Measure shapes

飛び込んでみましょう。
service capacity modeling library の m5d の説明の例です。
CPUはいくつあるのか?どのような周波数で動作しているか?RAMの実容量はどれくらいか?
ネットワーク帯域はどれくらいか?10ギガビットまでのキャパシティプランは立てられないことに気づきますね?

m5d のドライブの速さなど、かなりクールな内容も見えてきます。
このような情報は、正当な理由があって公開されないものです。クラウドプロバイダーは、基盤となるハードディスクを切り替えられるようにしたいし、特定の実装に縛られることも避けたいのです。
しかし、私たちがキャパシティプランを立てる際には、ハードディスクの速度を知っておく必要があります。

    "m5d.large": {
      "name": "m5d.large",
      "cpu": 2,
      "cpu_ghz": 3.1,
      "ram_gib": 7.48,
      "net_mbps": 500,
      "drive": {
        "name": "ephem", "size_gib": 70,
        "read_io_latency_ms": {"minimum_value":0.07, "low":0.08, "mid":0.12, "high":0.20, "maximum_value":2, "confidence":0.9, "single_tenant": false},
        "read_io_per_s": 30000,"write_io_per_s": 15000, "block_size_kib": 4 
      }
    },

では、実際に測定すればいいのか、具体的な例を挙げてみましょう。
まず、インスタンスを起動し、/proc から基本的なプロパティを収集します。
さらに興味深いのは、iperf、netperf、fio、ndbench といったベンチマークツール群を使用する点です。
私たちは負荷を生成し、それを測定します。bcc や bpftrace といったツールを使って、ネットワークやドライブの待ち時間の分布を測定することができます。

Measure disk latency

これはライブラリにあるヘルパーノートブックの1つのスクリーンショットです。

library/notebooks に行くと、負荷をかけながらディスクレイテンシーを実際に測定する方法の例があります。
それから biosnoop を使って、ディスクに当たっているすべてのディスク IO のレイテンシーを測定すると、このように素晴らしい分布を作り出すことができます。

これはいくつかの m5d インスタンスからの実際のデータで、濃い緑のボックスプロットは EC2 インスタンスからの実際の実際のデータです。
きれいな曲線はベータ分布のフィットで、収集したデータを使って、どのベータ分布がこのデータに最も合うかを調べました。
3点統計を共有すると、平均値110マイクロ秒、5パーセンタイル80マイクロ秒、95パーセンタイル160マイクロ秒のベータ分布になるんです。

この講演を通して、私たちは実際にこのトリックをよくやっていることがわかります。本当に複雑なものを取り上げて、ベータ分布でモデル化しようとするのです。

Measure network

ディスクに限ったことではありません。ネットワークも測定できます。

ネットワークの計測で唯一面白いのは、EC2 にはバーストという便利な機能があり、インスタンスが一時的にベースラインのプロビジョニングされたネットワークを超えることができることです。
これはインスタンスを起動するときやバックアップを取るときにとても便利な機能です。

これは非常に便利な機能ですが、長期的にコンピューターを購入しようとするときには問題です。なぜなら、このトップラインに基づいて意思決定を行うということになるからです。 このインスタンスでは、20分ほどバーストネットワークが表示されます。 ですから、テストを開始してすぐに測定すると、間違った値を得ることになります。バーストバケツを使い切るまで待って正確な値を測定します。

Hardware lifecycle at Netflix

Netflix はハードウェアのライフサイクルをどのように考えているのでしょうか?

私たちは一般的に、ハードウェアがこの段階を経て進歩していくものと考えています。つまり、新しいハードウェアを最初に起動するとき、私たちはそれをアルファと呼んでいます。
キャパシティプランナーは、アルファ版のハードウェアを勧めません。 アルファ版ハードウェアは、純粋に私のような、実験をすることに興奮する人たちのためのものです。

そして、一般的な開発者がハードウェアを目にするようになるのは、Beta や Stable になったときで、これは特定のインスタンスタイプが Netflix の本番環境で使われ始めたときです。安定版とは、通常、複数年の予約購入に全く問題がないことを意味します。

Netflix で起動する可能性のあるあらゆるタイプのインスタンスのライフサイクルや価格設定を一元管理するサービスも提供しています。

サービスキャパシティモデリングシステムは、インスタンスのコストを知るだけで良いのです。
リザーブドインスタンスかオンデマンドかは気にすることなく、このインスタンスを立ち上げるために AWS へ現在いくら払うのか、知るだけです。

User Input

もう少し複雑な問題に対処する必要があります。つまり、ユーザーは何を望んでいるのかをどのように教えてくれるのでしょうか?
ユーザーの欲求は、冒頭の方程式にとって重要な要素です。ユーザーが何を望んでいるかがわからなければ、答えはでません。しかし、ユーザーのインプットはおそらくそう簡単には得られません。

現実には、ワークロードに必要な CPU、RAM、ネットワーク、ディスクスペース、ディスク IO がどれくらい必要なのか、おそらくわからないでしょう。
Netflix で気づいたのは、彼らはおそらく桁違いの見積もりを知っているということです。つまり、彼らが送信するQPSの正確な数は分からないということです。
でも、ペタバイトかギガバイトかくらいは知っているはずです。1秒間に1万回なのか、10万回なのか。1秒間に1万個なのか、10万個なのか。そのため、私たちはユーザーからの入力を「インターバル」という言葉で表現しています。

User intervals

これは、ユーザーが値ではなく間隔で入力することの威力を示したいスライドです。
「10,000 QPSで計算します」と言う代わりに、「1000 QPSで、5パーセンタイルは100、95パーセンタイルは9,990です」と言うことができるのです。
そして、この右肩下がりの青い分布を画面に当てはめることができるのです。

ベータ分布の本当に素晴らしい点の1つは、ほとんどすべての一般的な統計分布を近似できることです。
正規分布に馴染みのある方はいらっしゃいますか?
正規分布、ユニフォーム、そう、ベータは究極の分布のようなものです。 緑色のものは、一様分布に非常に近いです。
区間を非常に狭くすることで、デルタを直接モデル化することができます。
また、紫色の分布は、基本的に正規分布にシフトしています。
このようにベータ分布は、多くの異なるタイプの区間入力を捕らえることができ、多くの異なる複雑な入力を捕らえることができるので、非常に便利です。
このモデルでそれを大いに活用することにしよう。

Capacity desires

キャパシティ欲求にダイブしてみましょう。

3つの入力があります。

  • service_tier
    • このクラスタはどれくらい重要なのか、どれくらいクリティカルなのか?
  • query_pattern
    • どのようにクエリを実行するのでしょうか?
    • クエリパターンは何ですか?
    • どのようなQPS?
    • どのようなアクセスパターンなのか?
  • data_shape
    • どのようなデータを使って、我々が言うところのデータ形状を計算するのか?

What is Service Tier?

Service Tier は私たちが大量のコンテキストを包むために用いる1つの数値です。
もっと具体的に言うと、どれだけ過剰にプロビジョニングするかというトレードオフです。
夜中の2時に起こされないために、どれだけのお金をこの問題に投じればいいのか?

ティアリングについて、これまでNetflixでは、「本番環境は重要で、テスト環境は重要でない」と言われてきました。しかし、それは誤りであることがわかりました。
例えば、アーティファクトストアや CI/CD システムを動かすデータベースもテストにあります。 これらは非常に重要です。これらは、たとえ本番環境でなくても、組織にとって非常に重要なものです。

Query pattern

クエリパターンについてです。
クエリパターンはアクセスパターンのようなものです。

これはレイテンシーでしょうか?スループットなのか?どのような一貫性を期待されているのでしょうか?このワークロードに強い一貫性を求めているのでしょうか? 強力な一貫性は、偶発的な一貫性よりも高価であることがわかりました。
また、ユーザーはおそらく、1秒あたりの読み取りと書き込みの推定値を教えてくれるはずです。

"QPSはいくつですか?"という質問だけにしておくこともできます。
もう一方では、非常に洗練された、ありとあらゆるクエリパターンを教えてもらうこともできます。

最後に、非常に重要なインプットとして、読み取りと書き込みにどれくらいのコストがかかるか、ということがあります。
例えば、SQLデータベースの場合、読み込みにかかるCPU時間がかなり制限されています。
ですから、CPU時間に対する平均読み込みレイテンシと平均書き込みレイテンシは、キャパシティプランニングにとって非常に重要なものなのです。
しかし、おそらくプロビジョニングをお願いしている人は、これらの数字を知らないのです。
そして重要な洞察は、ワークロードの作成者がおそらく知っているということです。Memcached モデルや Cassandra モデルを書いている人は、そのワークロードについて非常に経験が豊富で、「10万QPSを処理し、CPUにこれだけの時間を費やしているので、割り算をしてこれらの間隔を得る」というメトリクスを知っているはずです。

Stateful data shape

さらに深く掘り下げると、これらのユーザーの要望は、ユーザーが伝えるものと、ワークロード・プロバイダーがデフォルトで提供するものの合成であることがわかります。

ユーザーはおそらく、推定される状態サイズを知っているはずです。
しかし、そのデータに対してデータベースがどのような圧縮率を適用するかは、おそらく知らないでしょう。

Cassandra は特定の圧縮アルゴリズムを使っていて、通常2対1から3対1の圧縮率になりますが、Memcached はデータをまったく圧縮しません。 圧縮を考慮に入れないと、圧縮率のファクター分だけ過剰にプロビジョニングすることになり、スケールにおいては高くつきますから、これは重要です。

そして、それはさらに深いところにまで及びます。
例えば、JVMのような異なるワークロードは、ヒープ用にある量のメモリを必要とし、システム、例えばカーネルやこのインスタンス上で動作するサイドカーも、いくつかの予約メモリを必要とします。 なぜなら、そのワークロードを実行できる最小量のメモリを知る必要があるからです。

Example user input

スクリーンショットでは、サービスティア1のクエリーパターンで、1秒あたりの読み込みが10,000、1秒あたりの書き込みが10,000、データサイズが100ギガバイトという予想値になっています。
100人に2人、あるいは50人に1人の割合で、10倍以上の誤差が生じると考えています。
これはかなり安全な推定値であり、これらをベータ分布にマッピングすることができます。

さて、1秒あたりの読み取り回数、1秒あたりの書き込み回数、ステートサイズは人間が入力しました。
そして Service Capacity Modeling は圧縮、読み取りサイズ、読み取りサイズ、書き込みサイズをもたらすでしょう。

Capacity planning with certainty

さて、コンピュータについて正確に知り、ユーザーの欲求についてどう考えるかについて正確に知ったところで、実際にどのように容量計画を行うつもりなのでしょうか?
では、キャパシティプランニングを行いましょう。

今まで正しい入力ができましたので、次は正しい計算が必要です。心配しないでください、簡単な計算です。
心配しないでください、簡単な計算です。ライブラリにある関数を呼び出せばいいだけです。

Build a stateful model

さて、それではさっそく、ステートフルなモデルを構築してみましょう。

ステートフル・モデルは次のようなものです。

これは Cassandra のキャパシティ・モデルで、5つの具体的なインプットを取ります。

  • 特定のインスタンス・タイプ
  • 特定のクラウド・ドライブ
  • リージョン・コンテキスト(ゾーンがいくつあるかなど)
  • ユーザーの要望
  • 追加のモデル引数は、標準化できない要望を書き込むためのバックドアとなります

この関数の仕事は、オプションのキャパシティプランを返すことです。「なぜオプションなのか」と聞かれるかもしれません。
その理由は、T2 micro で毎秒100万のリクエストを走らせろと言われても、それがうまくいくクラスタは存在しないからです。
だからこれらのモデルは、「いや、ユーザーの欲求を満たすことはできない」というような返事をすることが許されているのです。

Build a stateless model

そして、ステートレス・モデルも全く同じに見えます。これがシステムの美しさです。
システムにあるワークロードを拡張していくと、インターフェースや実装方法は多かれ少なかれ同じようになります。 ただ異なるのは、各ワークロードがこのメソッドの内部をどのように計算するかということです。

Let's implement Cassandra

Cassandra の実装を少しずつ進めていきましょう。

Cassandra は Netflix の中で最も複雑なネットワーク、あるいは最も複雑なモデルだからです。 一般にデータベースは、キャパシティプランを立てなければならない最も複雑なソフトウェアです。
では、複雑なケースをどのように構築するか見てみましょう。

どのようにして CPU の数を決定するのでしょうか。2乗スタッフを使うことにします。
1秒あたりの平均リクエスト数と、1リクエストあたりの平均 CPU 時間を掛け合わせたものが R となります。
そして、それをサービス品質パラメーターに加え、Rの平方根を掛けます。
あるリクエストがサーバーにきて、実行するための空きCPUがない確率が1%未満であることが望ましいのです。それを Tier 0 サービスと呼びます。

ここの Q 値は2.375です。これはレイテンシーの代用品です。

これはどこから来たのでしょうか? MOR HARCHOL-BALTER 氏の「Performance Modeling and Design of Computer Systems」を強くお勧めします。 素晴らしい本です、ぜひお勧めします。

おそらく間違っているが役に立つかもしれない、いくつかの仮定を立てます。
この本は、M/M/kシステムを想定しています。つまり、イベントの到着がプラスで、応答時間が指数関数的に分布しているということです。
現実には、到着率やサービス時間が多少なりとも変わってくるでしょう。
M/M/kシステムで、平均応答時間の境界を設定することによって待ち行列の確率を束縛し、あとは通常の仮定の下で値Qを解けばいいわけです。 これはどういうことかというと、プラスオン分布と正規分布がなんとなく同じように見えると仮定しているわけです。

Network

次に、ネットワークにトライします。

Netflix では、かなり単純なネットワークモデルを使えることがわかります。
読み込みと書き込みの規模がどれくらいか、それぞれのレートを掛け合わせ、何らかのごまかしを加えるのです。
実際のところ、ごまかし要素は通常2つか3つです。バックアップや修理のために、ネットワークに余裕を持たせておくということです。
これはほとんどのデータストアでうまく機能します。

1秒あたりの読み込み量、読み込みサイズ、1秒あたりの書き込み量、書き込みサイズがわかっていれば、これらの数字を掛け合わせるだけです。

Disk

この2つはステートフルなサービスにしか適用されません。ステートレス・サービスを実行している場合は、この部分を無視してもかまいません。

ディスクは非常に特殊です。
例えば、Cassandra は特定のコンパクション戦略を使い、Elasticsearch は異なるマージ戦略を使うので、LSM ツリーがどのようにデータを配置するかによって、ユーザーの上にある無駄なディスクスペースの量が違ってきます。
ユーザーが100ギガを保存している場合、Cassandra はそれを実際に保存するために130ギガや140ギガを要するかもしれません。 これは、すべてのストレージ・エンジンと、そのデータのレイアウト方法と関係があるのです。

データのコピー数を入力サイズで掛け、それをいくつのゾーンに分割するかで割りそれに圧縮率をかけます。
これで、ゾーンごとにどれだけのディスクスペースがあるかがわかり、前の2つの数字に基づいて見積もりをすることができます。

EBS gp2 のようなネットワークドライブを使用している場合では、そのサイズの最大値を取り、必要なIOを得るために十分な帯域幅を確保する必要があります。

Memory

さて、いよいよ本題に入ります。これは私の「Memory is hard」のスライドです。全ては関数の集まりです。

メモリが大変なのは、メモリをどこに使うかという根本的なトレードオフがあるからです。 キャッシュによって読み込みを高速化するか、バッファリングによって書き込みを高速化するか、どちらかになります。

私の SQL ではバッファキャッシュがあり、Postgras ではページキャッシュがあります。Cassandra では、オンヒープメンバテーブルがあります。
読み込みに必要なRAMの量は、データサイズとワーキングセットの大きさに依存するわけです。

書き込みに必要なメモリの量は、書き込み帯域幅に依存します。また、圧縮戦略は、データストアがどのようにデータを中継しているかによって、フラッシュする頻度を減らすために必要なメモリの量に影響を与えます。

そして、ソフトウェア自体の特性もあります。
たとえば、JVMデータストアを使用している場合、書き込み帯域幅と読み取り帯域幅がJVMを通過するのに十分なメモリを確保する必要があります。

つまり、ノードごとに必要なメモリの量は、これらの構成要素に依存し、ワークロードごとに計算されるのです。 それを合計したものが必要なメモリ量になります。そして、これはノードの数に依存するため、少しトリッキーです。

Working set?

私は難しい話を忍びこませました。ワーキングセットです。

人々は自分が読むデータの量を知っていますか?自分がどれだけのデータを読むかなんて誰も知らないと思います。
この問題点は、ホットセットが分からないと RAM をどのように買ってよいか分からないはずです。

Netflix でこの問題を解決した方法は、質問を逆転させることでした。「ホットセットは何ですか」と聞くのではなく、 「私たちが持っているドライブのレイテンシーとレイテンシー SLO 、読み取りの速さを考慮して、どれくらいのメモリを購入する必要があるか?」と聞いたのです。

ここに NVMe フラッシュ・ドライブのディストリビューションがあります。これはとんでもなく高速です。典型的な読み取りレイテンシは120マイクロ秒で、とんでもなく高速です。
このドライブの前にメモリは必要ありません。

一方、EBS gp2は10倍遅いです。
一般的な読み取りレイテンシは1ミリ秒になります。低速のディスクは、レートをキャッシュするために、より多くのRAMを前面に必要とします。

Calculate from SLO

レイテンシーのサービスレベル目標を設定し、それをドライブのレイテンシー分布と比較して、次のように考えることができます。
SLO を満たさないドライブがある場合、「サービスが SLA や SLO を満たすことを保証するために、どれだけのメモリを買わなければならないか」と。

例えば、EBS gp2のP95レイテンシが1.35ミリ秒だとすると、P99のレイテンシが5ミリ秒の SLO を持つデータベースでは、SLO を満たすためにはデータの約45%を RAM に置くだけでよいことになります。

Netflisx が持つ Memcached のようなキャッシュとは対照的です。 我々のキャッシュは1ミリ秒以下のレイテンシ SLO を担っています。私たちはデータの100パーセントを RAM に置く必要があるのです。
キャッシュのワークロードでは、gp2 にはまったく頼れません。この洞察により、リードをキャッシュするためにどれだけの RAM を購入すればよいかがわかり、前進することができました。大成功です。
私たちはCPU、ネットワーク、ディスク、RAM を把握したのです。

私たちは特定のインスタンスタイプと具体的なユーザーの欲求に対してキャパシティプランを立てることができます。
しかし、問題があります。何十もの種類のクラウドドライブを考慮する必要があります。

解決策は?信頼できる "Forループ " です。

すべての異なる入力、すべての異なる可能なインスタンスをループして、絶対にデプロイしてはならないライフサイクルをフィルタリングすることができるのです。
それらをモデルに通して、それぞれのタイプについて、異なる種類の具体的なインスタンスのタイプを出力します。
12個必要だとします。r5d.2xlarge を買うなら、6個必要です。一番安いものを選ぶだけです。
直感的に、CPU、RAM、ネットワーク、ディスクの必要量はわかったなら、今の価格設定で必要なリソースを最も安く買うにはどうすればいいか、というように考えることができます。

Capacity planning with uncertainty

不確実性を考慮したキャパシティプランを作成します。 その方法はモンテカルロ法を使います。楽しいですよ。

実際に存在する世界を得ようとするのではなく、テールイベントに遭遇するのに十分なシミュレーションを行おうとしているのです。 そして、すべての世界の中で、最も後悔しないクラスタを選ぶのです。

Netflix では、お金を後悔しています。コンピューターの台数が少なすぎて後悔する、これをアンダープロビジョニングといいます。
100台のコンピューターを買うべきだったのに、10台しか買わなかった、やれやれ。

また、コンピューターを買いすぎたことも後悔しています。
これはお金の無駄遣いですよね?そのお金で『フレンズ』のエピソードをもっと作れたはずです。コンピューターにお金をかけたくはないのです。

また、オペレーターの時間もお金になるので、オペレーターの時間も後悔しています。ディスク容量がなくなったクラスタを夜中の2時に復旧させなければならないとしたら、それは会社にとって高くつきます。 だから、オペレーターの時間も使わなくて済むようにしたいのです。

価格やライフサイクルを自由に設定できるのと同じように、後悔のパラメータも自由に設定することができます。
オーバープロビジョニングをどの程度気にするか?停電はどの程度気にしますか? そして、他のすべての世界と比較して、この関数に対して最も後悔が少ない世界を「最小後悔」と呼びます。

この regret 関数はとてもシンプルです。パラメータを取ります。
買ったプラン、つまり買ったコンピューターのセットと、提案されたプランが必要です。
そして、この選択をどれだけ後悔しているかというのが、コストモデルです。例えば、このコンピューターを買うべきだったのに、実際にはこのコンピューターを買ってしまった。
それをどれだけ後悔しているかということです。

世界1で特定の入力セットが、6.6テラバイトの容量を持つ73,652ドルの i3en.xlarge コンピューターを48台買う計算をしたとしましょう。
世界2では、おかしな出来事がたくさん起こり、結局96台の r5.8xlarge 、646,309ドル、18テラバイトのディスクスペースという、非常に高価なクラスターを買うことになりました。

そして、後悔を計算することができます。世界1でコンピューターを買ったとしましょう。
しかし、私は世界2に住んでいます。そこで48台の i3en.xlarge を購入したのですが、実際は96台の r5.8xlarge が必要でした。
ディスク容量は6テラバイトを購入しましたが、18テラバイト必要でした。
これらを後悔の公式に当てはめれば、約1,000万ドルの後悔をすることになります。かつ、アンダープロビジョニングです。

逆の計算もできます。
世界1に住んでいて、世界2のコンピューターを買います。
48台の i3en.xlarge が必要なところ、96台の r5.8xlarge を購入しました。
約800万ドルの後悔をすることになります。

このことは、後悔は対称的ではないということを私たちに気づかせることになります。

定数の選択によって、アンダープロビジョニングとオーバープロビジョニングの相対的なコストが決まります。 このケースでは、前に提示したパラメータにより、オーバープロビジョニングのケースの方がオーバープロビジョニングのケースよりも後悔が少なかったのです。
しかし、1000回以上のシミュレーションをしてみると、それが正しい選択であることはほとんどないのです。

では、先ほどの例 (1万回の読み込み、1万回の書き込み、100ギガ) でシミュレーションをやってみましょう。

その結果の説明をします。
これに対する最も後悔の少ない選択肢は、12台の m5d.xlarges です。 コストはおよそ9,000ドルです。
このユースケースで興味深いのは、基本的に常に m クラスを購入していることです。
必要ないディスクを購入することがない m クラスを選んでいます。

さて、問題を難しくして、区間をとても大きくしてみましょう。
1秒間に10万から100万回の書き込みがあり、10~100テラバイトのデータを保存すると考えます。

一番後悔しない選択は、かなりリーズナブルな48台の i3en.xlarge で、だいたい73,000ドルくらいです。
ユーザーの入力があまり具体的でなかったので、こちらの方がバラツキがあります。 1秒間に10万~100万レートというのは、インターバルが大きいですね。

インターバルが大きい状態で最小後悔オプティマイザーを実行したときに何が起こったのか見てみます。

赤い線は48個の i3en.xlarge を選んだ世界のものです。
この世界では、1秒あたりの書き込み回数とデータサイズがわずかに増え、読み込みは少し高くなりました。

これはただ単に、平均から少し離れたところにあるカーブに偏った選択をすることで、リスクをヘッジしようとしているのです。
というのも、ユーザーの入力は非常に曖昧だったからです。

というわけで、これは素晴らしいことです。
不確実なユーザーの入力から具体的な後悔しない選択肢を出したのです。

しかし、もう一度最初に戻ってみてください。これは単なるモデルであり、モデルは間違っている可能性があります。 特に不確実なユーザー入力を扱う場合は、プロダクション開始後に正しい選択をしたかどうかを監視できるようにしなければなりません。

Monitoring choices CPU

では、CPU が十分かどうか、どのように監視するのでしょうか。
Netflix では、CPU ワーカーのキューイングを測定することで行っています。
私が知っているほとんどの場所では、CPU 使用率を監視していますが、それは間違っていると思います。使用率は、CPU をもっと買えば解決するのかどうか、実際には教えてくれないからです。

数年前のメルトダウン問題を覚えている人はいるだろうか。
メルトダウンはかなり大きな問題で、対策が進むにつれてすべてのCPUが遅くなったんです。
「データベースが遅くなったから、規模を拡大したい」と騒ぐ人が大勢いたんです。
そこで私たちが行ったのは、この指標を集めて、CPU キューがゼロになったグラフを見せることでした。
「すみません、あなたのデータベースは遅くなりました。CPU をもっと買っても、CPU 待ちの行列ができることはないので、何の役にも立ちません。」と。

2つのグラフがあります。
Tier 0はキューイングはありません、素晴らしいです。

Tier3では、どれくらいのキューイングが発生していますか?
だいたい30%くらいです。我々のモデルに合致しています。
このグラフを見て、「ああ、これなら大丈夫そうだ」と思いました。ティア3ではCPUを買い足す必要はありません。

この Tier 3のグラフを Tier 0 のシステムで見た場合、困ったことになります。スケールアップしてもっとCPUを買わなければなりません。

Monitoring choices Disk and Network

ディスクとネットワークについてはどうでしょうか?ディスクとネットワークの利用率として使うだけです。

ディスクスペースは非常に簡単です。実際に60%のディスクスペースを使用していて、30%のディスクスペースを使用したい場合は、ディスクを2倍にする必要があります。
しかし現実には、実際のデータがデータストアに入り始めるまで、それはわかりません。
良いニュースは、間違っているかどうかを簡単に知ることができることです。使っているディスク容量の大きさを測ればいいのです。そして、足りなければ、スケールアップすればいいのです。
EC2 の素晴らしいところは、間違いを犯したときに、そこから回復するのがそれほど難しくないということです。

ネットワークについても、同じことが言えます。
ネットワーク帯域幅、利用率、ベースラインネットワークのうちどれだけ使っているかなどを見ることができます。
興味深い作業パターンを見ることができます。例えば、1時間ごとにバックアップが実行されています。ネットワーク帯域幅を大量に使っています。
だからバーストは本当に便利なんです。

Monitoring choices Memory

さて、メモリはどうでしょうか。メモリは、あらゆるものと同様、最も複雑なものです。
十分なメモリがあるかどうかを測定するのは非常に難しいので、代わりに代理統計量を測定しています。

たとえば、読み込みに十分なメモリがあるかどうかを調べる場合、実際にメモリを測定するわけではありません。
もしページキャッシュがなかったり、ブロックキャッシュがなかったりして、ディスクの読み込みが大量に発生している場合、その読み込みを測定するのです。 というのも、もしページキャッシュやブロックキャッシュがなくてディスク IO が大量に発生しているなら、読み込みをキャッシュするのに十分なメモリを持っていない可能性があるからです。

bcc の cachestatのようなツールを使えば、カーネルが読み取りを行う際に、何パーセントの時間、キャッシュを逃したり、キャッシュに当たったりしているかを知ることができます。

Netflixでは、実際にはそこまで凝ったことはせず、/proc メトリクスを使用しています。

書き込みは少し複雑です。ほとんどのステートフルサービスが、書き込みをグループ化して、一度にフラッシュしてしまうことです。
そのため、IO なし、IO あり、IO なし、IO あり のようなデコボコのグラフができてしまいます。

私たちはステートフル・サービスがフラッシュ操作を行う頻度はどれくらいかを監視します。 通常は、10分に1回以下の頻度を目標にします。 手探りでやっているようなものですが、これが私たちのやり方です。
もし頻度が高すぎたり低すぎたりしたら、書き込み用のバッファスペースを調整するか、メモリを増設します。

What to do now?

これらのメトリクスを見ることで、ネットワークが足りない、CPU が足りない、ディスクが足りない、全部足りないというようなことを判断することができます。
EC2 の素晴らしいところは、おそらくあなたが使い果たしたものに対して正確に最適化するコンピューターを持っていることです。

例えば m5 クラスでネットワークが足りなくなったら、m5n クラスに切り替えて、より多くのネットワークを、CPU と同じ比率で使うことができるんです。

CPU が足りなくなったら、CPU に最適化されたインスタンスファミリーに移行すればいいのです。また、ディスクを使用している場合は、ストレージに最適化されたインスタンスファミリに移行することができます。

そして、もしすべてを使い果たしたら、スケールアップするしかありません。大きくするか、垂直にするか、どちらかです。
それはとてもシンプルなことです。使い切ったものを監視し、必要なものを買い足せばいい。

Conclusions

今日、私たちはハードウェアを理解しました。私たちはハードウェアを測定し、価格を決め、ライフサイクルを課しました。
そして、それらの具体的な入力に対して待ち行列理論を適用し、世界をシミュレートし、最も後悔の少ない世界を選ぶことができました。
そして、これだけ複雑なモデリングをしても、時には間違ってしまうことがあるのだと悟ったのです。
そして、間違ったときは、自分の選択を監視して、必要なものをもっと買えばいいのです。

繰り返しますが、このシステムはオープンソースで、プラグイン可能で、自分の情報を重ね合わせることができます。私たちの Skunkworks GitHub にあります。

ぜひ多くの人に見てもらいたいと思います。皆さんにチェックしていただけると嬉しいです。

ありがとうございました。

所感

不確実性が非常に高いハードウェアキャパシティプランニングにおいて、後悔の少ない選択をしている Netflix 社の事例紹介でした。
彼ら彼女らは独自のツールを開発し、独自のアルゴリズムに則ってキャパシティプランニングを行っています。このツールは公開されており誰でも使用可能です。

途中難しい話になりましたが、What to do now と Conclusions で話したもらったことが、我々のできるキャパシティプランニングの第一歩だと考えます。
クラウドの持つリソース伸縮性を十分に活かしていくこと、これをコツコツと実践していくことがリソース最適化の近道です。

参考

以上、吉井 亮 がお届けしました。