LXCで学ぶコンテナ入門 -軽量仮想化環境を実現する技術

第41回 Linuxカーネルのコンテナ機能 ― cgroupの改良版cgroup v2[5]

この記事を読むのに必要な時間:およそ 6.5 分

cgroup v2コアで使用する4.14カーネルで追加されたファイル

第38回でcgroup v2コアで使用するファイルについて紹介しました。いずれもcgroup.で始まるファイルでした。

その後,cgroup v2の開発が進むとともに,第38回で紹介したファイル以外に追加されたファイルがありますので,それらを今回紹介しましょう。

いずれも4.14カーネルで追加されました。

表1 cgroup v2コアで使用するファイル(追加分)

ファイル名 説明 可能な操作 デフォルト値
cgroup.type そのcgroupの現在のタイプ。root以外に存在 読み書き -
cgroup.threads そのcgroupに属するスレッドの登録,確認 読み書き -
cgroup.max.depth そのcgroupが持てる子孫の深さ 読み書き max
cgroup.max.descendants そのcgroupが持てる子孫の最大数 読み書き max
cgroup.stat cgroupのステータス 読み込み -

表1が4.14カーネルで追加されたファイルです。実際にファイルが出現していることを確認しましょう。4.14.44カーネルで試しています。 

$ uname -r
4.14.44-plamo64
$ sudo mount -t cgroup2 cgroup2 /sys/fs/cgroup/
$ ls /sys/fs/cgroup/ (cgroup rootにあるファイルを確認)
cgroup.controllers      cgroup.procs            cgroup.threads
cgroup.max.depth        cgroup.stat
cgroup.max.descendants  cgroup.subtree_control
(cgroup.threads, cgroup.max.depth, cgroup.max.descendants, cgroup.statが存在)
$ sudo mkdir /sys/fs/cgroup/test01
$ ls /sys/fs/cgroup/test01
cgroup.controllers  cgroup.max.descendants  cgroup.subtree_control  io.max
cgroup.events       cgroup.procs            cgroup.threads          io.stat
cgroup.max.depth    cgroup.stat             cgroup.type
(cgroup rootでなければcgroup.typeファイルが存在)

それでは,これらの追加されたファイルそれぞれについて説明していきましょう。

スレッドモード

4.14カーネルでは,cgroup v2に大きな変更が加えられました。これは,スレッド単位でcgroupを制御する,スレッドモードというモードです。

表1で紹介した,4.14で追加されたファイルのうち,次の2つのファイルがこのスレッドモードに関係します。

  • cgroup.type
  • cgroup.threads

cgroup.typeファイルは,cgroupがプロセスを扱うのか,スレッドを扱うのかなど,そのcgroupが持つ機能を表す文字列が書かれます。

cgroup.threadsファイルは,cgroup.procsファイルのスレッド版で,スレッドをcgroupに追加・削除する際,cgroupに属するスレッドを確認する際に使うファイルです。cgroup v1に存在したtasksファイルと同様のファイルです。

スレッドモードを説明すると長くなりますので,スレッドモードの説明とこれらのファイルの使い方については,この連載の後の回で詳しく紹介したいと思います。

cgroupの子孫の制御

4.14カーネルでは,スレッドモードの他に,cgroupの子孫を制御する機能が追加されました。

これは,cgroupの階層が深くなったり子孫数が多くなると,パフォーマンスに影響を与える可能性があるためです。特に権限委譲を行うと,ホストの管理者が知らないところでシステム上に存在するcgroupの数が増えてしまう可能性がありますので,そのような場合に有効な機能でしょう。

cgroup.max.depth

cgroup.max.depthファイルは,cgroupの子孫の深さを制限します。デフォルト値はmaxであり,制限がないことを表します。実際に試しながら確認しましょう。

"test1" cgroupを作成し,cgroup.max.depthファイルに2を書き込み,深さを2に制限します。つまり"test1"から見ると孫cgroupまでは許されます。しかし,ひ孫を作る所でエラーになるはずです。

$ sudo mkdir /sys/fs/cgroup/test1 (cgroupの作成)
$ echo 2 | sudo tee /sys/fs/cgroup/test1/cgroup.max.depth 
(子孫の深さを2に制限)
2
$ cat /sys/fs/cgroup/test1/cgroup.max.depth (設定を確認)
2

制限を2に設定しました。設定が確認できましたので,子孫のcgroupを作成して,設定したとおりに制限されているかを確認しましょう。

$ sudo mkdir /sys/fs/cgroup/test1/test2
(子cgroupを作成)
$ sudo mkdir /sys/fs/cgroup/test1/test2/test3
(孫cgroupを作成)
$ sudo mkdir /sys/fs/cgroup/test1/test2/test3/test4
mkdir: cannot create directory ‘/sys/fs/cgroup/test1/test2/test3/test4’: Resource temporarily unavailable
(ひ孫cgroupを作成しようとするとエラーになる)

