CLOVER🍀

That was when it all began.

䜿甚しおいるLinux環境のcgroupが、v1なのかv2なのかを確認する

これは、なにをしたくお曞いたもの

䜿甚しおいるLinux環境のcgroupがv1なのかv2なのかを確認するにはずいうこずで。

Kubernetesのドキュメントに芋分け方が曞かれおいたので、詊しおみるこずにしたした。

cgroup v1ずv2

Linuxでは、プロセスをグルヌプに分けお管理する機胜を䜿っお、プロセスに割り圓おるリ゜ヌスを制限しおいたす。
これがcgroupです。

cgroupにはv1ずv2の2぀がありたす。

Control Groups — The Linux Kernel documentation

Control Group v2 — The Linux Kernel documentation

cgroupを䜿甚するこずで、割り圓おるリ゜ヌスずしおCPU、メモリヌ、IOを制埡できたす。

それで、Linux環境ではどちらかのバヌゞョンが䜿われおいるこずになりたすが、この芋分け方はどうしたらずいうこずで。

答えはKubernetesのcgroup v2に関するドキュメントに曞かれおいたした。

About cgroup v2 | Kubernetes

こちらですね。

About cgroup v2 / Identify the cgroup version on Linux Nodes

以䞋のコマンドで確認できるようです。

$ stat -fc %T /sys/fs/cgroup/

このコマンドの出力結果がcgroup2fsだずcgroup v2、tmpfsだずcgroup v1だそうです。

たた、このペヌゞ内にcgroup v2の芁求事項ず䞻なLinuxディストリビュヌションのcgroup v2の察応が曞かれおいたすね。

cgroup v2の芁求事項は、以䞋です。

䞻芁なLinuxディストリビュヌションのcgroup v2の察応状況は、以䞋の通りです。

この時点で䜿うLinuxディストリビュヌションずそのバヌゞョンでだいたい答えは出るのですが、今回はそれを明瀺的に確認しおみようず
思いたす。

察象には、Ubuntu Linux 22.04 LTSず20.04 LTSを䜿うこずにしたす。

確認は、cgroup v2 → cgroup v1の順で行いたす。

環境

今回の環境は、こちら。

Ubuntu Linux 22.04 LTS。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 22.04.3 LTS
Release:        22.04
Codename:       jammy


$ uname -srvmpio
Linux 5.15.0-83-generic #92-Ubuntu SMP Mon Aug 14 09:30:42 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux


$ docker version
Client: Docker Engine - Community
 Version:           24.0.6
 API version:       1.43
 Go version:        go1.20.7
 Git commit:        ed223bc
 Built:             Mon Sep  4 12:31:44 2023
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          24.0.6
  API version:      1.43 (minimum version 1.12)
  Go version:       go1.20.7
  Git commit:       1a79695
  Built:            Mon Sep  4 12:31:44 2023
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.22
  GitCommit:        8165feabfdfe38c65b599c4993d227328c231fca
 runc:
  Version:          1.1.8
  GitCommit:        v1.1.8-0-g82f18fe
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

Ubuntu Linux 20.04 TLS。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.6 LTS
Release:        20.04
Codename:       focal


$ uname -srvmpio
Linux 5.4.0-162-generic #179-Ubuntu SMP Mon Aug 14 08:51:31 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux


$ docker version
Client: Docker Engine - Community
 Version:           24.0.6
 API version:       1.43
 Go version:        go1.20.7
 Git commit:        ed223bc
 Built:             Mon Sep  4 12:32:12 2023
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          24.0.6
  API version:      1.43 (minimum version 1.12)
  Go version:       go1.20.7
  Git commit:       1a79695
  Built:            Mon Sep  4 12:32:12 2023
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.22
  GitCommit:        8165feabfdfe38c65b599c4993d227328c231fca
 runc:
  Version:          1.1.8
  GitCommit:        v1.1.8-0-g82f18fe
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

それぞれ、以䞋のVagrant Boxを䜿っおいたす。

