Merge pull request #7372 from giuseppe/add-unified-configuration

podman: add option --cgroup-conf
This commit is contained in:
OpenShift Merge Robot 2020-08-24 09:55:14 -04:00 committed by GitHub
commit 8fdc116954
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 102 additions and 107 deletions

View File

@ -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
}

View File

@ -106,4 +106,6 @@ type ContainerCLIOpts struct {
SeccompPolicy string
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.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
}

View File

@ -2107,6 +2107,7 @@ _podman_container_run() {
--cap-add
--cap-drop
--cgroup-parent
--cgroup-conf
--cidfile
--conmon-pidfile
--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.
**--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

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.
**--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*.

4
go.mod
View File

@ -40,8 +40,8 @@ require (
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6
github.com/opencontainers/runc v1.0.0-rc91.0.20200708210054-ce54a9d4d79b
github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2
github.com/opencontainers/runtime-tools v0.9.1-0.20200714183735-07406c5828aa
github.com/opencontainers/runtime-spec v1.0.3-0.20200817204227-f9c09b4ea1df
github.com/opencontainers/runtime-tools v0.9.0
github.com/opencontainers/selinux v1.6.0
github.com/opentracing/opentracing-go v1.2.0
github.com/pkg/errors v0.9.1

5
go.sum
View File

@ -342,10 +342,11 @@ github.com/opencontainers/runc v1.0.0-rc91.0.20200708210054-ce54a9d4d79b/go.mod
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2 h1:9mv9SC7GWmRWE0J/+oD8w3GsN2KYGKtg6uwLN7hfP5E=
github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.3-0.20200817204227-f9c09b4ea1df h1:5AW5dMFSXVH4Mg3WYe4z7ui64bK8n66IoWK8i6T4QZ8=
github.com/opencontainers/runtime-spec v1.0.3-0.20200817204227-f9c09b4ea1df/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
github.com/opencontainers/runtime-tools v0.9.0 h1:FYgwVsKRI/H9hU32MJ/4MLOzXWodKK5zsQavY8NPMkU=
github.com/opencontainers/runtime-tools v0.9.0/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
github.com/opencontainers/runtime-tools v0.9.1-0.20200714183735-07406c5828aa h1:iyj+fFHVBn0xOalz9UChYzSU1K0HJ+d75b4YqShBRhI=
github.com/opencontainers/runtime-tools v0.9.1-0.20200714183735-07406c5828aa/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
github.com/opencontainers/selinux v1.3.0/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs=
github.com/opencontainers/selinux v1.5.1/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g=
github.com/opencontainers/selinux v1.5.2/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g=

View File

@ -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

View File

@ -385,7 +385,8 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
if err != nil {
return nil, errors.Wrapf(err, "Invalid Umask Value")
}
g.SetProcessUmask(uint32(decVal))
umask := uint32(decVal)
g.Config.Process.User.Umask = &umask
}
// Add addition groups if c.config.GroupAdd is not empty

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -60,7 +60,7 @@ type Process struct {
SelinuxLabel string `json:"selinuxLabel,omitempty" platform:"linux"`
}
// LinuxCapabilities specifies the whitelist of capabilities that are kept for a process.
// LinuxCapabilities specifies the list of allowed capabilities that are kept for a process.
// http://man7.org/linux/man-pages/man7/capabilities.7.html
type LinuxCapabilities struct {
// Bounding is the set of capabilities checked by the kernel.
@ -90,7 +90,7 @@ type User struct {
// GID is the group id.
GID uint32 `json:"gid" platform:"linux,solaris"`
// Umask is the umask for the init process.
Umask uint32 `json:"umask,omitempty" platform:"linux,solaris"`
Umask *uint32 `json:"umask,omitempty" platform:"linux,solaris"`
// AdditionalGids are additional group ids set for the container's process.
AdditionalGids []uint32 `json:"additionalGids,omitempty" platform:"linux,solaris"`
// Username is the user name.
@ -354,7 +354,7 @@ type LinuxRdma struct {
// LinuxResources has container runtime resource constraints
type LinuxResources struct {
// Devices configures the device whitelist.
// Devices configures the device allowlist.
Devices []LinuxDeviceCgroup `json:"devices,omitempty"`
// Memory restriction configuration
Memory *LinuxMemory `json:"memory,omitempty"`
@ -372,6 +372,8 @@ type LinuxResources struct {
// Limits are a set of key value pairs that define RDMA resource limits,
// where the key is device name and value is resource limits.
Rdma map[string]LinuxRdma `json:"rdma,omitempty"`
// Unified resources.
Unified map[string]string `json:"unified,omitempty"`
}
// LinuxDevice represents the mknod information for a Linux special device file
@ -392,7 +394,8 @@ type LinuxDevice struct {
GID *uint32 `json:"gid,omitempty"`
}
// LinuxDeviceCgroup represents a device rule for the whitelist controller
// LinuxDeviceCgroup represents a device rule for the devices specified to
// the device controller
type LinuxDeviceCgroup struct {
// Allow or deny
Allow bool `json:"allow"`
@ -628,6 +631,7 @@ const (
ArchS390X Arch = "SCMP_ARCH_S390X"
ArchPARISC Arch = "SCMP_ARCH_PARISC"
ArchPARISC64 Arch = "SCMP_ARCH_PARISC64"
ArchRISCV64 Arch = "SCMP_ARCH_RISCV64"
)
// LinuxSeccompAction taken upon Seccomp rule match
@ -635,12 +639,13 @@ type LinuxSeccompAction string
// Define actions for Seccomp rules
const (
ActKill LinuxSeccompAction = "SCMP_ACT_KILL"
ActTrap LinuxSeccompAction = "SCMP_ACT_TRAP"
ActErrno LinuxSeccompAction = "SCMP_ACT_ERRNO"
ActTrace LinuxSeccompAction = "SCMP_ACT_TRACE"
ActAllow LinuxSeccompAction = "SCMP_ACT_ALLOW"
ActLog LinuxSeccompAction = "SCMP_ACT_LOG"
ActKill LinuxSeccompAction = "SCMP_ACT_KILL"
ActKillProcess LinuxSeccompAction = "SCMP_ACT_KILL_PROCESS"
ActTrap LinuxSeccompAction = "SCMP_ACT_TRAP"
ActErrno LinuxSeccompAction = "SCMP_ACT_ERRNO"
ActTrace LinuxSeccompAction = "SCMP_ACT_TRACE"
ActAllow LinuxSeccompAction = "SCMP_ACT_ALLOW"
ActLog LinuxSeccompAction = "SCMP_ACT_LOG"
)
// LinuxSeccompOperator used to match syscall arguments in Seccomp

View File

@ -1,5 +1,23 @@
package specs
// ContainerState represents the state of a container.
type ContainerState string
const (
// StateCreating indicates that the container is being created
StateCreating ContainerState = "creating"
// StateCreated indicates that the runtime has finished the create operation
StateCreated ContainerState = "created"
// StateRunning indicates that the container process has executed the
// user-specified program but has not exited
StateRunning ContainerState = "running"
// StateStopped indicates that the container process has exited
StateStopped ContainerState = "stopped"
)
// State holds information about the runtime state of the container.
type State struct {
// Version is the version of the specification that is supported.
@ -7,7 +25,7 @@ type State struct {
// ID is the container ID
ID string `json:"id"`
// Status is the runtime status of the container.
Status string `json:"status"`
Status ContainerState `json:"status"`
// Pid is the process ID for the container process.
Pid int `json:"pid,omitempty"`
// Bundle is the path to the container's bundle directory.

View File

@ -29,9 +29,6 @@ var (
type Generator struct {
Config *rspec.Spec
HostSpecific bool
// This is used to keep a cache of the ENVs added to improve
// performance when adding a huge number of ENV variables
envMap map[string]int
}
// ExportOptions have toggles for exporting only certain parts of the specification
@ -239,12 +236,7 @@ func New(os string) (generator Generator, err error) {
}
}
envCache := map[string]int{}
if config.Process != nil {
envCache = createEnvCacheMap(config.Process.Env)
}
return Generator{Config: &config, envMap: envCache}, nil
return Generator{Config: &config}, nil
}
// NewFromSpec creates a configuration Generator from a given
@ -254,14 +246,8 @@ func New(os string) (generator Generator, err error) {
//
// generator := Generator{Config: config}
func NewFromSpec(config *rspec.Spec) Generator {
envCache := map[string]int{}
if config != nil && config.Process != nil {
envCache = createEnvCacheMap(config.Process.Env)
}
return Generator{
Config: config,
envMap: envCache,
}
}
@ -287,27 +273,11 @@ func NewFromTemplate(r io.Reader) (Generator, error) {
if err := json.NewDecoder(r).Decode(&config); err != nil {
return Generator{}, err
}
envCache := map[string]int{}
if config.Process != nil {
envCache = createEnvCacheMap(config.Process.Env)
}
return Generator{
Config: &config,
envMap: envCache,
}, nil
}
// createEnvCacheMap creates a hash map with the ENV variables given by the config
func createEnvCacheMap(env []string) map[string]int {
envMap := make(map[string]int, len(env))
for i, val := range env {
envMap[val] = i
}
return envMap
}
// SetSpec sets the configuration in the Generator g.
//
// Deprecated: Replace with:
@ -444,12 +414,6 @@ func (g *Generator) SetProcessUsername(username string) {
g.Config.Process.User.Username = username
}
// SetProcessUmask sets g.Config.Process.User.Umask.
func (g *Generator) SetProcessUmask(umask uint32) {
g.initConfigProcess()
g.Config.Process.User.Umask = umask
}
// SetProcessGID sets g.Config.Process.User.GID.
func (g *Generator) SetProcessGID(gid uint32) {
g.initConfigProcess()
@ -492,44 +456,21 @@ func (g *Generator) ClearProcessEnv() {
return
}
g.Config.Process.Env = []string{}
// Clear out the env cache map as well
g.envMap = map[string]int{}
}
// AddProcessEnv adds name=value into g.Config.Process.Env, or replaces an
// existing entry with the given name.
func (g *Generator) AddProcessEnv(name, value string) {
if name == "" {
return
}
g.initConfigProcess()
g.addEnv(fmt.Sprintf("%s=%s", name, value), name)
}
// AddMultipleProcessEnv adds multiple name=value into g.Config.Process.Env, or replaces
// existing entries with the given name.
func (g *Generator) AddMultipleProcessEnv(envs []string) {
g.initConfigProcess()
for _, val := range envs {
split := strings.SplitN(val, "=", 2)
g.addEnv(val, split[0])
}
}
// addEnv looks through adds ENV to the Process and checks envMap for
// any duplicates
// This is called by both AddMultipleProcessEnv and AddProcessEnv
func (g *Generator) addEnv(env, key string) {
if idx, ok := g.envMap[key]; ok {
// The ENV exists in the cache, so change its value in g.Config.Process.Env
g.Config.Process.Env[idx] = env
} else {
// else the env doesn't exist, so add it and add it's index to g.envMap
g.Config.Process.Env = append(g.Config.Process.Env, env)
g.envMap[key] = len(g.Config.Process.Env) - 1
env := fmt.Sprintf("%s=%s", name, value)
for idx := range g.Config.Process.Env {
if strings.HasPrefix(g.Config.Process.Env[idx], name+"=") {
g.Config.Process.Env[idx] = env
return
}
}
g.Config.Process.Env = append(g.Config.Process.Env, env)
}
// AddProcessRlimits adds rlimit into g.Config.Process.Rlimits.
@ -1502,7 +1443,7 @@ func (g *Generator) AddDevice(device rspec.LinuxDevice) {
return
}
if dev.Type == device.Type && dev.Major == device.Major && dev.Minor == device.Minor {
fmt.Fprintf(os.Stderr, "WARNING: Creating device %q with same type, major and minor as existing %q.\n", device.Path, dev.Path)
fmt.Fprintln(os.Stderr, "WARNING: The same type, major and minor should not be used for multiple devices.")
}
}

View File

@ -566,20 +566,6 @@ func DefaultProfile(rs *specs.Spec) *rspec.LinuxSeccomp {
},
}...)
/* Flags parameter of the clone syscall is the 2nd on s390 */
syscalls = append(syscalls, []rspec.LinuxSyscall{
{
Names: []string{"clone"},
Action: rspec.ActAllow,
Args: []rspec.LinuxSeccompArg{
{
Index: 1,
Value: 2080505856,
ValueTwo: 0,
Op: rspec.OpMaskedEqual,
},
},
},
}...)
}
return &rspec.LinuxSeccomp{

4
vendor/modules.txt vendored
View File

@ -418,9 +418,9 @@ github.com/opencontainers/runc/libcontainer/devices
github.com/opencontainers/runc/libcontainer/system
github.com/opencontainers/runc/libcontainer/user
github.com/opencontainers/runc/libcontainer/utils
# github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2
# github.com/opencontainers/runtime-spec v1.0.3-0.20200817204227-f9c09b4ea1df
github.com/opencontainers/runtime-spec/specs-go
# github.com/opencontainers/runtime-tools v0.9.1-0.20200714183735-07406c5828aa
# github.com/opencontainers/runtime-tools v0.9.0
github.com/opencontainers/runtime-tools/error
github.com/opencontainers/runtime-tools/filepath
github.com/opencontainers/runtime-tools/generate