"test1" cgroupの子として"test2",孫として"test3"までは作成できました。しかし,さらにひ孫として"test4"を作成しようとしたところでエラーになりました。

cgroup.max.depthの制限にひっかかった場合は,エラーとしてEAGAINが返ります。

ここで"test2","test3" cgroup内のcgroup.max.depthファイルはどうなっているのか確認してみましょう。

$ cat /sys/fs/cgroup/test1/test2/cgroup.max.depth 
max
$ cat /sys/fs/cgroup/test1/test2/test3/cgroup.max.depth 
max
(制限値を書き込んでいないcgroupではmaxのまま)

このように特に設定していないcgroupの制限は"max"となっています。この場合でも上位の"test1"で設定した制限が効いていますので,上位で設定した制限にひとつでもひっかかるとエラーになることがわかります。

図3 cgroup.max.depth

図3 cgroup.max.depth

cgroup.max.descendants

cgroup.max.descendantsファイルは,cgroupが持てる子孫の数を制限します。デフォルト値はcgroup.max.depthと同じく"max"であり,制限がないことを表します。試してみましょう。

"test1"のcgroup.max.descendantsファイルに2を書き込み,子孫数を2に制限します。

$ sudo mkdir /sys/fs/cgroup/test1 (cgroupの作成)
$ echo 2 | sudo tee /sys/fs/cgroup/test1/cgroup.max.descendants 
(子孫の数を2に制限)
2
$ cat /sys/fs/cgroup/test1/cgroup.max.descendants (設定を確認)
2

制限を2に設定しました。設定が確認できましたので,子cgroupを作成して,設定したとおりに制限されているか確認しましょう。

$ sudo mkdir /sys/fs/cgroup/test1/test2
(ひとつめの子cgroupを作成)
$ sudo mkdir /sys/fs/cgroup/test1/test3
(ふたつめの子cgroupを作成)
$ sudo mkdir /sys/fs/cgroup/test1/test4
mkdir: cannot create directory '/sys/fs/cgroup/test1/test4': Resource temporarily unavailable
(3つめの子cgroupを作成しようとするとエラーになる)

3つめのcgroupを作るところでエラーになりました。cgroup.max.depthと同様にEAGAINが返ります。

図4 cgroup.max.descendants

図4 cgroup.max.descendants

cgroup.stat

cgroupの統計情報が含まれているファイルで,読み取り専用です。現時点ではcgroupの子孫情報のみ含まれています。

nr_descendants
利用できる子孫cgroupの数
nr_dying_descendants
消滅途中の子孫cgroupの数

「消滅途中」とは,ユーザがcgroupを削除しても,システム負荷に応じてcgroupが消滅するまでに時間がかかるので,子孫のうち,その削除途中の状態にあるcgroup数がカウントされます。

先のcgroup.max.descendantsの例で,2つ子cgroupを作成したあとのcgroup.statファイルを確認してみましょう。

$ cat /sys/fs/cgroup/test1/cgroup.stat 
nr_descendants 2
nr_dying_descendants 0

子cgroupをふたつ作成したので,nr_descendantsが2となっています。

まとめ

今回はcgroup v2に追加された新機能を紹介しました。

nsdelegateマウントオプションは,cgroup名前空間と連携して,自動的に権限委譲の境界を定義する機能です。この機能により,名前空間をまたいでプロセスは移動できません。そして,名前空間のrootではコントローラのリソース制限値を変更できません。

そして,これまでは無限に子孫を増やせたcgroupに,子孫の数を制限する機能が追加されました。システム上のcgroupの数や階層が増えてパフォーマンスに影響を与えるのを防げます。

次回からは,前回書いたとおりにudzuraさんにCRIUについて書いていただく予定です。先日開催されたJapanContainerDays v18.12で,udzuraさんのCRIUに関するセッションを聞きました。非常に面白い内容でしたので,今後の記事が楽しみです。

著者プロフィール

加藤泰文(かとうやすふみ)

2009年頃にLinuxカーネルのcgroup機能に興味を持って以来,Linuxのコンテナ関連の最新情報を追っかけたり,コンテナの勉強会を開いたりして勉強しています。英語力のない自分用にLXCのmanページを日本語訳していたところ,あっさり本家にマージされてしまい,それ以来日本語訳のパッチを送り続けています。

Plamo Linuxメンテナ。ファーストサーバ株式会社所属。

Twitter:@ten_forward
技術系のブログ:http://tenforward.hatenablog.com/

コメント

コメントの記入