privilege下,设置cgroup fs为可写的方式
oci/spec_opts.go WithWriteableCgroupfs 目前只有在 WithPrivileged 时才会使用
cgroup fs默认挂载为ro
pkg/cri/server/instrumented_service.go CreateContainer
—> pkg/cri/server/container_create.go CreateContainer
——> pkg/cri/server/container_create_linux.go containerSpec
———> pkg/cri/opts/spec_linux.go WithMounts 加入 /sys/fs/cgroup
在nerdctl中的实现
run.go runAction
opts = append(opts,
oci.WithDefaultSpec(),
oci.WithDefaultUnixDevices,
oci.WithMounts([]specs.Mount{
{Type: "cgroup", Source: "cgroup", Destination: "/sys/fs/cgroup", Options: []string{"ro", "nosuid", "noexec", "nodev"}},
}),
WithoutRunMount(), // unmount default tmpfs on "/run": https://github.com/containerd/nerdctl/issues/157
)
在runc中的实现
libcontainer/rootfs_linux.go mountToRootfs
- 先mount一个tmpfs到oci config.json中定义的destination
- 再挂载cgroup 的subsystem
case "cgroup":
if cgroups.IsCgroup2UnifiedMode() {
return mountCgroupV2(m, c)
}
return mountCgroupV1(m, c)
func mountCgroupV1(m *configs.Mount, c *mountConfig) error {
binds, err := getCgroupMounts(m)
if err != nil {
return err
}
var merged []string
for _, b := range binds {
ss := filepath.Base(b.Destination)
if strings.Contains(ss, ",") {
merged = append(merged, ss)
}
}
tmpfs := &configs.Mount{
Source: "tmpfs",
Device: "tmpfs",
Destination: m.Destination,
Flags: defaultMountFlags,
Data: "mode=755",
PropagationFlags: m.PropagationFlags,
}
if err := mountToRootfs(tmpfs, c); err != nil {
return err
}
for _, b := range binds {
if c.cgroupns {
subsystemPath := filepath.Join(c.root, b.Destination)
if err := os.MkdirAll(subsystemPath, 0755); err != nil {
return err
}
// cgroup subsystem的mount flag,使用的是config.json中cgroup mount的options
flags := defaultMountFlags
if m.Flags&unix.MS_RDONLY != 0 {
flags = flags | unix.MS_RDONLY
}
cgroupmount := &configs.Mount{
Source: "cgroup",
Device: "cgroup", // this is actually fstype
Destination: subsystemPath,
Flags: flags,
Data: filepath.Base(subsystemPath),
}
if err := mountNewCgroup(cgroupmount); err != nil {
return err
}
} else {
if err := mountToRootfs(b, c); err != nil {
return err
}
}
}
for _, mc := range merged {
for _, ss := range strings.Split(mc, ",") {
// symlink(2) is very dumb, it will just shove the path into
// the link and doesn't do any checks or relative path
// conversion. Also, don't error out if the cgroup already exists.
if err := os.Symlink(mc, filepath.Join(c.root, m.Destination, ss)); err != nil && !os.IsExist(err) {
return err
}
}
}
return nil
}