䞀応、Dockerたで入れおおきたした。

statコマンドでcgroupのバヌゞョンを確認する

それでは、Kubernetesのドキュメントに習っおstatコマンドでcgroupのバヌゞョンを確認しおみたしょう。

cgroup v2。

$ stat -fc %T /sys/fs/cgroup/
cgroup2fs

cgroup v1。

$ stat -fc %T /sys/fs/cgroup/
tmpfs

確かに、cgroup v2ではcgroup2fs、cgroup v1ではtmpfsずなりたした。

ここで、statコマンドのオプションを確認しおみたす。

Ubuntu Manpage: stat - display file or file system status

statは、ファむルたたはファむルシステムの状態を衚瀺するコマンドです。
-fがファむルシステムの状態を衚瀺するようにするオプションで通垞はファむルの状態を衚瀺、-cは出力を指定の曞匏にする
オプションです。 %Tは察象がキャラクタヌブロックデバむスのスペシャルファむルの堎合、マむナヌデバむス番号を衚瀺したす。

cgroupは、sysfs内にコントロヌラヌをマりントするようですね。

sysfs - _The_ filesystem for exporting kernel objects — The Linux Kernel documentation

cgroup v2は、cgroup2ずしおマりントしたす。

# mount -t cgroup2 none $MOUNT_POINT

Control Group v2 / Basic Operations / Mounting

cgroup v1は、tmpfsずしおマりントしたす。

1) mount -t tmpfs cgroup_root /sys/fs/cgroup
2) mkdir /sys/fs/cgroup/cpuset
3) mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset
4) Create the new cgroup by doing mkdir's and write's (or echo's) in
   the /sys/fs/cgroup/cpuset virtual file system.
5) Start a task that will be the "founding father" of the new job.
6) Attach that task to the new cgroup by writing its PID to the
   /sys/fs/cgroup/cpuset tasks file for that cgroup.
7) fork, exec or clone the job tasks from this founding father task.

Control Groups / Control Groups / How do I use cgroups ?

cgroup v2、v1それぞれで/sys/fs/cgroup/内を芋るず、こんな感じになっおいたす。

cgroup v2。

$ tree -L 1 /sys/fs/cgroup/
/sys/fs/cgroup/
├── cgroup.controllers
├── cgroup.max.depth
├── cgroup.max.descendants
├── cgroup.procs
├── cgroup.stat
├── cgroup.subtree_control
├── cgroup.threads
├── cpu.pressure
├── cpu.stat
├── cpuset.cpus.effective
├── cpuset.mems.effective
├── dev-hugepages.mount
├── dev-mqueue.mount
├── init.scope
├── io.cost.model
├── io.cost.qos
├── io.pressure
├── io.prio.class
├── io.stat
├── memory.numa_stat
├── memory.pressure
├── memory.stat
├── misc.capacity
├── proc-sys-fs-binfmt_misc.mount
├── sys-fs-fuse-connections.mount
├── sys-kernel-config.mount
├── sys-kernel-debug.mount
├── sys-kernel-tracing.mount
├── system.slice
└── user.slice

10 directories, 20 files

cgroup v1。

$ tree -L 1 /sys/fs/cgroup/
/sys/fs/cgroup/
├── blkio
├── cpu -> cpu,cpuacct
├── cpu,cpuacct
├── cpuacct -> cpu,cpuacct
├── cpuset
├── devices
├── freezer
├── hugetlb
├── memory
├── net_cls -> net_cls,net_prio
├── net_cls,net_prio
├── net_prio -> net_cls,net_prio
├── perf_event
├── pids
├── rdma
├── systemd
└── unified

17 directories, 0 files

これらがcgroupのコントロヌラヌですね。

以降、もう少し違う角床で情報を芋おいっおみたす。

mountコマンドで芋おみる

cgroupのコントロヌラヌはsysfsファむルシステム䞊で動䜜しおいるようなので、mountコマンドでも確認できそうです。

cgroup v2。

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

