- 最も早く登場したIOバンド幅コントローラ
- システム管理者がそれぞれのcontrol groupにたいしてバンド幅上限を設定する
- デバイスが暇しててもIOを律速してしまうためIOバンド幅が無駄になってしまう
- 次に登場したio.latencyコントローラ
- IOのレイテンシに着目
- 最もレイテンシの小さいcgroupを守るためなら他のcgroupsを犠牲にする
- io.weight は work-conserving propotional controller に基づいた I/O コストモデルの実装.
- work-conserving とは,制御対象リソースをフル稼働させるように頑張ること
- IOの制御で難しいのはコストを測る自明な指標が無いこと
- IOの制御でよく使われるのはバンド幅とIOPS
- これはデバイスの種類とIOパターンによって使えなくなることがある
- いくつかの主要な属性を仮定すれば,与えられたIO列のコスト見積が完全に謎かというとそうでもない
weight値
- それぞれのcgroupに weight という値を割り当てる
- weight値は階層的・相対的な値
- グループA = 100,グループB = 300 → グループBは75%のバンド幅を使える
- 各グループが実際に使えるバンド幅の割合は,同じ階層のweight値の合計に対する比率で決まる
root
/ \
A B
/\ /\
C D E F
キャパシティ計算
- 各グループが現在使っているキャパシティ(バイト数ではなく,能力という意味)をどう決定するか
- 単なるIOPSやバンド幅では不十分
- io.weightでは新しいコストモデルを使う
新コストモデル
与えられたリクエストの実行に必要となるデバイスの実行時間を見積もる
-
まず,リクエストがシーケンシャルかランダムかを決める
- 実際はグラデーションだけど,そこはモデル単純化のために2値で判定する
-
基本コスト = シーケンシャル/ランダムに応じた固定値。シーケンシャル < ランダム
-
新コストモデルの計算結果 = 基本コスト + 転送されるページ数に応じたコスト
-
デフォルトでio.weightコントローラはデバイスの挙動を見てパラメータを決定しようとする
-
手書きすることもできる
- 最大スループット
- シーケンシャルとランダムの最大IOPS
-
デフォルトのコストモデルに満足できないならBPFでフックして任意のコストモデルを指定できる
vtime
io.weightコントローラの核となるタイマー
- 各デバイスにvirtual clock(= vtime)を割り当てる
- vtimeは通常は現実の時間と同じ早さで時を刻む
- 各control groupもvtimeを持つ
- IO要求のコストを決定しグループのvtimeに加算する
- グループのvtime < デバイスのvtime → IO要求を送信できる
weight値とコストの関係
- グループに割り振られたweight値を用いて,IO要求のコストのスケールを行う
- 上図のグループAは総バンド幅の25%を割り当てられている
- そのためグループAが発行するIO要求のコストは4倍される
- → グループAのvtimeはグループBのvtimeより4倍早く進む
バンド幅の貸し借り
- IO要求がたまっているのにデバイスが暇するのを避けたい
- 割り当てられたバンド幅を使い切ってないグループがあればそのグループのweight値を必要量まで一時的に低下させる
- 結果として,未使用のバンド幅を,その時バンド幅を必要としているグループに貸し出すことになる
- バンド幅がたくさん必要になったとき,貸し出したバンド幅を取り戻す仕組みも入っている
デバイスvtimeの調節
- コストモデルは完全ではない
- デバイスの性能は経年劣化したりする
- コストモデルが現実と乖離すると,io.weightコントローラが発行するIO量が過剰/過小になる
- 過剰: レイテンシが増加する
- 過小: 未使用のバンド幅が無駄になる
- デバイスが過負荷の場合,デバイスのvtimeの進行を遅くする
- IO要求がゆっくりとデバイスに送られるようになる
- デバイスが暇な場合,デバイスのvtimeの進行を早める
手動スケーリング
- vtimeの調整を自動でやろうとする -リクエスト完了時間が増大したらIO量が過剰になっていると判断する
- 状況によっては自動調整は適さない
- 書き込み要求がデバイス自身でキューされ,デバイスの判断した順序で処理される場合
- io.weightコントローラはIO要求のレイテンシを制御できなくなる
- これが嫌なら,バンド幅を犠牲にしてデバイスに送るIO量を減らすように設定することもできる
root cgroupにのみ存在するQoSに関する設定
====== =====================================
enable Weight-based control enable
ctrl "auto" or "user"
rpct Read latency percentile [0, 100]
rlat Read latency threshold
wpct Write latency percentile [0, 100]
wlat Write latency threshold
min Minimum scaling percentage [1, 10000]
max Maximum scaling percentage [1, 10000]
====== =====================================
8:16 enable=1 ctrl=auto rpct=95.00 rlat=75000 wpct=95.00 wlat=150000 min=50.00 max=150.0
-
MAJOR:MINOR = 8:16のデバイスに対する設定
-
enable=1: weightをもとにした制御を有効にする
-
ctrl=auto: カーネルがパラメタを自動決定する
-
rpct=95.00 rlat=75000: readレイテンシの95パーセンタイルが75msを超えたらデバイスが飽和したとみなす
-
wpct=95.00 wlat=150000: writeレイテンシの95パーセンタイルが150msを超えたらデバイスが飽和したとみなす
-
min=50.00 max=150.0: 全体のIO発行レートを50%から150%の間で調整する
-
飽和点を下げる(おそらく,rlatやwlatを下げることを意味している)と,レイテンシのQoSは向上する
- バンド幅が無駄になる
-
minとmaxの範囲を狭めると,コストモデルに忠実になる
root cgroupにのみ存在する設定
====== =====================================
ctrl "auto" or "user"
model The cost model in use - "linear"
[r|w]bps The maximum sequential IO throughput
[r|w]seqiops The maximum 4k sequential IOs per second
[r|w]randiops The maximum 4k random IOs per second
====== =====================================