Replace the experimental --mount-cgroup-v2 flag with in-sandbox-cgroup

The new flag is not a boolean flag, in deference to PR#14197.

PiperOrigin-RevId: 970257422
This commit is contained in:
Shailend Chand
2026-08-24 20:29:27 -07:00
committed by gVisor bot
parent 134522f2d9
commit baf615a53c
13 changed files with 96 additions and 50 deletions
+1 -1
View File
@@ -434,7 +434,7 @@ docker-tests: integration-test-images $(RUNTIME_BIN)
@$(call install_runtime_noreload,$(RUNTIME)-dcache,--fdlimit=2000 --dcache=100) # Used by TestDentryCacheLimit.
@$(call install_runtime_noreload,$(RUNTIME)-host-uds,--host-uds=all) # Used by TestHostSocketConnect.
@$(call install_runtime_noreload,$(RUNTIME)-overlay,--overlay2=all:self) # Used by TestOverlay*.
@$(call install_runtime,$(RUNTIME)-cgroupv2,--mount-cgroup-v2) # Used by TestSystemd* and TestPIDFDSelftests.
@$(call install_runtime,$(RUNTIME)-cgroupv2,--in-sandbox-cgroup=v2) # Used by TestSystemd* and TestPIDFDSelftests.
@$(call test_runtime_cached,$(RUNTIME),$(INTEGRATION_TARGETS) --test_env=TEST_SAVE_RESTORE_NETSTACK=true //test/e2e:integration_runtime_test //test/e2e:runtime_in_docker_test)
.PHONY: docker-tests
+6 -6
View File
@@ -284,8 +284,8 @@ type Loader struct {
sharedMounts map[string]*vfs.Mount
// cgroup2Mount is an internal mount of the cgroup2fs singleton used to
// manage per-container cgroups. It is only set when MountCgroupV2 is
// enabled.
// manage per-container cgroups. It is only set when InSandboxCgroup is
// InSandboxCgroupV2.
//
// +checklocks:mu
cgroup2Mount *vfs.Mount
@@ -1534,7 +1534,7 @@ func (l *Loader) createContainerProcess(info *containerInfo) (*kernel.ThreadGrou
l.startGoferMonitor(info)
if l.root.cid == l.sandboxID {
if l.root.conf.MountCgroupV2 {
if l.root.conf.InSandboxCgroup == config.InSandboxCgroupV2 {
if err := l.setupCgroup2(); err != nil {
return nil, nil, err
}
@@ -1545,7 +1545,7 @@ func (l *Loader) createContainerProcess(info *containerInfo) (*kernel.ThreadGrou
}
}
}
if l.root.conf.MountCgroupV2 {
if l.root.conf.InSandboxCgroup == config.InSandboxCgroupV2 {
// Create the container's cgroup and resolve its cgroup namespace
// before the container's mounts are set up, so that its
// /sys/fs/cgroup mount is rooted per the namespace.
@@ -1690,7 +1690,7 @@ func (l *Loader) destroySubcontainer(cid string) error {
// Cleanup the device gofer.
l.k.RemoveDevGofer(l.k.ContainerName(cid))
if l.root.conf.MountCgroupV2 {
if l.root.conf.InSandboxCgroup == config.InSandboxCgroupV2 {
l.removeContainerCgroup2(cid)
}
@@ -1737,7 +1737,7 @@ func (l *Loader) executeAsync(args *control.ExecArgs) (kernel.ThreadID, error) {
}
args.PIDNamespace = tg.PIDNamespace()
if l.root.conf.MountCgroupV2 {
if l.root.conf.InSandboxCgroup == config.InSandboxCgroupV2 {
// Join the container's cgroup and cgroup namespace, like Linux's
// runc exec does.
leader := tg.Leader()
+5 -5
View File
@@ -130,7 +130,7 @@ func registerFilesystems(k *kernel.Kernel, info *containerInfo, rdmaSnapshot *rd
AllowUserMount: true,
AllowUserList: true,
})
if info.conf.MountCgroupV2 {
if info.conf.InSandboxCgroup == config.InSandboxCgroupV2 {
vfsObj.MustRegisterFilesystemType(cgroup2fs.Name, &cgroup2fs.FilesystemType{}, &vfs.RegisterFilesystemTypeOptions{
AllowUserMount: true,
AllowUserList: true,
@@ -284,7 +284,7 @@ func setupContainerVFS(ctx context.Context, info *containerInfo, mntr *container
// If cgroups are mounted, then only check for the cgroup mounts per
// container. Otherwise the root cgroups will be enabled.
if mntr.cgroupsMounted && !info.conf.MountCgroupV2 {
if mntr.cgroupsMounted && info.conf.InSandboxCgroup != config.InSandboxCgroupV2 {
cgroupRegistry := mntr.l.k.CgroupRegistry()
for _, ctrl := range kernel.CgroupCtrls {
cg, err := cgroupRegistry.FindCgroup(ctx, ctrl, "/"+mntr.containerID)
@@ -339,7 +339,7 @@ func compileMounts(spec *specs.Spec, conf *config.Config, containerID string) []
// Mount all submounts from the spec.
for _, m := range spec.Mounts {
if conf.MountCgroupV2 {
if conf.InSandboxCgroup == config.InSandboxCgroupV2 {
// Under this flag, we only want a single unified mount at
// /sys/fs/cgroup. Skip any legacy v1 controller sub-mounts
// (e.g., /sys/fs/cgroup/cpu) requested by the OCI spec.
@@ -885,9 +885,9 @@ func (c *containerMounter) mountSubmounts(ctx context.Context, spec *specs.Spec,
return fmt.Errorf("mount shared mount %q to %q: %v", submount.hint.Name, submount.mount.Destination, err)
}
} else if submount.mount.Type == cgroupfs.Name || submount.mount.Type == cgroup2fs.Name {
if conf.MountCgroupV2 {
if conf.InSandboxCgroup == config.InSandboxCgroupV2 {
// There is no "type: cgroup2" defined in the OCI spec.
// So, when the runsc flag MountCgroupV2 is set, we honor the
// So, when the runsc flag InSandboxCgroup is set to v2, we honor the
// OCI request for "type: cgroupfs" by a v2 mount.
if submount.mount.Type == cgroupfs.Name {
submount.mount.Type = cgroup2fs.Name
+46 -2
View File
@@ -321,8 +321,8 @@ type Config struct {
// Don't configure cgroups.
IgnoreCgroups bool `flag:"ignore-cgroups"`
// Mount cgroup v2 instead of cgroup v1 inside the sandbox.
MountCgroupV2 bool `flag:"mount-cgroup-v2"`
// InSandboxCgroup indicates the cgroup setup inside the sandbox.
InSandboxCgroup InSandboxCgroupType `flag:"in-sandbox-cgroup"`
// Use systemd to configure cgroups.
SystemdCgroup bool `flag:"systemd-cgroup"`
@@ -843,6 +843,50 @@ func (n GoferNetworkNamespace) String() string {
return string(n)
}
// InSandboxCgroupType tells which cgroup setup to use inside the sandbox.
type InSandboxCgroupType int
const (
// InSandboxCgroupV1 mounts cgroup v1 inside the sandbox.
InSandboxCgroupV1 InSandboxCgroupType = iota
// InSandboxCgroupV2 mounts cgroup v2 inside the sandbox.
InSandboxCgroupV2
)
func inSandboxCgroupTypePtr(v InSandboxCgroupType) *InSandboxCgroupType {
return &v
}
// Set implements flag.Value. Set(String()) should be idempotent.
func (c *InSandboxCgroupType) Set(v string) error {
switch v {
case "v1":
*c = InSandboxCgroupV1
case "v2":
*c = InSandboxCgroupV2
default:
return fmt.Errorf("invalid in-sandbox-cgroup %q", v)
}
return nil
}
// Get implements flag.Value.
func (c *InSandboxCgroupType) Get() any {
return *c
}
// String implements flag.Value.
func (c InSandboxCgroupType) String() string {
switch c {
case InSandboxCgroupV1:
return "v1"
case InSandboxCgroupV2:
return "v2"
}
panic(fmt.Sprintf("Invalid in-sandbox cgroup type %d", c))
}
// QueueingDiscipline is used to specify the kind of Queueing Discipline to
// apply for a give FDBasedLink.
type QueueingDiscipline int
+9 -4
View File
@@ -451,6 +451,11 @@ func TestOverrideError(t *testing.T) {
value: "invalid",
error: "invalid file access type",
},
{
name: "in-sandbox-cgroup",
value: "invalid",
error: "invalid in-sandbox-cgroup",
},
} {
t.Run(tc.name, func(t *testing.T) {
if err := c.Override(testFlags, tc.name, tc.value, false); err == nil || !strings.Contains(err.Error(), tc.error) {
@@ -483,12 +488,12 @@ func TestOverrideAllowlist(t *testing.T) {
error: "error setting flag",
},
{
flag: "mount-cgroup-v2",
value: "true",
flag: "in-sandbox-cgroup",
value: "v1",
},
{
flag: "mount-cgroup-v2",
value: "false",
flag: "in-sandbox-cgroup",
value: "v2",
},
{
flag: "oci-seccomp",
+3 -3
View File
@@ -47,7 +47,7 @@ const (
flagQDisc = "qdisc"
flagQDiscTBFRate = "qdisc-tbf-rate"
flagQDiscTBFBurst = "qdisc-tbf-burst"
flagMountCgroupV2 = "mount-cgroup-v2"
flagInSandboxCgroup = "in-sandbox-cgroup"
maxQDiscTBFBurst = uint64(1<<32 - 1)
defaultQDiscTBFRate = uint64(0)
@@ -149,7 +149,7 @@ func RegisterFlags(flagSet *flag.FlagSet) {
flagSet.String("override-procs", "", "comma-separated list of proc files to override with stubs (e.g. kallsyms)")
flagSet.Bool("ignore-cgroups", false, "don't configure cgroups.")
flagSet.Bool(flagMountCgroupV2, false, "EXPERIMENTAL. Mount cgroup v2 instead of cgroup v1 inside the sandbox. cgroup v2 support in gVisor is experimental and incomplete. Do not use for production workloads.")
flagSet.Var(inSandboxCgroupTypePtr(InSandboxCgroupV1), flagInSandboxCgroup, "cgroup setup to use inside the sandbox: v1 (default), v2.")
flagSet.Int("fdlimit", -1, "Specifies a limit on the number of host file descriptors that can be open. Applies separately to the sentry and gofer. Note: each file in the sandbox holds more than one host FD open.")
flagSet.Int("dcache", -1, "Set the global dentry cache size. This acts as a coarse-grained control on the number of host FDs simultaneously open by the sentry. If negative, per-mount caches are used.")
flagSet.Bool("iouring", false, "TEST ONLY; Enables io_uring syscalls in the sentry. Support is experimental and very limited.")
@@ -222,7 +222,7 @@ var overrideAllowlist = map[string]struct {
flagQDisc: {check: checkQDisc},
flagQDiscTBFRate: {check: checkQDiscTBFRate},
flagQDiscTBFBurst: {check: checkQDiscTBFBurst},
flagMountCgroupV2: {},
flagInSandboxCgroup: {},
}
// checkOverlay2 ensures that overlay2 can only be enabled using "memory" or
+1
View File
@@ -52,4 +52,5 @@ func RegisterDeprecatedFlags(flagSet *flag.FlagSet) {
deprecatedBool(flagSet, "cgroupfs", false, "DEPRECATED: this flag has no effect.", time.Date(2027, time.January, 1, 0, 0, 0, 0, time.UTC))
deprecatedBool(flagSet, "fsgofer-host-uds", false, "DEPRECATED: use host-uds=all", time.Date(2027, time.January, 1, 0, 0, 0, 0, time.UTC))
deprecatedBool(flagSet, "save-restore-netstack", true, "DEPRECATED: this flag has no effect.", time.Date(2027, time.January, 1, 0, 0, 0, 0, time.UTC))
deprecatedBool(flagSet, "mount-cgroup-v2", false, "DEPRECATED: use in-sandbox-cgroup=v2", time.Date(2027, time.January, 1, 0, 0, 0, 0, time.UTC))
}
+4 -4
View File
@@ -2373,7 +2373,7 @@ func TestMultiContainerEvent(t *testing.T) {
t.Run(name, func(t *testing.T) {
conf := testutil.TestConfig(t)
if name == "enableCgroupsV2" {
conf.MountCgroupV2 = true
conf.InSandboxCgroup = config.InSandboxCgroupV2
}
rootDir, cleanup, err := testutil.SetupRootDir()
if err != nil {
@@ -2510,7 +2510,7 @@ func TestMultiContainerEvent(t *testing.T) {
func TestCgroupV2ReadControlFile(t *testing.T) {
conf := testutil.TestConfig(t)
conf.MountCgroupV2 = true
conf.InSandboxCgroup = config.InSandboxCgroupV2
rootDir, cleanup, err := testutil.SetupRootDir()
if err != nil {
@@ -2581,7 +2581,7 @@ func TestCgroupV2ReadControlFile(t *testing.T) {
// mount in its spec is never given a cgroup2 node.
func TestMultiContainerCgroupV2Destroy(t *testing.T) {
conf := testutil.TestConfig(t)
conf.MountCgroupV2 = true
conf.InSandboxCgroup = config.InSandboxCgroupV2
rootDir, cleanup, err := testutil.SetupRootDir()
if err != nil {
@@ -3233,7 +3233,7 @@ func TestMultiContainerCgroupsMemoryUsage(t *testing.T) {
for name, conf := range configs(t, false /* noOverlay */) {
if cgroupV2 {
name += "-cgroupV2"
conf.MountCgroupV2 = true
conf.InSandboxCgroup = config.InSandboxCgroupV2
}
t.Run(name, func(t *testing.T) {
rootDir, cleanup, err := testutil.SetupRootDir()
+1 -1
View File
@@ -313,7 +313,7 @@ func TestOverlayCheckpointRestore(t *testing.T) {
func TestPIDFDSelftests(t *testing.T) {
ctx := context.Background()
// pidfd_setns_test creates cgroup namespaces, which requires cgroup2fs to
// be mounted in the sandbox (--mount-cgroup-v2).
// be mounted in the sandbox (--in-sandbox-cgroup=v2).
d := dockerutil.MakeContainerWithRuntime(ctx, t, "-cgroupv2")
defer d.CleanUp(ctx)
+14 -16
View File
@@ -83,7 +83,7 @@ def _syscall_test(
netstack_sr = False,
nftables = False,
kvm_use_cpu_nums = True,
mount_cgroup_v2 = False,
in_sandbox_cgroup = "v1",
**kwargs):
# Prepend "runsc" to non-native platform names.
full_platform = platform if platform == "native" else "runsc_" + platform
@@ -184,10 +184,8 @@ def _syscall_test(
"--kvm-use-cpu-nums=" + str(kvm_use_cpu_nums),
]
if mount_cgroup_v2:
runner_args.append("--mount-cgroup-v2=true")
else:
runner_args.append("--mount-cgroup-v2=false")
if in_sandbox_cgroup:
runner_args.append("--in-sandbox-cgroup=" + in_sandbox_cgroup)
# Trace points are platform agnostic, so enable them for ptrace only.
if platform == "ptrace":
@@ -234,7 +232,7 @@ def syscall_test_variants(
netstack_sr = False,
nftables = False,
kvm_use_cpu_nums = False,
mount_cgroup_v2 = False,
in_sandbox_cgroup = "v1",
**kwargs):
"""Generates syscall tests for all variants.
@@ -292,7 +290,7 @@ def syscall_test_variants(
netstack_sr = netstack_sr,
nftables = nftables,
kvm_use_cpu_nums = kvm_use_cpu_nums,
mount_cgroup_v2 = mount_cgroup_v2,
in_sandbox_cgroup = in_sandbox_cgroup,
**kwargs
)
@@ -319,7 +317,7 @@ def syscall_test_variants(
netstack_sr = netstack_sr,
nftables = nftables,
kvm_use_cpu_nums = kvm_use_cpu_nums,
mount_cgroup_v2 = mount_cgroup_v2,
in_sandbox_cgroup = in_sandbox_cgroup,
**kwargs
)
@@ -348,7 +346,7 @@ def syscall_test_variants(
netstack_sr = netstack_sr,
nftables = nftables,
kvm_use_cpu_nums = kvm_use_cpu_nums,
mount_cgroup_v2 = mount_cgroup_v2,
in_sandbox_cgroup = in_sandbox_cgroup,
**kwargs
)
if not use_tmpfs:
@@ -375,7 +373,7 @@ def syscall_test_variants(
netstack_sr = netstack_sr,
nftables = nftables,
kvm_use_cpu_nums = kvm_use_cpu_nums,
mount_cgroup_v2 = mount_cgroup_v2,
in_sandbox_cgroup = in_sandbox_cgroup,
**kwargs
)
if add_fusefs:
@@ -400,7 +398,7 @@ def syscall_test_variants(
netstack_sr = netstack_sr,
nftables = nftables,
kvm_use_cpu_nums = kvm_use_cpu_nums,
mount_cgroup_v2 = mount_cgroup_v2,
in_sandbox_cgroup = in_sandbox_cgroup,
**kwargs
)
@@ -429,7 +427,7 @@ def syscall_test(
nftables = False,
perf = False,
kvm_use_cpu_nums = False,
mount_cgroup_v2 = False,
in_sandbox_cgroup = "v1",
**kwargs):
"""syscall_test is a macro that will create targets for all platforms.
@@ -488,7 +486,7 @@ def syscall_test(
container = container,
one_sandbox = one_sandbox,
kvm_use_cpu_nums = kvm_use_cpu_nums,
mount_cgroup_v2 = mount_cgroup_v2,
in_sandbox_cgroup = in_sandbox_cgroup,
**kwargs
)
@@ -517,7 +515,7 @@ def syscall_test(
netstack_sr = False,
nftables = nftables,
kvm_use_cpu_nums = kvm_use_cpu_nums,
mount_cgroup_v2 = mount_cgroup_v2,
in_sandbox_cgroup = in_sandbox_cgroup,
**kwargs
)
@@ -550,7 +548,7 @@ def syscall_test(
netstack_sr = False,
nftables = nftables,
kvm_use_cpu_nums = kvm_use_cpu_nums,
mount_cgroup_v2 = mount_cgroup_v2,
in_sandbox_cgroup = in_sandbox_cgroup,
**kwargs
)
@@ -609,6 +607,6 @@ def syscall_test(
netstack_sr = False,
nftables = nftables,
kvm_use_cpu_nums = kvm_use_cpu_nums,
mount_cgroup_v2 = mount_cgroup_v2,
in_sandbox_cgroup = in_sandbox_cgroup,
**kwargs
)
+3 -5
View File
@@ -79,7 +79,7 @@ var (
netstackSR = flag.Bool("netstack-sr", false, "enables netstack s/r")
nftables = flag.Bool("nftables", false, "enables nftables")
kvmUseCPUNums = flag.Bool("kvm-use-cpu-nums", false, "use cpu numbers in kvm platform")
mountCgroupV2 = flag.Bool("mount-cgroup-v2", false, "mount cgroups v2")
inSandboxCgroup = flag.String("in-sandbox-cgroup", "v1", "cgroup setup to use inside the sandbox (v1 or v2)")
)
const (
@@ -444,10 +444,8 @@ func runRunsc(tc *gtest.TestCase, spec *specs.Spec) error {
} else {
args = append(args, "-kvm-use-cpu-nums=false")
}
if *mountCgroupV2 {
args = append(args, "-mount-cgroup-v2=true")
} else {
args = append(args, "-mount-cgroup-v2=false")
if *inSandboxCgroup != "" {
args = append(args, "-in-sandbox-cgroup="+*inSandboxCgroup)
}
testLogDir := ""
+2 -2
View File
@@ -77,7 +77,7 @@ syscall_test(
syscall_test(
size = "large",
mount_cgroup_v2 = True,
in_sandbox_cgroup = "v2",
shard_count = more_shards,
test = "//test/syscalls/linux:cgroup2_test",
)
@@ -193,7 +193,7 @@ syscall_test(
)
syscall_test(
mount_cgroup_v2 = True,
in_sandbox_cgroup = "v2",
test = "//test/syscalls/linux:cgroup2_ebpf_test",
)
+1 -1
View File
@@ -104,7 +104,7 @@ apps:
category: "System software"
verdict: "experimental"
version: "259.5"
notes: "Requires the experimental `--mount-cgroup-v2` runsc flag."
notes: "Requires the `--in-sandbox-cgroup=v2` runsc flag."
test_source: "test/e2e/systemd_test.go"
- name: "Apache Kafka"