cgroup v1。

$ mount | grep cgroup
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
cgroup2 on /sys/fs/cgroup/unified type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,name=systemd)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
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/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,rdma)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)

cgroup v2では、階局は単䞀になりたす。

Unlike v1, cgroup v2 has only single hierarchy.

Control Group v2 / Basic Operations / Mounting

別解。/proc/self/mountinfoから。

cgroup v2。

$ cat /proc/self/mountinfo | grep cgroup
35 25 0:30 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw,nsdelegate,memory_recursiveprot

cgroup v1。

$ cat /proc/self/mountinfo | grep cgroup
36 26 0:30 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:9 - tmpfs tmpfs ro,mode=755
37 36 0:31 / /sys/fs/cgroup/unified rw,nosuid,nodev,noexec,relatime shared:10 - cgroup2 cgroup2 rw,nsdelegate
38 36 0:32 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:11 - cgroup cgroup rw,xattr,name=systemd
41 36 0:35 / /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime shared:15 - cgroup cgroup rw,hugetlb
42 36 0:36 / /sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,net_cls,net_prio
43 36 0:37 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:17 - cgroup cgroup rw,memory
44 36 0:38 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:18 - cgroup cgroup rw,pids
45 36 0:39 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:19 - cgroup cgroup rw,cpu,cpuacct
46 36 0:40 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:20 - cgroup cgroup rw,perf_event
47 36 0:41 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:21 - cgroup cgroup rw,cpuset
48 36 0:42 / /sys/fs/cgroup/rdma rw,nosuid,nodev,noexec,relatime shared:22 - cgroup cgroup rw,rdma
49 36 0:43 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:23 - cgroup cgroup rw,blkio
50 36 0:44 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:24 - cgroup cgroup rw,devices
51 36 0:45 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:25 - cgroup cgroup rw,freezer

コンテナ内でも芋おみたしょう。

cgroup v2。

$ docker container run -it --rm ubuntu:22.04 cat /proc/self/mountinfo | grep cgroup
618 617 0:30 / /sys/fs/cgroup ro,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw,nsdelegate,memory_recursiveprot

cgroup v1。

$ docker container run -it --rm ubuntu:20.04 cat /proc/self/mountinfo | grep cgroup
702 701 0:61 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - tmpfs tmpfs rw,mode=755
703 702 0:32 /docker/e71d4f44ee79dd9e2704f4e7131c5db6b5268eb137db847153b29b09c79d04f5 /sys/fs/cgroup/systemd ro,nosuid,nodev,noexec,relatime master:11 - cgroup cgroup rw,xattr,name=systemd
704 702 0:35 /docker/e71d4f44ee79dd9e2704f4e7131c5db6b5268eb137db847153b29b09c79d04f5 /sys/fs/cgroup/hugetlb ro,nosuid,nodev,noexec,relatime master:15 - cgroup cgroup rw,hugetlb
705 702 0:36 /docker/e71d4f44ee79dd9e2704f4e7131c5db6b5268eb137db847153b29b09c79d04f5 /sys/fs/cgroup/net_cls,net_prio ro,nosuid,nodev,noexec,relatime master:16 - cgroup cgroup rw,net_cls,net_prio
706 702 0:37 /docker/e71d4f44ee79dd9e2704f4e7131c5db6b5268eb137db847153b29b09c79d04f5 /sys/fs/cgroup/memory ro,nosuid,nodev,noexec,relatime master:17 - cgroup cgroup rw,memory
707 702 0:38 /docker/e71d4f44ee79dd9e2704f4e7131c5db6b5268eb137db847153b29b09c79d04f5 /sys/fs/cgroup/pids ro,nosuid,nodev,noexec,relatime master:18 - cgroup cgroup rw,pids
708 702 0:39 /docker/e71d4f44ee79dd9e2704f4e7131c5db6b5268eb137db847153b29b09c79d04f5 /sys/fs/cgroup/cpu,cpuacct ro,nosuid,nodev,noexec,relatime master:19 - cgroup cgroup rw,cpu,cpuacct
709 702 0:40 /docker/e71d4f44ee79dd9e2704f4e7131c5db6b5268eb137db847153b29b09c79d04f5 /sys/fs/cgroup/perf_event ro,nosuid,nodev,noexec,relatime master:20 - cgroup cgroup rw,perf_event
710 702 0:41 /docker/e71d4f44ee79dd9e2704f4e7131c5db6b5268eb137db847153b29b09c79d04f5 /sys/fs/cgroup/cpuset ro,nosuid,nodev,noexec,relatime master:21 - cgroup cgroup rw,cpuset
711 702 0:42 /docker/e71d4f44ee79dd9e2704f4e7131c5db6b5268eb137db847153b29b09c79d04f5 /sys/fs/cgroup/rdma ro,nosuid,nodev,noexec,relatime master:22 - cgroup cgroup rw,rdma
712 702 0:43 /docker/e71d4f44ee79dd9e2704f4e7131c5db6b5268eb137db847153b29b09c79d04f5 /sys/fs/cgroup/blkio ro,nosuid,nodev,noexec,relatime master:23 - cgroup cgroup rw,blkio
713 702 0:44 /docker/e71d4f44ee79dd9e2704f4e7131c5db6b5268eb137db847153b29b09c79d04f5 /sys/fs/cgroup/devices ro,nosuid,nodev,noexec,relatime master:24 - cgroup cgroup rw,devices
714 702 0:45 /docker/e71d4f44ee79dd9e2704f4e7131c5db6b5268eb137db847153b29b09c79d04f5 /sys/fs/cgroup/freezer ro,nosuid,nodev,noexec,relatime master:25 - cgroup cgroup rw,freezer

