cgroup模式检测

cgroup有v1和v2版本,系统上对cgroupfs的挂载支持三种不同的模式: 统一(Unified) — 最简单的方式,只暴露纯粹的cgroup v2接口。在该模式下,/sys/fs/cgroup 是唯一挂载到主机上的文件系统,所有的控制器都通过它暴露。 兼容(Legacy) — 传统的cgroup v1模式,该模式下不同的控制器拥有自己挂载目录:/sys/fs/cgroup/<controller>/。在此基础之上,systemd拥有自己的cgroup层级来实现管理功能:/sys/fs/cgroup/systemd/。 混合(Hybrid) — 这是上面两种模式的结合形式。这种模式和兼容模式非常相似,但是会多挂载一个层级目录/sys/fs/cgroup/unified/,该目录下包含cgoup v2的接口(但是该目录下只是暴露cgroupfs层级树,不包含控制器功能,控制器都挂载到了兼容模式的单独目录下,/sys/fs/cgroup/unified/仅仅是纯粹的cgroupfs的v2的功能能力,无关资源管控)。在此种模式下,既能够兼容cgroup v1的功能,又能使用一些cgroup v2的特性。 对于不同的操作系统发行版,或者相同发行版的不同版本,挂载模式可能都不一样,因此要使用cgroup功能,需要使用者(如runc,新版jvm)能够检测当前的系统上使用的是何种模式,对于检测何种模式可以使用下列简单的方式: 在根命名空间中,可以使用statfs()获取/sys/fs/cgroup/这个文件系统的类型,如果.f_type是 CGROUP2_SUPER_MAGIC,则说明是统一模式。如果.f_type是TMPFS_MAGIC ,则可能是cgroup v1模式或者可能是混合模式,更进一步检查可通过statfs()获取/sys/fs/cgroup/unified/的文件系统类型,如果它的.f_type是CGROUP2_SUPER_MAGIC,则说明使用的是混合模式,否则就是cgroup v1模式。 下面是containerd中的实现: // github.com/containerd/cgroups/utils.go // Mode returns the cgroups mode running on the host func Mode() CGMode { checkMode.Do(func() { var st unix.Statfs_t if err := unix.Statfs(unifiedMountpoint, &st); err != nil { cgMode = Unavailable return } switch st.Type { case unix.CGROUP2_SUPER_MAGIC: cgMode = Unified default: cgMode = Legacy if err := unix.Statfs(filepath.Join(unifiedMountpoint,…