Kubernetes 1.22: SIG-Node (kubelet) 変更内容
Kubernetes 1.22が先月リリースされました。
SIG-Node関連の変更をCHANGELOGからまとめています。
📝 の部分は、私のコメントです。
What's New
Kubernetesノードのスワップサポート
Kubernetes 1.22のリリースでは、スワップメモリを使用してノードを実行するためのアルファサポートが利用可能になりました。この変更により、管理者はLinuxノードでスワップを構成することを選択でき、ブロックストレージの一部を追加の仮想メモリとして扱います。
📝 メモ
KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/2400-node-swap/README.md
ついにKubernetesでスワップが使えるようになりました。Podからスワップがどのように使われるかはSwapBehavior
という設定で決まります。
-
SwapBehavior
がLimitedSwap
(デフォルト)の場合- cgroups v1では、メモリとスワップの合計がresources.limits.memoryを超えないように制限される
- cgroups v2では、スワップが使えない
- これはcgroups v2では、メモリとスワップの上限設定が独立しており、メモリとスワップをあわせた量で制限できないため
-
SwapBehavior
がUnlimitedSwap
の場合- 制限なくスワップが使える(ホストシステムのスワップすべてを使える)
なお、今回のスワップサポートはノード単位の制御であり、Pod単位でスワップの利用をコントロールすることはできません。KEPによれば、BetaまでにPod単位でのスワップ量の制御をいれたいとのことです。
クラスター全体のseccompのデフォルト
新しいフィーチャーゲート(アルファ)SeccompDefault
が、対応するコマンドラインフラグ--seccomp-default
およびkubeletの設定とともにkubeletに追加されました。両方が有効になっている場合、seccompプロファイルを明示的に設定していないポッドのkubeletの動作が変わります。
クラスタ全体のseccompのデフォルトでは、kubeletはデフォルトで Unconfined
ではなくRuntimeDefault
seccompプロファイルを使用します。これにより、Kubernetesデプロイメントのデフォルトのクラスター全体のワークロードセキュリティを強化できます。セキュリティ管理者は、ワークロードにデフォルトでseccompが設定され、より安心して眠れるようになります。
この機能の詳細については、公式のseccompチュートリアルを参照してください。
📝 メモ
KEP: https://github.com/kubernetes/enhancements/tree/34fa3dd/keps/sig-node/2413-seccomp-by-default
seccompはプロセスが呼べるシステムコールを制限するLinuxカーネルのセキュリティ機構です。このseccompプロファイルのデフォルトを設定できるようになりました。
seccompプロファイルにRuntimeDefault
を指定すると、コンテナランタイムのデフォルトプロファイルが使われるようになります。例えば、containerdの場合、デフォルトプロファイルはここで定義されており、capabilityの設定などに応じて動的に決定していることがわかります。
PSP (PodSecurityPolicy)でもデフォルトのseccompプロファイルの設定が可能ですが、PSPは廃止予定となっています。
メモリリソースのQoS
もともと、Kubernetesはcgroups v1 APIを使用していました。この設計では、PodのQoSクラスはCPUリソース(cpu_shares
など)にのみ適用されます。 Kubernetes cgroup managerは、cgroups v1でmemory.limit_in_bytes
を使用してコンテナーのメモリ容量を制限し、oom_scores
を使用して、メモリ不足イベントが発生した場合にコンテナープロセスを強制終了する順序を設定します。この実装には欠点があります。Guaranteed
Podの場合、メモリを完全に予約できず、ページキャッシュがリサイクルされるリスクがあります。Burstable
Podの場合、メモリをオーバーコミットする(request
をlimit
未満に設定する)と、Linuxカーネルがメモリ不足状態を検出したときにコンテナが強制終了されるリスクが高まります。
アルファ機能として、Kubernetes v1.22はcgroups v2 APIを使用してメモリの割り当てと分離を制御できます。この機能は、メモリリソースの競合がある場合に、ワークロードとノードの可用性を向上させるように設計されています。
📝 メモ
PR: https://github.com/kubernetes/kubernetes/pull/102970
KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2570-memory-qos
カーネルのcgroup v2ドキュメント: https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html
cgroup v2を利用できる環境で、メモリリソースの柔軟な制御が可能になりました。
これまで、Kubernetesでのメモリリソースの制御はlimits.memoryの上限設定のみで、超えた際にOOMが発生するだけでした。これにはいくつかの問題がありました:
- コンテナのメモリリクエストは完全にreserveされているわけではないので、page cacheがリサイクルされる可能性がある
- メモリを使い果たしつつある時に頻繁にアロケーションレイテンシが発生する
- メモリのオーバーコミットはスロットルされない
- (Podではない)ノードリソースのメモリは完全には守られていない
これまでのメモリ上限(memory.max
)に加え、cgroup v2
で追加されたmemory.high
, memory.min
の2つのパラメータを設定することで、これらの課題を解決しようとしています。
-
memory.high
: メモリリソースのスロットル。この値よりメモリを使うと、プロセスはスロットルされ、メモリが回収されます(put under heavy reclaim pressure)- メモリを回収するとは、(dirtyなpage cacheを書き出して、)page cacheを開放したり、スワップアウトしたりすることを指している?
- この値は、デフォルトでは
limits.memory (node allocatable memory if no limit) * 0.8
になります。すなわち、limits.memoryの8割を超えるとスロットルがかかるようになります。この係数0.8はMemoryThrottlingFactorというkubeletの設定で変更可能です。
-
memory.min
: cgroupが常に維持すべきメモリ量を設定できます。例えば、システムがメモリが回収する必要があるときでも、memory.minで設定した分は維持されます。memory.minを適切に設定することで、ページキャッシュがリサイクルされないようにできます。- この値は、
requests.memory
の値が設定されます。すなわち、requests == limitsのようなGuaranteed Podの場合、ページキャッシュがリサイクルされることはなくなります。
- この値は、
この機能はアルファのため、利用するにはMemoryQoSフィチャーゲートを有効にする必要があります。
既知の問題点
複数のコンテナを持つGuaranteed PodでCPUとメモリマネージャーが正しく機能していません
複数のコンテナーを持つGuaranteedポッドが、CPU、メモリ、およびデバイスマネージャーの設定された割り当てで正しく機能しないというリグレッションバグが見つかりました。修正は今後のリリースで利用可能になります。
緊急アップグレードノート
アップグレード前に必ず読んでください
- デフォルトの
StreamingProxyRedirects
は無効になっています。マスターとノードの間に2以上のバージョンスキューがあり、古いノードが--redirect-container-streaming
を有効にしていた場合、これはそれらを壊します。この場合でも、StreamingProxyRedirects
を手動で有効にすることができます。 (#101647、@pacoxu)
種類別の変更
非推奨
-PodUnknown
フェーズは非推奨になりました。(#95286、@SergeyKanzhelev)
- Dynamic Kubelet Configurationは非推奨になり、フラグ
--dynamic-config-dir
が使用されるとkubeletは警告を表示します。フィーチャーゲートDynamicKubeletConfig
はデフォルトで無効になっているため、明示的に有効にする必要があります。(#102966、@SergeyKanzhelev)[SIG Cloud Provider, Instrumentation and Node]
APIの変更
- WindowsでHostProcessコンテナのアルファサポートを追加(#99576、@marosset)[SIG API Machinery, Apps, Node, Testing, Windows]
- 新しいkubeletのアルファ機能
SeccompDefault
を追加しました。この機能により、Pod/コンテナのSecurityContext
またはPodのアノテーションで他に何も指定されていない場合に、RuntimeDefault
(以前のruntime/default
)seccompプロファイルにフォールバックできます。この機能を使用するには、フィーチャーゲートを有効にし、kubeletオプションSeccompDefault
(--seccomp-default
)をtrue
に設定します。(#101943, @saschagrunert)[SIG Node] - スワップのサポート(アルファ)は、
NodeSwapEnabled
フィーチャーフラグを使用してKubernetesノードで有効にできるようになりました。詳細については、KEP-2400を参照してください。(#102823、@ehashman) - エフェメラルコンテナで、ポッドとは異なる
securityContext
を設定できるようになりました。クラスター管理者は、クラスターでこの機能を有効にする前に、セキュリティポリシーコントローラーがEphemeralContainers
をサポートしていることを確認する必要があります。(#99023、@verb) - cgroups v2(Alpha)によるメモリのQoSサポートの導入。
MemoryQoS
機能は現在アルファ版です。これにより、cgroups v2
で実行されているkubelet
は、コンテナ、Pod、およびQoSレベルでメモリQoSを設定して、より良いメモリ品質を保護および保証できます。この機能は、フィーチャーゲートMemory QoSを介して有効にできます。 (#102970、@borgerli) - NodeSwapEnabledフィーチャーフラグの名前がNodeSwapに変更されました
このフラグは1.22.0-beta.1リリースでのみ使用可能であり、今後は新しいフラグを使用する必要があります。(#103553、@ehashman)[SIG Node]
Feature
-
system-cluster-critical
Podは低いOOMスコアを取得するべきではありません。現在のところ、
system-node-critical
ポッドとsystem-cluster-critical
ポッドの両方のOOMスコアは-997であり、OOMKilledされる最後のプロセスの1つになっています。定義上、ノードがリソース不足であり、system-node-critical Podを再スケジュールできない場合でも、system-cluster-critical Podを他の場所でスケジュールできます。これが、system-node-critical
がsystem-cluster-critical
よりも高い優先度値を持つ理由です。この変更により、system-node-critical
優先度クラスのみが低いOOMScoreを持つことができます。必要なアクション
ユーザーがPodを最後にOOMKilledにする必要があり、Podがsystem-cluster-criticalプライオリティクラスの場合は、既存の動作を維持するためにsystem-node-criticalプライオリティクラスに変更する必要があります(#99729、@ravisantoshgudimetla)- 📝
system-cluster-critical
はクラスタ全体で動くPodにつかうプライオリティクラスなので、Preemptされても他のノードで動く余地があるのに対し、system-node-critical
はそのノードで動く必要があるため、system-node-critical
を優先するという変更です。
- 📝
-
cgroup v2
をサポートするために、CRIにunified mapを追加します。 https://github.com/opencontainers/runtime-spec/blob/master/config-linux.md#unified を参照してください。 (#102578、@payall4u) -
ユーザー名前空間でkubeletを実行するためのサポートを有効にするフィーチャーゲート
KubeletInUserNamespace
を追加します。kubeletを実行する前に、ユーザー名前空間を作成する必要があります。
CRIなどのすべてのノードコンポーネントは、同じユーザー名前空間で実行されている必要があります。フィーチャーゲートが有効になっている場合、kubeletは次のsysctl値の設定中に発生するエラーを無視します:
vm.overcommit_memory
、vm.panic_on_oom
、kernel.panic
、kernel.panic_on_oops
、kernel.keys.root_maxkeys
、kernel.keys.root_maxbytes
(これらのsysctl値は、コンテナーではなく、ホスト用です)kubeletは、
/dev/kmsg
を開く際のエラーも無視します。
このフィーチャーゲートにより、kube-proxyはRLIMIT_NOFILE
の設定中にエラーを無視することもできます。このフィーチャーゲートは、ルートレスDocker / Podman内で
kind
またはminikube
を使用してKubernetesを実行する場合に特に便利です。(#92863、@AkihiroSuda)[SIG Network, Node and Testing] -
net.ipv4.ip_unprivileged_port_start
を安全なsysctl
として扱います。(#103326、@pacoxu) -
メモリマネージャ機能はベータ版に移行し、デフォルトで有効になっています。(#101947、@cynepco3hahue)
-
メモリ上の
EmptyDir
ボリュームは、ホスト上のポッド割り当て可能メモリと、オプションの明示的なユーザー指定値の小さい方がサイズの上限として設定されます。 (#101048, @dims)
-HugePageStorageMediumSize
機能はGAに移行し、無条件に有効になります。コンテナレベルで複数のサイズのHuge Pageリソースを無条件に使用できるようにします。 (#99144, @bart0sh) -
SetHostnameAsFQDN
はGAに移行するため、無条件に無効になります。 (#101294, @javidiaz) -
PodリソースAPIは、メモリマネージャフィーチャーゲートが有効で、メモリマネージャーポリシーが静的である場合に、メモリマネージャメトリックを提供します。 (#101030, @cynepco3hahue)
Bug or Regression
- DBusの再起動後でも
GracefulNodeShutdown
が動くようにします( (#100369, @wzshiming) - execプローブが
timeoutSeconds
よりも長くかかる場合に、dockershimでもExecProbeTimeout=false
kubeletフィーチャーゲートが考慮されるようにします。 (#100200, @jackfrancis) - Podの起動時またはシャットダウン時のkubeletの競合状態を修正します。これにより、Podのシャットダウンに時間がかかる場合があります。 (#102344, @smarterclayton) [SIG Apps, Node, Storage and Testing]
- systemd cgroupドライバーを使用する場合のリソースの制御を修正しました (#102147, @kolyshkin)
-
PostStart
フックエラーのランタイムコンテナステータスを修正しました。 (#100608, @pacoxu) - タイムアウトしたポートフォワードストリームでkubeletがパニックする問題を修正しました。 (#102489, @saschagrunert)
- 長時間実行され、頻繁に使用される接続の「ポートフォワード」メモリリークが修正されました。 (#99839, @saschagrunert)
- コンテナの最初の再起動後に
startupProbe
が機能しなくなるバグを修正しました。 (#101093, @wzshiming) - 複数のPodを削除するときに、Graceful terminationが動作するようになりました。 (#100101, @deads2k)
- Kubelet:ノードリストと
kube-apiserver
の同期を待機するときのパフォーマンスを改善します。 (#99336, @neolit123) - Kubelet:PodIPの戻り値は、Downward APIと
pod.status.PodIPs
フィールドで同じになりました (#103307, @aojea) - cpusetのパースで、"1--3"や"10-6"などの無効な入力が正しく検出されるようになりました。 (#100565, @lack)
- 以前にRunningだったことがkubeletに認識されているポッドは、Pendingに戻らないようにする必要があります。kubeletは終了を推測します。 (#102821, @ehashman)
-
imagefs.minReclaim
が設定されているときにKubeletがDiskPressure
でスタックするのを防ぎます (#99095, @maxlaverse) - AppArmorホストバリデーションから
/sbin/apparmor_parser
のチェックを削除しました。
これにより、バイナリを別のパスに置くディストリビューションでAppArmorを使用できます。 (#97968, @saschagrunert) [SIG Node and Testing] - フェーズも変更されない限り、Podステータスのreasonフィールドとmessageフィールドはリセットされなくなりました。 (#103785, @smarterclayton) [SIG Node]
- Graceful Node Shutdown Podの終了理由とメッセージを更新しました。
Graceful Node Shutdown Podの拒否理由とメッセージを更新しました。 (#102840, @Kissy)
Other (Cleanup or Flake)
- 非推奨期間の後、Kubeletの
--chaos-chance
フラグが削除されました。 (#101057, @wangyysde) [SIG Node] - 非推奨の
runAsGroup
フィーチャーゲートは削除されました。これは、runAsGroup
機能が1.21でGAに移行したためです。 (#101581, @carlory)
Discussion