/proc/[pid]/cgroupで芋おみる

最埌に自分自身が所属するcgroupの情報を、/proc/self/cgroupで芋おみたしょう。

cgroup v2。

$ cat /proc/self/cgroup
0::/user.slice/user-1000.slice/session-4.scope

cgroup v1。

$ cat /proc/self/cgroup
12:freezer:/
11:devices:/user.slice
10:blkio:/user.slice
9:rdma:/
8:cpuset:/
7:perf_event:/
6:cpu,cpuacct:/user.slice
5:pids:/user.slice/user-1000.slice/session-6.scope
4:memory:/user.slice/user-1000.slice/session-6.scope
3:net_cls,net_prio:/
2:hugetlb:/
1:name=systemd:/user.slice/user-1000.slice/session-6.scope
0::/user.slice/user-1000.slice/session-6.scope

プロセスが所属するcgroupは、/proc/[pid]/cgroupで確認できたす。自プロセスの堎合は、/proc/self/cgroupずなりたす。

cgroupの名前空間は、/proc/[pid]/cgroupファむルずcgroupファむルシステムv1の堎合はtmpfsファむルシステムで衚珟されるこずが
曞かれおいたす。

コンテナ内で確認しおみたしょう。

cgroup v2。

$ docker container run -it --rm ubuntu:22.04 cat /proc/self/cgroup
0::/

cgroup v1。

