diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go index 403a1065bb..d0bc8d4668 100644 --- a/cmd/podman/common/create.go +++ b/cmd/podman/common/create.go @@ -516,5 +516,10 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet { "seccomp-policy", "default", "Policy for selecting a seccomp profile (experimental)", ) + createFlags.StringSliceVar( + &cf.CgroupConf, + "cgroup-conf", []string{}, + "Configure cgroup v2 (key=value)", + ) return &createFlags } diff --git a/cmd/podman/common/create_opts.go b/cmd/podman/common/create_opts.go index f9e4d7ca5b..16d41988ff 100644 --- a/cmd/podman/common/create_opts.go +++ b/cmd/podman/common/create_opts.go @@ -106,4 +106,6 @@ type ContainerCLIOpts struct { SeccompPolicy string Net *entities.NetOptions + + CgroupConf []string } diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go index bf50bb56bb..4de622916b 100644 --- a/cmd/podman/common/specgen.go +++ b/cmd/podman/common/specgen.go @@ -450,7 +450,20 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string s.ResourceLimits.Pids = &pids } s.ResourceLimits.CPU = getCPULimits(c) - if s.ResourceLimits.CPU == nil && s.ResourceLimits.Pids == nil && s.ResourceLimits.BlockIO == nil && s.ResourceLimits.Memory == nil { + + unifieds := make(map[string]string) + for _, unified := range c.CgroupConf { + splitUnified := strings.SplitN(unified, "=", 2) + if len(splitUnified) < 2 { + return errors.Errorf("--cgroup-conf must be formatted KEY=VALUE") + } + unifieds[splitUnified[0]] = splitUnified[1] + } + if len(unifieds) > 0 { + s.ResourceLimits.Unified = unifieds + } + + if s.ResourceLimits.CPU == nil && s.ResourceLimits.Pids == nil && s.ResourceLimits.BlockIO == nil && s.ResourceLimits.Memory == nil && s.ResourceLimits.Unified == nil { s.ResourceLimits = nil } diff --git a/completions/bash/podman b/completions/bash/podman index 379ba7fc8f..af222bf65a 100644 --- a/completions/bash/podman +++ b/completions/bash/podman @@ -2107,6 +2107,7 @@ _podman_container_run() { --cap-add --cap-drop --cgroup-parent + --cgroup-conf --cidfile --conmon-pidfile --cpu-period diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index 976a1e681c..2b5e866378 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -89,6 +89,10 @@ The *split* option splits the current cgroup in two sub-cgroups: one for conmon Path to cgroups under which the cgroup for the container will be created. If the path is not absolute, the path is considered to be relative to the cgroups path of the init process. Cgroups will be created if they do not already exist. +**--cgroup-conf**=*KEY=VALUE* + +When running on cgroup v2, specify the cgroup file to write to and its value. For example **--cgroup-conf=memory.high=1073741824** sets the memory.high limit to 1GB. + **--cidfile**=*id* Write the container ID to the file diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index b6c1fab177..4449b53fc8 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -104,6 +104,10 @@ The **split** option splits the current cgroup in two sub-cgroups: one for conmo Path to cgroups under which the cgroup for the container will be created. If the path is not absolute, the path is considered to be relative to the cgroups path of the init process. Cgroups will be created if they do not already exist. +**--cgroup-conf**=*KEY=VALUE* + +When running on cgroup v2, specify the cgroup file to write to and its value. For example **--cgroup-conf=memory.high=1073741824** sets the memory.high limit to 1GB. + **--cidfile**=*file* Write the container ID to *file*. diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go index 437729c2de..835dccd713 100644 --- a/libpod/container_inspect.go +++ b/libpod/container_inspect.go @@ -465,6 +465,7 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named if ctrSpec.Linux.Resources.Pids != nil { hostConfig.PidsLimit = ctrSpec.Linux.Resources.Pids.Limit } + hostConfig.CgroupConf = ctrSpec.Linux.Resources.Unified if ctrSpec.Linux.Resources.BlockIO != nil { if ctrSpec.Linux.Resources.BlockIO.Weight != nil { hostConfig.BlkioWeight = *ctrSpec.Linux.Resources.BlockIO.Weight diff --git a/libpod/define/container_inspect.go b/libpod/define/container_inspect.go index 8adf3c0773..44c3d515b2 100644 --- a/libpod/define/container_inspect.go +++ b/libpod/define/container_inspect.go @@ -518,6 +518,8 @@ type InspectContainerHostConfig struct { IOMaximumIOps uint64 `json:"IOMaximumIOps"` // IOMaximumBandwidth is Windows-only and not presently implemented. IOMaximumBandwidth uint64 `json:"IOMaximumBandwidth"` + // CgroupConf is the configuration for cgroup v2. + CgroupConf map[string]string `json:"CgroupConf"` } // InspectBasicNetworkConfig holds basic configuration information (e.g. IP diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index c49d51fc52..e0c875fe9f 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -31,12 +31,13 @@ const ( type CreateResourceConfig struct { BlkioWeight uint16 // blkio-weight BlkioWeightDevice []string // blkio-weight-device - CPUPeriod uint64 // cpu-period - CPUQuota int64 // cpu-quota - CPURtPeriod uint64 // cpu-rt-period - CPURtRuntime int64 // cpu-rt-runtime - CPUShares uint64 // cpu-shares - CPUs float64 // cpus + CgroupConf map[string]string + CPUPeriod uint64 // cpu-period + CPUQuota int64 // cpu-quota + CPURtPeriod uint64 // cpu-rt-period + CPURtRuntime int64 // cpu-rt-runtime + CPUShares uint64 // cpu-shares + CPUs float64 // cpus CPUsetCPUs string CPUsetMems string // cpuset-mems DeviceCgroupRules []string //device-cgroup-rule diff --git a/pkg/specgen/generate/validate.go b/pkg/specgen/generate/validate.go index dca45cc0e6..ed337321b0 100644 --- a/pkg/specgen/generate/validate.go +++ b/pkg/specgen/generate/validate.go @@ -23,6 +23,12 @@ func verifyContainerResources(s *specgen.SpecGenerator) ([]string, error) { return warnings, nil } + if s.ResourceLimits.Unified != nil { + if !cgroup2 { + return nil, errors.New("Cannot use --cgroup-conf without cgroup v2") + } + } + // Memory checks if s.ResourceLimits.Memory != nil { memory := s.ResourceLimits.Memory diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go index a9161071b1..a52225f877 100644 --- a/pkg/specgen/specgen.go +++ b/pkg/specgen/specgen.go @@ -415,6 +415,10 @@ type ContainerResourceConfig struct { ThrottleReadIOPSDevice map[string]spec.LinuxThrottleDevice `json:"throttleReadIOPSDevice,omitempty"` // IO write rate limit per cgroup per device, IO per second ThrottleWriteIOPSDevice map[string]spec.LinuxThrottleDevice `json:"throttleWriteIOPSDevice,omitempty"` + // CgroupConf are key-value options passed into the container runtime + // that are used to configure cgroup v2. + // Optional. + CgroupConf map[string]string `json:"unified,omitempty"` } // ContainerHealthCheckConfig describes a container healthcheck with attributes