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 []stringfor _, 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的optionsflags := defaultMountFlagsif m.Flags&unix.MS_RDONLY != 0 {flags = flags | unix.MS_RDONLY}cgroupmount := &configs.Mount{Source: "cgroup",Device: "cgroup", // this is actually fstypeDestination: 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}