$ docker container run -it --rm ubuntu:20.04 cat /proc/self/cgroup
12:freezer:/docker/149c401b108d6be632678c8325ae96dbf9a7aba8c413747b2e1d764c61a128bc
11:devices:/docker/149c401b108d6be632678c8325ae96dbf9a7aba8c413747b2e1d764c61a128bc
10:blkio:/docker/149c401b108d6be632678c8325ae96dbf9a7aba8c413747b2e1d764c61a128bc
9:rdma:/docker/149c401b108d6be632678c8325ae96dbf9a7aba8c413747b2e1d764c61a128bc
8:cpuset:/docker/149c401b108d6be632678c8325ae96dbf9a7aba8c413747b2e1d764c61a128bc
7:perf_event:/docker/149c401b108d6be632678c8325ae96dbf9a7aba8c413747b2e1d764c61a128bc
6:cpu,cpuacct:/docker/149c401b108d6be632678c8325ae96dbf9a7aba8c413747b2e1d764c61a128bc
5:pids:/docker/149c401b108d6be632678c8325ae96dbf9a7aba8c413747b2e1d764c61a128bc
4:memory:/docker/149c401b108d6be632678c8325ae96dbf9a7aba8c413747b2e1d764c61a128bc
3:net_cls,net_prio:/docker/149c401b108d6be632678c8325ae96dbf9a7aba8c413747b2e1d764c61a128bc
2:hugetlb:/docker/149c401b108d6be632678c8325ae96dbf9a7aba8c413747b2e1d764c61a128bc
1:name=systemd:/docker/149c401b108d6be632678c8325ae96dbf9a7aba8c413747b2e1d764c61a128bc
0::/docker/149c401b108d6be632678c8325ae96dbf9a7aba8c413747b2e1d764c61a128bc

cgroup v1の/docker/の埌ろに芋えおいるのは、コンテナのidですね。

䜙談

cgroup v1の堎合、自分自身のコンテナのidは/proc/self/cgroupや/proc/self/mountinfoを芋ればわかるこずになりたす。

ではcgroup v2の堎合はずいうず、/proc/self/mountinfoのcgroupずしおマりントしおいる箇所以倖を芋ればよさそうです。

$ docker container run -it --rm ubuntu:22.04 cat /proc/self/mountinfo | grep docker
588 425 0:46 / / rw,relatime master:223 - overlay overlay rw,lowerdir=/var/lib/docker/overlay2/l/XZFSJBHY5DCBKZT3WS3UVIIMNL:/var/lib/docker/overlay2/l/EJEZWN23ZAMZZ2VSUXSWEOV3OX,upperdir=/var/lib/docker/overlay2/a6049ac9fab5259cdddbeb67d0b36f2f6313f09a07a4b79a70097d00ca4c4ce5/diff,workdir=/var/lib/docker/overlay2/a6049ac9fab5259cdddbeb67d0b36f2f6313f09a07a4b79a70097d00ca4c4ce5/work
621 588 253:0 /var/lib/docker/containers/d2454afd9c7b4c47b726c8f556e6f83b100a464b4f6440fe9f0c92fcb39c61ea/resolv.conf /etc/resolv.conf rw,relatime - ext4 /dev/mapper/ubuntu--vg-ubuntu--lv rw
622 588 253:0 /var/lib/docker/containers/d2454afd9c7b4c47b726c8f556e6f83b100a464b4f6440fe9f0c92fcb39c61ea/hostname /etc/hostname rw,relatime - ext4 /dev/mapper/ubuntu--vg-ubuntu--lv rw
623 588 253:0 /var/lib/docker/containers/d2454afd9c7b4c47b726c8f556e6f83b100a464b4f6440fe9f0c92fcb39c61ea/hosts /etc/hosts rw,relatime - ext4 /dev/mapper/ubuntu--vg-ubuntu--lv rw

こんなずころでしょうか。

おわりに

䜿甚しおいるLinux環境のcgroupが、v1なのかv2なのかを確認する方法をちょっず調べおみたした。ちょっず脱線もしおいたすけど。

あたり明瀺的に確認する機䌚はない気がしたすが、コンテナに関する呚蟺知識を芋おいける感じなのでたたにこういうのを远っおみるず
面癜いですね。

/sys/fs/cgroupや/proc/self/cgroup、/proc/self/mountinfoはランタむムやラむブラリヌのコンテナ察応でも出おくるので、
芚えおおくずよいかもしれたせん。

過去に曞いた゚ントリヌは、このあたりです。

JavaがDockerコンテナ内でどのようにCPU数、メモリサイズを取得しているのかを調べてみる - CLOVER🍀

Dockerコンテナ内で動作するNode.jsが認識するCPU数、メモリサイズ(ヒープサイズ除く)は、ホスト側のものになるという話 - CLOVER🍀