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

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

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

前回の記事は,私が所属する会社のAdvent Calendarの5日目の記事でした。これまでは,この連載記事でAdvent Calendarに参加するのは1回だけでした。

今年はcgroup v2の話題を書こうと決めたときに,内容から考えて1回では済まない量になるだろうと思いました。そこで,続けて2回でcgroup v2の紹介をして,2つのAdvent Calendarに参加しようと決めました。1回目はちょうど社内で募集が始まっていた会社のAdvent Calendar,2回目は例年どおりLinux Advent Calendarに参加することにしました。

そういうわけで,今回の記事は昨年まで何度か参加していたLinux Advent Calendar 2017の19日目の記事です。


今回は,実際にcgroup v2を操作しながら,前回紹介したcgroup v2の特徴をおさらいしましょう。

今回の実行例は,cgroup v1,v2のマウントを自由に行うために,systemdが動いていない環境であるPlamo Linux 6.2の4.11.12カーネル上で実行しています。

前回書いたとおり,執筆時点で最新の4.14カーネルでは新しい機能が追加されています。新しい機能については後の回で紹介しますので,今回は少し前のバージョンである4.11カーネルを使用しています。4.13以降の新しいカーネルでは,今回の実行例とは実行結果が異なることがありますのでご注意ください。

cgroup v2のマウント

cgroup v2は,ファイルシステムのタイプとしてcgroup2を指定してマウントします。今回試している4.11カーネルの時点では,マウントオプションはありません。

# mount -t cgroup2 cgroup2 /sys/fs/cgroup/
# grep cgroup2 /proc/self/mountinfo (マウントされているのを確認)
25 19 0:22 / /sys/fs/cgroup rw,relatime - cgroup2 cgroup2 rw

cgroup v1では,サブシステム(コントローラ)名やその他いくつかオプションが存在しましたが,cgroup v2では上の実行例のように指定するオプションもなく,シンプルにファイルシステムをマウントするだけです。

上の実行例のようにマウントした際にcgroup rootとなる,/sys/fs/cgroupを確認してみましょう。

# ls /sys/fs/cgroup/
cgroup.controllers  cgroup.procs  cgroup.subtree_control

cgroup v2でコントロールを行うためのファイルが3つ現れており,cgroup v2がマウントされていることがわかります。

なお,4.13カーネルでcgroup namespace関連のマウントオプションがひとつだけ追加されました。この機能については後の回で紹介する予定です。

cgroup v2コアで使用するファイル

cgroup v2の各cgroup内に現れるファイルのうち,サブシステムと関係なく出現するファイルを紹介しておきましょう。それぞれのファイルの詳細については後で説明します。

表1 cgroup v2コアで使用するファイル

ファイル名 説明
cgroup.controllers そのcgroupで使えるサブシステム
cgroup.procs そのcgroupに属するプロセスの登録,確認
cgroup.subtree_control 子cgroupで有効にするサブシステム
cgroup.events そのcgroupと子孫のcgroupにプロセスが所属しているかを確認する。また,所属状況が変化した場合に通知を受け取れる。root以外に出現

cgroupの作成

cgroupを作成する方法は,前回説明した通りcgroup v1と同じです。

"test01"というcgroupを作ってみましょう。cgroup v1と同様にmkdirコマンドを使います。

# mkdir /sys/fs/cgroup/test01
# ls /sys/fs/cgroup/test01
cgroup.controllers  cgroup.events  cgroup.procs  cgroup.subtree_control

作成したcgroupの中のファイルを一覧してみると,rootよりはファイルがひとつ増えていますね。cgroup.eventsというファイルです。これは前回紹介したcgroup v2の特徴のうち,⁠cgroup状態通知」に関係するファイルです。このファイルについては次回説明します。

cgroupの削除

cgroupを作成する方法だけでなく,削除方法もcgroup v1と同様にrmdirコマンドで行います。上で作成した"test01"を削除してみましょう。

