podman: add option --cgroup-conf

it allows to manually tweak the configuration for cgroup v2.

we will expose some of the options in future as single
options (e.g. the new memory knobs), but for now add the more generic
--cgroup-conf mechanism for maximum control on the cgroup
configuration.

OCI specs change: https://github.com/opencontainers/runtime-spec/pull/1040

Requires: https://github.com/containers/crun/pull/459

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano
2020-08-19 14:11:16 +02:00
parent 3967c46544
commit d856210ea8
11 changed files with 50 additions and 7 deletions

View File

@ -516,5 +516,10 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
"seccomp-policy", "default", "seccomp-policy", "default",
"Policy for selecting a seccomp profile (experimental)", "Policy for selecting a seccomp profile (experimental)",
) )
createFlags.StringSliceVar(
&cf.CgroupConf,
"cgroup-conf", []string{},
"Configure cgroup v2 (key=value)",
)
return &createFlags return &createFlags
} }

View File

@ -106,4 +106,6 @@ type ContainerCLIOpts struct {
SeccompPolicy string SeccompPolicy string
Net *entities.NetOptions Net *entities.NetOptions
CgroupConf []string
} }

View File

@ -450,7 +450,20 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
s.ResourceLimits.Pids = &pids s.ResourceLimits.Pids = &pids
} }
s.ResourceLimits.CPU = getCPULimits(c) 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 s.ResourceLimits = nil
} }

View File

@ -2107,6 +2107,7 @@ _podman_container_run() {
--cap-add --cap-add
--cap-drop --cap-drop
--cgroup-parent --cgroup-parent
--cgroup-conf
--cidfile --cidfile
--conmon-pidfile --conmon-pidfile
--cpu-period --cpu-period

View File

@ -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. 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* **--cidfile**=*id*
Write the container ID to the file Write the container ID to the file

View File

@ -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. 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* **--cidfile**=*file*
Write the container ID to *file*. Write the container ID to *file*.

View File

@ -465,6 +465,7 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named
if ctrSpec.Linux.Resources.Pids != nil { if ctrSpec.Linux.Resources.Pids != nil {
hostConfig.PidsLimit = ctrSpec.Linux.Resources.Pids.Limit hostConfig.PidsLimit = ctrSpec.Linux.Resources.Pids.Limit
} }
hostConfig.CgroupConf = ctrSpec.Linux.Resources.Unified
if ctrSpec.Linux.Resources.BlockIO != nil { if ctrSpec.Linux.Resources.BlockIO != nil {
if ctrSpec.Linux.Resources.BlockIO.Weight != nil { if ctrSpec.Linux.Resources.BlockIO.Weight != nil {
hostConfig.BlkioWeight = *ctrSpec.Linux.Resources.BlockIO.Weight hostConfig.BlkioWeight = *ctrSpec.Linux.Resources.BlockIO.Weight

View File

@ -518,6 +518,8 @@ type InspectContainerHostConfig struct {
IOMaximumIOps uint64 `json:"IOMaximumIOps"` IOMaximumIOps uint64 `json:"IOMaximumIOps"`
// IOMaximumBandwidth is Windows-only and not presently implemented. // IOMaximumBandwidth is Windows-only and not presently implemented.
IOMaximumBandwidth uint64 `json:"IOMaximumBandwidth"` 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 // InspectBasicNetworkConfig holds basic configuration information (e.g. IP

View File

@ -31,12 +31,13 @@ const (
type CreateResourceConfig struct { type CreateResourceConfig struct {
BlkioWeight uint16 // blkio-weight BlkioWeight uint16 // blkio-weight
BlkioWeightDevice []string // blkio-weight-device BlkioWeightDevice []string // blkio-weight-device
CPUPeriod uint64 // cpu-period CgroupConf map[string]string
CPUQuota int64 // cpu-quota CPUPeriod uint64 // cpu-period
CPURtPeriod uint64 // cpu-rt-period CPUQuota int64 // cpu-quota
CPURtRuntime int64 // cpu-rt-runtime CPURtPeriod uint64 // cpu-rt-period
CPUShares uint64 // cpu-shares CPURtRuntime int64 // cpu-rt-runtime
CPUs float64 // cpus CPUShares uint64 // cpu-shares
CPUs float64 // cpus
CPUsetCPUs string CPUsetCPUs string
CPUsetMems string // cpuset-mems CPUsetMems string // cpuset-mems
DeviceCgroupRules []string //device-cgroup-rule DeviceCgroupRules []string //device-cgroup-rule

View File

@ -23,6 +23,12 @@ func verifyContainerResources(s *specgen.SpecGenerator) ([]string, error) {
return warnings, nil return warnings, nil
} }
if s.ResourceLimits.Unified != nil {
if !cgroup2 {
return nil, errors.New("Cannot use --cgroup-conf without cgroup v2")
}
}
// Memory checks // Memory checks
if s.ResourceLimits.Memory != nil { if s.ResourceLimits.Memory != nil {
memory := s.ResourceLimits.Memory memory := s.ResourceLimits.Memory

View File

@ -415,6 +415,10 @@ type ContainerResourceConfig struct {
ThrottleReadIOPSDevice map[string]spec.LinuxThrottleDevice `json:"throttleReadIOPSDevice,omitempty"` ThrottleReadIOPSDevice map[string]spec.LinuxThrottleDevice `json:"throttleReadIOPSDevice,omitempty"`
// IO write rate limit per cgroup per device, IO per second // IO write rate limit per cgroup per device, IO per second
ThrottleWriteIOPSDevice map[string]spec.LinuxThrottleDevice `json:"throttleWriteIOPSDevice,omitempty"` 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 // ContainerHealthCheckConfig describes a container healthcheck with attributes