inductor's blog

nothing but self note :)

新しいLinux namespaceである「CPU Namespace」について

はじめに

この記事は、以下のlwn.netの記事を抄訳したものです。

lwn.net

CPU Namespaceのご紹介

これはCPU namespaceのインターフェスとそのメカニズムを証明するための初期プロトタイプです。

現状におけるCPUリソースの制限方法

Linuxカーネルでは、タスクのCPUリソースを制御するために2つの方法を提供します。

  1. cgroup cpuset: 該当のグループにアタッチされた単一または複数のタスクの集合に対し、CPUリソースを制限するためのメカニズムです。
  2. syscall sched_setaffinity: CPUの集合に対して特定のタスクをピニングするためのシステムコールです(訳注: NUMA利用時の条件下などにおいてよく利用される手法)。

また、カーネルはシステムにおいて利用可能なCPUリソースを閲覧可能にするために3つの方法を提供します。

  1. sys/procfs: CPUのシステム情報はsys及びprocファイルシステムを通じて公開され、CPUの負荷特性に加えてオンライン、オフラインなどの状態や、存在に関しても公開します。
  2. syscall sched_getaffinity: タスクのcpuset affinityを取得するためのシステムコールインターフェースです。
  3. cgroup cpuset: cgroupは閲覧用というよりは制御用のメカニズムではありますが、タスクのグループに適用されたCPU制限の情報を取得するためにも使われます。

情報の一貫性

制御用、閲覧用のインターフェースは互いに大きく離れています。リソース制限はcgroupsのような制御インターフェースを通じて設定できますが、多くのアプリケーションはレガシーで制御機構を持たなかったり、あるいはsysfs/procfsを通じてシステム情報を取得し、その情報に基づいたCPUやメモリリソースの割当を行います。

こうした制御は予期しない動作を招くだけでなく、パフォーマンスへの影響も懸念されます。

この問題に対する既存の解決策には、cpusetのcgroupを通じて設定されたリソース制限と一致するようなsysfsオンラインファイルをマウントすることによって実際のsysfs情報を偽造できるLXCFSなどのユーザー空間ツールが含まれます。

ただし、LXCFSは外部の解決策であり、アプリケーション側でこれが必要であると明示的に設定してあげる必要があります。もう1つの懸念としては、LXCFSのようなツールが、procfsの負荷統計情報のような他の表示メカニズムについては取り扱わないことが挙げられます。

そうした背景から、明確なインターフェースの必要性が提唱される可能性が生じます。

セキュリティと公正利用への影響

長いので省略... 主にマルチテナントの環境において複数のコンテナが存在する場合にシステム全体に関する情報がセキュリティやマシンリソースの公正利用に影響を及ぼす可能性を示唆していました。

その上で、新しく作られるCPU namespaceではCPU情報を仮想的に隔離し、IDごと分けてしまうことでプロセス側でこうしたハンドリングをしなくてもよいよ、みたいな機構を提供するためのプロトタイプ実装を作りましたみたいな話が書かれている。

実験

Nginxのworker_process: autoを設定した時に既存の方法とCPU namespace用いた場合でパフォーマンス計測を行っている。

Case1: vanilla kernel - cpuset 4 cpus, no optimization
Case2: CPU namespace kernel - cpuset 4 cpus
メトリック Case1 Case2 Case1とCase2の比較(Case2基準)
PIDの数 177 5 172少ない
初期メモリ使用量(MB) 272.8 11.12 95.92%少ない
ピーク時のメモリ使用量(MB) 281.3 20.62 92.66%少ない
平均レイテンシ(ms) 70.91 25.36 64.23%速い
リクエスト数/秒 47011.05 47080.98
転送量(MB)/秒 38.11 38.16

CPU namespaceを使った場合ではcpusetの制限で設定したのと同じだけのPID数が生成されており、メモリ使用量が大幅に削減された。レイテンシが大幅に削減されつつもリクエスト数、転送量には影響がほぼなかった。

注意: この新しいnamespaceをDockerなどのコンテナランタイムで活用するために、クローンしたCPU namespaceのフラグがPID namespaceと一致するように変更しています(コンテナの構成要素であり、これらが常に利用されるため)。

本プロトタイプが現在抱える欠点

  1. コンテナではCPUランタイムを制限するためにCFS periodとCFS quotaの値を頻繁に利用しますが、このRFCインターフェースではこうした事情は考慮外になっています。
  2. /proc/statは名前空間を認識しており、topのようなユーザー空間のプログラムでは名前空間に基づいた仮想的なCPUの使用率が表示されますが、システム側のプロセスや、namespace外にある他のアプリケーションがCPU利用率を挙げた場合においてもsys/user timeが上昇して表示されます。これは理想的には(他プロセスによって)奪われた時間として表示されるべきです。

(まだ他にもあるけど翻訳疲れたのでこのへんで終わっておく)などといった問題もまだまだ色々ありそう。

参考情報: https://pratiksampat.github.io/cpu_namespace.html

おわりに

CPUリソースをコンテナ内でより正しく扱うために新しく提唱されているCPU namespaceというのがあるんだよ、というご紹介でした。

cgroup側であれこれこねくり回して頑張ってたCPUリソースの制限をもっとシンプルな形でフェアに使えるようにしようね、という話だとは思うんですが、ここまでくるとVMでもいいなという邪な気持ちが生まれる気持ちも少しあります。これが実装されたらコンテナ側でもリソース制限の実装はかなり大きく変わっていくと思うので、今後の動向に注目しておきたいと思います。

それでは、今日はこのへんで。