Linux cgroup version 2

Linux の cgroup version 2 を使って cpu リソースの制限をしてみる。

目次

  1. 検証環境
  2. cgroup v2 のマウント状況を確認
  3. cgroup v2 を利用できるようにする
  4. cgroup とプロセスの紐づけを確認
  5. 新しく作成されたプロセスの cgroup を確認
  6. cgroup 内のファイル
  7. cgroup の作成
  8. cpu の利用を制限
  9. cgroup の削除
  10. 参考

検証環境

AWS EC2 で立ち上げた Ubuntu 18.04 環境で試した。 カーネルバージョンは 5.3.0-1019-aws 。

1
2
$ uname -a
Linux ip-172-31-41-199 5.3.0-1019-aws #21~18.04.1-Ubuntu SMP Mon May 11 12:33:03 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

cgroup v2 のマウント状況を確認

Ubuntu 18.04 では cgroup v1 と v2 が共存している。 マウント状況は次のようになっている。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$ mount | grep cgroup
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
cgroup on /sys/fs/cgroup/unified type cgroup2 (rw,nosuid,nodev,noexec,relatime)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,name=systemd)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,rdma)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)

/sys/fs/cgroup/unified に cgroup v2 のファイルシステムがマウントされている。

cgroup v2 では、cgroup 内の cgroup.controllers に利用可能なコントローラが記載されている。 デフォルトでは /sys/fs/cgroup/unified/cgroup.controllers は空になっている。

これは、同じコントローラがバージョン1とバージョン2の両方にマウントすることができず、 デフォルトでは cgroup v1 にコントローラがマウントされているため。

man cgroups の Cgroups v2 unified hierarchy セクションによると、 cgroup v1 にマウントされていないコントローラが、 cgroup v2 で利用可能になる。

A cgroup v2 controller is available only if it is not currently in use via a mount against a cgroup v1 hierarchy.

cgroup v2 を利用できるようにする

先述のとおり、デフォルトでは cgroup v2 でコントローラが利用できないため、 起動時のオプションを指定して cgroup v1 を無効にし、cgroup v2 を利用できるようにする。 そのためには GRUB_CMDLINE_LINUX_DEFAULTsystemd.unified_cgroup_hierarchy=1 cgroup_no_v1=all を指定する。

検証環境では /etc/default/grub.d/50-cloudimg-settings.cfg で設定した。

1
GRUB_CMDLINE_LINUX_DEFAULT="console=tty1 console=ttyS0 nvme_core.io_timeout=4294967295 systemd.unified_cgroup_hierarchy=1 cgroup_no_v1=all"

変更したら、sudo update-grub で更新し、再起動する。 再起動すると、cgroup v2 だけが /sys/fs/cgroup にマウントされている。

1
2
$ mount | grep cgroup
cgroup on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime)

マウント位置も /sys/fs/cgroup/unified から /sys/fs/cgroup に変わっている。

cgroup.controllers を確認すると、コントローラも利用可能になっている。

1
2
$ cat /sys/fs/cgroup/cgroup.controllers
cpuset cpu io memory pids rdma

cgroup とプロセスの紐づけを確認

cgroup に属するプロセスは cgroup.procs ファイルで管理されている。 cgroup.procs にはその cgroup に属するプロセスの PID が一行ごとに記載されている。 ルート cgroup に属する PID は cat /sys/fs/cgroup/cgroup.procs で確認できる。 大量に表示されるので出力が割愛する。

PID の方から cgroup を確認するには /proc/${PID}/cgroup を見ればよい。

現在のプロセスの cgroup を確認してみる。

1
2
$ cat /proc/$$/cgroup
0::/system.slice/snap.amazon-ssm-agent.amazon-ssm-agent.service

cgroup v2 では常に 0::$PATH の形式になっている。 $PATH の部分がルート cgroup からのパスになっている。 /sys/fs/cgroup/system.slice/snap.amazon-ssm-agent.amazon-ssm-agent.service/cgroup.procs に 現在のプロセスの PID が記載されているのが確認できる。

