AWS の IOPS と I/O クレジットがよくわからなかったので整理した

最近 AWS を触り始めて、EBS を使っているのだが、どうも I/O 速度に制限がかかる仕様があるらしい。調べてみると IOPS やら I/O クレジットやらといった考え方が出てきた。ドキュメントを読んでもわかりづらかったので整理してみた。

そもそもの前提

AWS のボリュームでは無尽蔵に I/O を発生させることはできず、AWS 側で帯域制限ならぬ I/O 制限が実施されている。

この制限が具体的にいつ、どのように、どれだけ働くのかという仕組みが I/O クレジット という考え方。この時に使う単位が IOPS(I/O per Second) で、読んで字の如く「1秒間のI/O数」を表す。

最初に結論

速度制限について1:

  • I/O 回数は I/O クレジット残数(IOPSで表現される)が枯渇すると制限が加えられる
  • 制限値は「ボリューム 1 GB あたり 3 IOPS まで」
  • この制限は I/O クレジットが回復したら(またクレジットを使い切るまでは)緩和される

速度制限について2:

  • ボリュームの種類毎に最大 IOPS が定められており、これを超える速度は出せない
    • 例: 汎用 SSD (gp2) だと 10000 IOPS

I/O クレジットの補充/消費ルール:

  • [減る] ボリュームで 1 秒間に n 回 I/O を行うと、n [IOPS] が消費される
  • [増える] 初期状態では 540 万 IOPS が付与される
  • [増える] ボリューム 1GB あたり 3 IOPS が、1 秒毎に補充される

I/O 1回カウントのルール:

  • SSD は 256KiB 毎、HDD は 1024KiB 毎の読み書きが 1 I/O になる
  • ただしランダムアクセス時は上記の 256 or 1024 毎が適用されない
  • 以下 SSD の例:
    • 連続アクセスの場合、読み書き量が n [KiB] なら I/O 数は Ceiling(n/256)
    • ランダムアクセスの場合、アクセス数が k 回、各アクセスにおける読み書き量が n [KiB] なら I/O 数は k * Ceiling(n/256)

上記を踏まえて心がけること:

  • I/O クレジットが枯渇すると I/O 速度落ちるので、クレジット消費ペース等を事前に計算した上で、必要ボリューム数やサイズ等を設計しましょう
  • 上限 IOPS も ボリュームの種類 毎に定まっているので、ユースケースに適した種類を選びましょう
  • CloudWatch を使えば I/O クレジットの消費状況をウォッチできます。また必要なら「しきい値を超えた時にアラートを出す」ことも可能のようです(まだ使ってないのでよくわかりません)

以下各ルールや仕様の細かい話が続く。

I/O クレジットその1: 消費と補充のルール

io_credit_bucket_model

出展: Amazon Web Services ブログ: 【AWS発表】新しいSSDベースのElastic Block Storage

わかりやすそうでよくわからない図だが、要するに IOPS の補充/消費ルール について以下のようなことを言っている。

  • [減る] ボリュームで 1 秒間に n 回 I/O を行うと、n IOPS が消費される
  • [増える] 初期状態では 540 万 IOPS が付与 される
  • [増える] ボリューム 1GB あたり 3 IOPS が、1 秒毎に補充 される

要するに、普通は減る一方の I/O クレジットだが、最初に540万ほど付与される&毎秒少しだが補充されるという話。

I/O クレジットその2: クレジットが枯渇したら

続いて I/O クレジットが枯渇したら(ゼロになったら)どうなるかという話。

結論を言うと ベースラインパフォーマンス にまで I/O 速度が引き落とされる。ベースラインパフォーマンスとは、上記の 1 秒毎に補充されるペースと同じ値。つまり ボリューム 1GB あたり 3 IOPS

一つ例を挙げる。

例1: 100 GB のボリュームを使っていて I/O クレジットが枯渇した場合

この時、1000 IOPS(秒間1000回のI/O) を発生させようとしても、ベースラインにまで落とされてしまうため、実際は 300 IOPS の速度となる。ベースラインにまで落とされたくなかったら、I/O クレジットが補充されるのを待つしかない。

I/O クレジットその3: IOPS には上限もある

ここでふと疑問が生じる。「じゃあ(I/Oクレジット使い切るまでは)めちゃくちゃバーストさせてもいいの?」と。たとえば 100 万 IOPS(1秒に100回のI/O)を発生させてもいいのか。

結論を言うと 別に構わないがバーストにも上限が定められている

上限値は ボリュームによって異なる が、一例を挙げると 2018/06/25 時点で以下のようになっている。

ボリューム種類 上限(ボリューム毎) 上限(インスタンス毎)
汎用 SSD (gp2) 10000[IOPS] 80000[IOPS]
プロビジョンド IOPS SSD (io1) 32000[IOPS] 80000[IOPS]

たとえば「汎用 SSD (gp2)」ボリュームを使った場合、たとえ I/O クレジットが十分であっても 1 ボリュームあたり 10000 IOPS(秒間1万回のI/O)以上の速度を出すことはできない。また、1 インスタンスに 10 個のボリュームを繋いでいたとしても、10 個それぞれで 10000 IOPS を出すことは叶わない(計 80000 IOPS 分までしか出ない)。

I/O クレジットその4: IOPS の I/O ってそもそも何?

IOPS は I/O per Second だと述べたが、そもそもここでいう I/O とは何を示しているのか。何をどうしたら 1 I/O とみなすのか。

詳しい話は I/O の特性とモニタリング - Amazon Elastic Compute Cloud に書いてあるが、要するに

  • 「最大サイズ」分の I/O 操作1回分を 1 I/O とする
  • 「最大サイズ」はボリューム種類によって異なる
    • SSD: 256KiB
    • HDD: 1024KiB
  • 連続した読み書きはなるべく最大サイズになるまでマージされる
    • 例1: SSD で 32 KiB の連続する 7 個のデータを書き込んだ → 1 I/O
    • 例2: SSD で 32 KiB の連続する 8 個のデータを書き込んだ → 1 I/O
    • 例3: SSD で 32 KiB の連続する 9 個のデータを書き込んだ → 2 I/O
  • 連続しない(ランダムな)読み書きはマージされない
    • 例1: SSD で 32 KiB のデータをランダムアクセスで 7 個読んだ → 7 I/O

つまり(SSDを例にすると) 256KiB 分の読み書き一つが 1 I/O になる ということ。連続した 1MB のデータなら 4 I/O、1GB のデータなら 4096 I/O、10GB なら 40960 I/O。

仮に 10 GB のデータを 40 分でコピーした場合、コピー元ボリューム(コピー先ボリューム)では 40960 / 60*40 = 40960 / 2400 ≒ 17 [IOPS] 17 IOPS の読み込み(書き込み)操作が発生したことになる。

参考