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

  1. opts = append(opts,
  2. oci.WithDefaultSpec(),
  3. oci.WithDefaultUnixDevices,
  4. oci.WithMounts([]specs.Mount{
  5. {Type: "cgroup", Source: "cgroup", Destination: "/sys/fs/cgroup", Options: []string{"ro", "nosuid", "noexec", "nodev"}},
  6. }),
  7. WithoutRunMount(), // unmount default tmpfs on "/run": https://github.com/containerd/nerdctl/issues/157
  8. )

在runc中的实现

libcontainer/rootfs_linux.go mountToRootfs

  1. 先mount一个tmpfs到oci config.json中定义的destination
  2. 再挂载cgroup 的subsystem
    1. case "cgroup":
    2. if cgroups.IsCgroup2UnifiedMode() {
    3. return mountCgroupV2(m, c)
    4. }
    5. return mountCgroupV1(m, c)
  1. func mountCgroupV1(m *configs.Mount, c *mountConfig) error {
  2. binds, err := getCgroupMounts(m)
  3. if err != nil {
  4. return err
  5. }
  6. var merged []string
  7. for _, b := range binds {
  8. ss := filepath.Base(b.Destination)
  9. if strings.Contains(ss, ",") {
  10. merged = append(merged, ss)
  11. }
  12. }
  13. tmpfs := &configs.Mount{
  14. Source: "tmpfs",
  15. Device: "tmpfs",
  16. Destination: m.Destination,
  17. Flags: defaultMountFlags,
  18. Data: "mode=755",
  19. PropagationFlags: m.PropagationFlags,
  20. }
  21. if err := mountToRootfs(tmpfs, c); err != nil {
  22. return err
  23. }
  24. for _, b := range binds {
  25. if c.cgroupns {
  26. subsystemPath := filepath.Join(c.root, b.Destination)
  27. if err := os.MkdirAll(subsystemPath, 0755); err != nil {
  28. return err
  29. }
  30. // cgroup subsystem的mount flag,使用的是config.json中cgroup mount的options
  31. flags := defaultMountFlags
  32. if m.Flags&unix.MS_RDONLY != 0 {
  33. flags = flags | unix.MS_RDONLY
  34. }
  35. cgroupmount := &configs.Mount{
  36. Source: "cgroup",
  37. Device: "cgroup", // this is actually fstype
  38. Destination: subsystemPath,
  39. Flags: flags,
  40. Data: filepath.Base(subsystemPath),
  41. }
  42. if err := mountNewCgroup(cgroupmount); err != nil {
  43. return err
  44. }
  45. } else {
  46. if err := mountToRootfs(b, c); err != nil {
  47. return err
  48. }
  49. }
  50. }
  51. for _, mc := range merged {
  52. for _, ss := range strings.Split(mc, ",") {
  53. // symlink(2) is very dumb, it will just shove the path into
  54. // the link and doesn't do any checks or relative path
  55. // conversion. Also, don't error out if the cgroup already exists.
  56. if err := os.Symlink(mc, filepath.Join(c.root, m.Destination, ss)); err != nil && !os.IsExist(err) {
  57. return err
  58. }
  59. }
  60. }
  61. return nil
  62. }