1
2
$ grep $$ /sys/fs/cgroup/system.slice/snap.amazon-ssm-agent.amazon-ssm-agent.service/cgroup.procs
1244

新しく作成されたプロセスの cgroup を確認

検証用に、何もしない無限ループのプロセスを作成する。

1
2
$ while true; do : ; done &
[1] 1374

PID から cgroup を確認する。

1
2
$ cat /proc/1374/cgroup
0::/system.slice/snap.amazon-ssm-agent.amazon-ssm-agent.service

先ほど確認した、現在のプロセスと同じ cgroup に紐づいたのが確認できる。

cgroup 内のファイル

cgroup 内には次のようなファイルがある。

1
2
3
4
5
$ ls /sys/fs/cgroup/system.slice/snap.amazon-ssm-agent.amazon-ssm-agent.service
cgroup.controllers  cgroup.max.descendants  cgroup.threads  cpu.stat         io.pressure     memory.events.local  memory.min        pids.current
cgroup.events       cgroup.procs            cgroup.type     cpu.weight       io.stat         memory.high          memory.oom.group  pids.events
cgroup.freeze       cgroup.stat             cpu.max         cpu.weight.nice  memory.current  memory.low           memory.pressure   pids.max
cgroup.max.depth    cgroup.subtree_control  cpu.pressure    io.max           memory.events   memory.max           memory.stat

利用可能なコントローラ cpu, io, memory, pids 毎にいくつかのファイルがあるのがわかる。 これらのファイルを介して、この cgroup に属するプロセスへのリソース配分を制御する。

cpu.max では cpu の利用率を制限できる。 このファイルは $MAX $PERIOD の形式で、$PERIOD マイクロ秒あたり $MAX マイクロ秒まで cpu を利用できる、と制限する。 デフォルトでは次のようになっている。

1
2
$ cat /sys/fs/cgroup/system.slice/snap.amazon-ssm-agent.amazon-ssm-agent.service/cpu.max
max 100000

max は、最大値まで利用可能であることを表す。 この設定では 100% まで利用可能。

先ほど検証用に作成したプロセスはこの cgroup に属しているので、100% cpu を利用可能になる。 確認してみると、ほぼ 100% 利用しているのがわかる。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ top -b -p 1374
top - 07:48:06 up 40 min,  1 user,  load average: 1.00, 0.95, 0.60
Tasks:   1 total,   1 running,   0 sleeping,   0 stopped,   0 zombie
%Cpu(s): 16.6 us,  0.2 sy,  0.0 ni, 83.1 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  2003028 total,  1591292 free,   123708 used,   288028 buff/cache
KiB Swap:        0 total,        0 free,        0 used.  1733084 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 1374 ubuntu    20   0   23264   1748      0 R  93.8  0.1  13:20.86 bash

top - 07:48:09 up 40 min,  1 user,  load average: 1.00, 0.95, 0.61
Tasks:   1 total,   1 running,   0 sleeping,   0 stopped,   0 zombie
%Cpu(s): 50.2 us,  0.0 sy,  0.0 ni, 49.8 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  2003028 total,  1591292 free,   123640 used,   288096 buff/cache
KiB Swap:        0 total,        0 free,        0 used.  1733108 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 1374 ubuntu    20   0   23264   1748      0 R 100.0  0.1  13:23.87 bash

top - 07:48:12 up 40 min,  1 user,  load average: 1.00, 0.95, 0.61
Tasks:   1 total,   1 running,   0 sleeping,   0 stopped,   0 zombie
%Cpu(s): 50.1 us,  0.0 sy,  0.0 ni, 49.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  2003028 total,  1591292 free,   123640 used,   288096 buff/cache
KiB Swap:        0 total,        0 free,        0 used.  1733108 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 1374 ubuntu    20   0   23264   1748      0 R  99.7  0.1  13:26.87 bash

cgroup の作成

新しい cgroup は、cgroup 階層に新しいディレクトリを作成することで作成できる。 検証用に test という cgroup を作ってみる。

1
$ sudo mkdir /sys/fs/cgroup/test

