Kubernetes v1.37:メモリQoSがベータに昇格
日本語
コピー
Memory QoS は Kubernetes v1.37 で Beta に昇格し、デフォルトで有効になった。cgroup v2 を動かす Linux ノードでは、この機能によってカーネルがメモリコントローラーを通じてコンテナメモリをより正確に扱えるようになる。v1.22 で Alpha として導入され、v1.36 で階層的なメモリ予約によって拡張された。
本記事では v1.37 での変更点、Beta 昇格がクラスタ運用者にとって何を意味するのか、そしてこの機能の設定方法を説明する。
v1.37 での変更
Memory QoS が Beta になりデフォルトで有効化
MemoryQoS フィーチャーゲートは v1.37 で Beta になった。つまり、すべての v1.37 kubelet で、設定を一切変更しなくてもこのフィーチャーゲートが有効になっている。デフォルトで有効にしても安全なのは、デフォルトの kubelet 設定ではメモリスロットリングもメモリ予約も有効にならないからだ。明示的に設定しない限り、memory.high、memory.min、memory.low の値が cgroup に書き込まれることはない。
有効にする動作は kubelet 設定フィールドで選ぶ。
memoryThrottlingFactorを設定すると(例えば0.9)、Burstable と BestEffort のコンテナでmemory.highスロットリングが有効になる。デフォルト値はnullで、スロットリングは行われない。memoryReservationPolicyをTieredReservationにすると、memory.minとmemory.lowを通じて階層的なメモリ保護が有効になる。デフォルト値はNoneで、メモリ予約は行われない。
デフォルトの memoryThrottlingFactor が null に
以前の Alpha 版では memoryThrottlingFactor のデフォルトは 0.9 だった。つまりフィーチャーゲートを有効にするだけで、kubelet がコンテナに memory.high を設定していた。v1.37 ではデフォルトが null になったため、値を設定しない限り kubelet は memory.high を設定しない。
この変更の理由は、フィーチャーゲートがデフォルトで有効になったことにある。memory.high を自動で設定すると、本来スロットリングされないはずのワークロードがスロットリングされるおそれがある。null にしておけば、v1.37 へアップグレードしても既存クラスタの実行時の挙動は変わらない。
kubelet 設定ファイルに memoryThrottlingFactor の値がすでに明示的に書かれている場合、その値はアップグレード後も維持され、スロットリングもこれまでどおり有効になる。設定ファイルに memoryThrottlingFactor がなければ、kubelet は新しいデフォルト値 null を採用し、memory.high を設定しなくなる。この場合にスロットリングを維持したいなら、memoryThrottlingFactor を明示的に追加する:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
memoryThrottlingFactor: 0.9
v1.37 で MemoryQoS を設定する方法
Memory QoS の設定の詳細は Memory QoS with cgroup v2、Configuring memory reservation、System requirements を参照してほしい。
メモリスロットリングのみを有効にする
memoryThrottlingFactor を 0 から 1 の間の値に設定する。kubelet はこの係数を使って Burstable と BestEffort のコンテナの memory.high を計算する。QoS クラスごとの memory.high の計算方法は Memory throttling を参照。
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
memoryThrottlingFactor: 0.9
メモリスロットリングと段階的な予約を両方有効にする
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
memoryThrottlingFactor: 0.9
memoryReservationPolicy: TieredReservation
段階的な予約のみを有効にし、スロットリングはしない
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
memoryReservationPolicy: TieredReservation
Memory QoS を完全に無効にする
アップグレード後にこの機能を無効にしたい場合は、フィーチャーゲートを false に設定し、kubelet の設定に矛盾がないことを確認する。memoryThrottlingFactor が元のデフォルト値 0.9 以外に設定されている場合、または memoryReservationPolicy が TieredReservation の場合、kubelet はその設定を拒否する。これらのフィールドを設定していたなら、削除するか調整すること。
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
featureGates:
MemoryQoS: false
フィーチャーゲートが無効の場合、または memoryReservationPolicy が TieredReservation でない場合、kubelet は cgroup v2 ノードの起動時に残存する保護設定をリセットする。対象はルート kubepods cgroup の memory.min=0 と memory.low=0、および Burstable QoS cgroup の memory.low=0 だ。コンテナについては、再起動や resize などの調整パスで残った memory.high の値が max にリセットされる。
既知の制約: メモリ予約はノード単位
memoryReservationPolicy はノード上のすべての Pod に作用する。TieredReservation を有効にすると、Guaranteed Pod はすべて memory.min を、Burstable Pod はすべて memory.low を受け取り、個々の Pod がオプトインやオプトアウトをすることはできない。ハード予約が必要なワークロードと、回収可能なままにしておくべきワークロードが同じノードに混在している場合、どちらか一方のポリシーを両方に適用するしかない。
ハード予約はコンテナの cgroup に計上されるものすべてを対象にし、ページキャッシュも含まれる。そのため、大きなファイルを読む Pod がメモリを抱え込み、カーネルが隣の Pod のために回収できたはずのメモリを解放しないことがある。
SIG Node はこれら 2 つの問題を kubernetes/kubernetes#140246 で追跡しています。影響を受けている場合は、その issue でワークロードについて説明することをおすすめします。
今後の予定
Memory QoS の次のマイルストーンは GA への昇格です。Beta 利用者からのフィードバック次第で、そこに至るまでに必要な調整が決まります。問題が発生した場合は kubernetes/kubernetes で bug を報告してください。
さらに詳しく知るには
- KEP-2570: Memory QoS
- Pod のサービス品質クラス
- cgroup v2 での Memory QoS
- コンテナのリソース管理
- Kubernetes における cgroups v2 のサポート
- Linux カーネル cgroups v2 ドキュメント
参加する
この機能は SIG Node が推進しています。コントリビュートやフィードバックに興味があれば、以下の方法で連絡できます。
- Slack: #sig-node
- メーリングリスト
- SIG Node ミーティング