# rmdir /sys/fs/cgroup/test01/
# ls /sys/fs/cgroup/
cgroup.controllers  cgroup.procs  cgroup.subtree_control

cgroupにプロセスが所属しておらず,子cgroupを持っていないcgroupのみ削除できるのも,cgroup v1と同じです。

cgroupへのプロセスの追加,削除,確認

使用するファイル

cgroup v1でタスクをcgroupに所属させる場合は,スレッドIDやプロセスIDをファイルに書き込みました。また,cgroupに所属しているタスクは,ファイルの中身を見ることで確認できました。このとき使うファイルは2種類ありました。

表2 cgroupに所属するタスクに関連するファイル

ファイル名 表示されるID cgroupのバージョン
tasks スレッドID v1のみ
cgroup.procs (※) プロセスID v1, v2
※)
第3回での解説では紹介していませんでした。

プロセスの追加

cgroup v2ではプロセス単位で追加を行いますので,tasksファイルはありません。cgroup.procsファイルを使って登録や確認を行います。

プロセスを登録する操作はcgroup v1と同じです。プロセスをcgroupに登録してみましょう。さきほどの例で作成した"test01"グループに登録します。

# echo $$
3028
# echo $$ > /sys/fs/cgroup/test01/cgroup.procs 
# cat /sys/fs/cgroup/test01/cgroup.procs
3028
3035(これはcatコマンドのPID)

cgroup.procsにカレントシェルのPIDを書き込み,ファイルの中身を表示させると,登録したPIDが表示されました。

プロセスの削除

プロセスの削除は,PIDを別のcgroupに登録することで行います。これもcgroup v1と同じですね。

# grep 3028 /sys/fs/cgroup/test01/cgroup.procs (test01に3028が所属している)
3028
# echo $$ > /sys/fs/cgroup/cgroup.procs        (3028をrootに登録)
# grep 3028 /sys/fs/cgroup/cgroup.procs        (rootに登録されたことを確認)
3028
# grep 3028 /sys/fs/cgroup/test01/cgroup.procs (test01からは削除された)
# 

上の例のように,PIDが3028のプロセスをroot(または他のcgroup)に登録すると,"test01"からは削除されます。

プロセスが所属するcgroupの確認

プロセスが所属しているcgroupの情報は,/proc/[PID]/cgroupにあります("[PID]"にはプロセスのPIDが入ります)⁠

cgroup v1では,このファイルの中身は次のようになっています。

# cat /proc/12314/cgroup 
15:debug:/
14:rdma:/
13:pids:/
12:hugetlb:/
11:net_prio:/
10:perf_event:/
9:net_cls:/
8:freezer:/
7:devices:/
6:memory:/
5:blkio:/
4:cpuacct:/
3:cpu:/test01
2:cpuset:/
1:name=systemd:/

階層ごとに1行エントリが作成されます。各行はコロン区切りで(階層を作成した順):(サブシステム名):(所属するcgroupパス)となります。ひとつの階層に複数のサブシステムが属している場合は,サブシステム名)⁠の部分はカンマ区切りでサブシステムが並びます。

上の例だと,PID:12314のプロセスは,cpuサブシステム用のツリーのみ/test01に属しており,その他のツリーではrootに属していることがわかります。

cgroup v2では,次のようになります。

# cat /proc/self/cgroup 
0::/test01

階層はひとつしかありませんので1行で,v1でサブシステム名が入っていた部分は何も入っていません。v2では番号は常に"0"で,サブシステム名の部分には何も入らず0::(所属するcgroupパス)となります。

ちなみにv1とv2を共存させた場合,cgroupファイルの中身は次のようになります。

# cat /proc/self/cgroup 
2:blkio,memory:/test01
1:cpu:/test01
0::/test01

cgroup v2は必ず"0"でエントリが始まり,サブシステム名が空ですので,v1のエントリと区別がつきます。v1のエントリは"1"から始まりますのでバッティングすることもありません。

著者プロフィール

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

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

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

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

コメント

コメントの記入