ディレクトリ(cgroup)を作成すると、自動的にファイルが作成されている。

1
2
3
4
5
$ ls /sys/fs/cgroup/test/
cgroup.controllers  cgroup.max.descendants  cgroup.threads  cpu.stat         io.pressure     memory.events.local  memory.min        pids.current
cgroup.events       cgroup.procs            cgroup.type     cpu.weight       io.stat         memory.high          memory.oom.group  pids.events
cgroup.freeze       cgroup.stat             cpu.max         cpu.weight.nice  memory.current  memory.low           memory.pressure   pids.max
cgroup.max.depth    cgroup.subtree_control  cpu.pressure    io.max           memory.events   memory.max           memory.stat

利用可能なコントローラは次のようになっている。

1
2
$ cat /sys/fs/cgroup/test/cgroup.controllers
cpu io memory pids

作っただけでは何のプロセスも属しておらず、cgroup.procs は空になっている。

1
$ cat /sys/fs/cgroup/test/cgroup.procs

cpu も 100% 利用可能になっている。

1
2
$ cat /sys/fs/cgroup/test/cpu.max
max 100000

cpu の利用を制限

cpu.max を変更して test cgroup の cpu の利用を 50% に制限してみる。

1
$ sudo sh -c 'echo "50000 100000" >/sys/fs/cgroup/test/cpu.max'

先述した通り cgroup に属するプロセスは cgroup.procs で管理されている。 プロセスを別の cgroup に移動するにはその PID を移動先 cgroup の cgroup.procs に追記すればよい。

先ほど作成した検証用プロセスをこの test cgroup に移動する。

1
$ sudo sh -c 'echo 1374 >>/sys/fs/cgroup/test/cgroup.procs'

移動したプロセスの cpu 利用率をを確認してみる。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ top -b -p 1374
top - 08:02:31 up 55 min,  1 user,  load average: 0.78, 0.95, 0.85
Tasks:   1 total,   1 running,   0 sleeping,   0 stopped,   0 zombie
%Cpu(s): 25.2 us,  0.2 sy,  0.0 ni, 74.5 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  2003028 total,  1589220 free,   125220 used,   288588 buff/cache
KiB Swap:        0 total,        0 free,        0 used.  1731500 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 1374 ubuntu    20   0   23264   1748      0 R  60.0  0.1  27:38.44 bash

top - 08:02:34 up 55 min,  1 user,  load average: 0.72, 0.93, 0.85
Tasks:   1 total,   1 running,   0 sleeping,   0 stopped,   0 zombie
%Cpu(s): 26.0 us,  0.0 sy,  0.0 ni, 74.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  2003028 total,  1589212 free,   125228 used,   288588 buff/cache
KiB Swap:        0 total,        0 free,        0 used.  1731492 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 1374 ubuntu    20   0   23264   1748      0 R  50.2  0.1  27:39.95 bash

top - 08:02:37 up 55 min,  1 user,  load average: 0.72, 0.93, 0.85
Tasks:   1 total,   1 running,   0 sleeping,   0 stopped,   0 zombie
%Cpu(s): 26.0 us,  0.0 sy,  0.0 ni, 74.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  2003028 total,  1589212 free,   125228 used,   288588 buff/cache
KiB Swap:        0 total,        0 free,        0 used.  1731492 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 1374 ubuntu    20   0   23264   1748      0 R  50.0  0.1  27:41.45 bash

移動前は 100% だったが、50% 程度に制限されているのがわかる。

PID から cgroup も調べてみる。

1
2
$ cat /proc/1374/cgroup
0::/test

cgroup の削除

cgroup を削除するには、事前に所属するプロセスがない状態にする必要がある。 test cgroup に属している検証用のプロセスを kill する。

1
$ kill 1374

test cgroup に属しているプロセスがないことを確認。

1
$ cat /sys/fs/cgroup/test/cgroup.procs

test cgroup のディレクトリを削除する。

1
$ sudo rmdir /sys/fs/cgroup/test

cgroup を作成したときと同様にディレクトリを削除するだけでよく、ファイルは自動で処理される。

参考