Feature: option for disable OOM killer

Add cgroup support for disable OOM killer.

Signed-off-by: Hu Keping <hukeping@huawei.com>
This commit is contained in:
HuKeping 2015-02-26 19:53:55 +08:00 committed by Hu Keping
parent 15313dfdf3
commit a4a924e1b6
15 changed files with 73 additions and 15 deletions

View file

@ -156,6 +156,7 @@ type Info struct {
IPv4Forwarding bool
Debug bool
NFd int
OomKillDisable bool
NGoroutines int
SystemTime string
ExecutionDriver string

View file

@ -377,13 +377,14 @@ func populateCommand(c *Container, env []string) error {
}
resources := &execdriver.Resources{
Memory: c.hostConfig.Memory,
MemorySwap: c.hostConfig.MemorySwap,
CpuShares: c.hostConfig.CpuShares,
CpusetCpus: c.hostConfig.CpusetCpus,
CpusetMems: c.hostConfig.CpusetMems,
CpuQuota: c.hostConfig.CpuQuota,
Rlimits: rlimits,
Memory: c.hostConfig.Memory,
MemorySwap: c.hostConfig.MemorySwap,
CpuShares: c.hostConfig.CpuShares,
CpusetCpus: c.hostConfig.CpusetCpus,
CpusetMems: c.hostConfig.CpusetMems,
CpuQuota: c.hostConfig.CpuQuota,
Rlimits: rlimits,
OomKillDisable: c.hostConfig.OomKillDisable,
}
processConfig := execdriver.ProcessConfig{

View file

@ -24,6 +24,11 @@ func (daemon *Daemon) ContainerCreate(name string, config *runconfig.Config, hos
return "", warnings, fmt.Errorf("The working directory '%s' is invalid. It needs to be an absolute path.", config.WorkingDir)
}
if !daemon.SystemConfig().OomKillDisable {
hostConfig.OomKillDisable = false
return "", warnings, fmt.Errorf("Your kernel does not support oom kill disable.")
}
container, buildWarnings, err := daemon.Create(config, hostConfig, name)
if err != nil {
if daemon.Graph().IsNotExist(err, config.Image) {

View file

@ -100,13 +100,14 @@ type NetworkInterface struct {
// TODO Windows: Factor out ulimit.Rlimit
type Resources struct {
Memory int64 `json:"memory"`
MemorySwap int64 `json:"memory_swap"`
CpuShares int64 `json:"cpu_shares"`
CpusetCpus string `json:"cpuset_cpus"`
CpusetMems string `json:"cpuset_mems"`
CpuQuota int64 `json:"cpu_quota"`
Rlimits []*ulimit.Rlimit `json:"rlimits"`
Memory int64 `json:"memory"`
MemorySwap int64 `json:"memory_swap"`
CpuShares int64 `json:"cpu_shares"`
CpusetCpus string `json:"cpuset_cpus"`
CpusetMems string `json:"cpuset_mems"`
CpuQuota int64 `json:"cpu_quota"`
Rlimits []*ulimit.Rlimit `json:"rlimits"`
OomKillDisable bool `json:"oom_kill_disable"`
}
type ResourceStats struct {

View file

@ -54,6 +54,7 @@ func SetupCgroups(container *configs.Config, c *Command) error {
container.Cgroups.CpusetCpus = c.Resources.CpusetCpus
container.Cgroups.CpusetMems = c.Resources.CpusetMems
container.Cgroups.CpuQuota = c.Resources.CpuQuota
container.Cgroups.OomKillDisable = c.Resources.OomKillDisable
}
return nil

View file

@ -118,6 +118,9 @@ lxc.cgroup.cpuset.mems = {{.Resources.CpusetMems}}
{{if .Resources.CpuQuota}}
lxc.cgroup.cpu.cfs_quota_us = {{.Resources.CpuQuota}}
{{end}}
{{if .Resources.OomKillDisable}}
lxc.cgroup.memory.oom_control = {{.Resources.OomKillDisable}}
{{end}}
{{end}}
{{if .LxcConfig}}

View file

@ -68,6 +68,7 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
IPv4Forwarding: !daemon.SystemConfig().IPv4ForwardingDisabled,
Debug: os.Getenv("DEBUG") != "",
NFd: fileutils.GetTotalUsedFds(),
OomKillDisable: daemon.SystemConfig().OomKillDisable,
NGoroutines: runtime.NumGoroutine(),
SystemTime: time.Now().Format(time.RFC3339Nano),
ExecutionDriver: daemon.ExecutionDriver().Name(),

View file

@ -36,6 +36,7 @@ docker-create - Create a new container
[**--mac-address**[=*MAC-ADDRESS*]]
[**--name**[=*NAME*]]
[**--net**[=*"bridge"*]]
[**--oom-kill-disable**[=*false*]]
[**-P**|**--publish-all**[=*false*]]
[**-p**|**--publish**[=*[]*]]
[**--pid**[=*[]*]]
@ -165,6 +166,9 @@ This value should always larger than **-m**, so you should alway use this with *
'container:<name|id>': reuses another container network stack
'host': use the host network stack inside the container. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure.
**--oom-kill-disable**=*true*|*false*
Whether to disable OOM Killer for the container or not.
**-P**, **--publish-all**=*true*|*false*
Publish all exposed ports to random ports on the host interfaces. The default is *false*.

View file

@ -37,6 +37,7 @@ docker-run - Run a command in a new container
[**--mac-address**[=*MAC-ADDRESS*]]
[**--name**[=*NAME*]]
[**--net**[=*"bridge"*]]
[**--oom-kill-disable**[=*false*]]
[**-P**|**--publish-all**[=*false*]]
[**-p**|**--publish**[=*[]*]]
[**--pid**[=*[]*]]
@ -285,6 +286,9 @@ and foreground Docker containers.
'container:<name|id>': reuses another container network stack
'host': use the host network stack inside the container. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure.
**--oom-kill-disable**=*true*|*false*
Whether to disable OOM Killer for the container or not.
**-P**, **--publish-all**=*true*|*false*
Publish all exposed ports to random ports on the host interfaces. The default is *false*.

View file

@ -149,6 +149,7 @@ Create a container
"CpuShares": 512,
"CpusetCpus": "0,1",
"CpusetMems": "0,1",
"OomKillDisable": false,
"PortBindings": { "22/tcp": [{ "HostPort": "11022" }] },
"PublishAllPorts": false,
"Privileged": false,
@ -194,6 +195,7 @@ Json Parameters:
- **Cpuset** - The same as CpusetCpus, but deprecated, please don't use.
- **CpusetCpus** - String value containing the cgroups CpusetCpus to use.
- **CpusetMems** - Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.
- **OomKillDisable** - Boolean value, whether to disable OOM Killer for the container or not.
- **AttachStdin** - Boolean value, attaches to stdin.
- **AttachStdout** - Boolean value, attaches to stdout.
- **AttachStderr** - Boolean value, attaches to stderr.
@ -354,6 +356,7 @@ Return low-level information on the container `id`
"LxcConf": [],
"Memory": 0,
"MemorySwap": 0,
"OomKillDisable": false,
"NetworkMode": "bridge",
"PortBindings": {},
"Privileged": false,

View file

@ -939,6 +939,7 @@ Creates a new container.
--mac-address="" Container MAC address (e.g. 92:d0:c6:0a:29:33)
--name="" Assign a name to the container
--net="bridge" Set the Network mode for the container
--oom-kill-disable=false Whether to disable OOM Killer for the container or not
-P, --publish-all=false Publish all exposed ports to random ports
-p, --publish=[] Publish a container's port(s) to the host
--privileged=false Give extended privileges to this container
@ -1897,6 +1898,7 @@ To remove an image using its digest:
--memory-swap="" Total memory (memory + swap), '-1' to disable swap
--name="" Assign a name to the container
--net="bridge" Set the Network mode for the container
--oom-kill-disable=false Whether to disable OOM Killer for the container or not
-P, --publish-all=false Publish all exposed ports to random ports
-p, --publish=[] Publish a container's port(s) to the host
--pid="" PID namespace to use

View file

@ -476,6 +476,7 @@ container:
--cpuset-cpus="": CPUs in which to allow execution (0-3, 0,1)
--cpuset-mems="": Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.
--cpu-quota=0: Limit the CPU CFS (Completely Fair Scheduler) quota
--oom-kill-disable=true|false: Whether to disable OOM Killer for the container or not.
### Memory constraints
@ -552,6 +553,27 @@ would be 2*300M, so processes can use 300M swap memory as well.
We set both memory and swap memory, so the processes in the container can use
300M memory and 700M swap memory.
By default, Docker kills processes in a container if an out-of-memory (OOM)
error occurs. To change this behaviour, use the `--oom-kill-disable` option.
Only disable the OOM killer on containers where you have also set the
`-m/--memory` option. If the `-m` flag is not set, this can result in the host
running out of memory and require killing the host's system processes to free
memory.
Examples:
The following example limits the memory to 100M and disables the OOM killer for
this container:
$ docker run -ti -m 100M --oom-kill-disable ubuntu:14.04 /bin/bash
The following example, illustrates a dangerous way to use the flag:
$ docker run -ti --oom-kill-disable ubuntu:14.04 /bin/bash
The container has unlimited memory which can cause the host to run out memory
and require killing system processes to free memory.
### CPU share constraint
By default, all containers get the same proportion of CPU cycles. This proportion

View file

@ -18,6 +18,7 @@ type SysInfo struct {
CpuCfsQuota bool
IPv4ForwardingDisabled bool
AppArmor bool
OomKillDisable bool
}
// New returns a new SysInfo, using the filesystem to detect which features the kernel supports.
@ -36,6 +37,12 @@ func New(quiet bool) *SysInfo {
if !sysInfo.SwapLimit && !quiet {
logrus.Warn("Your kernel does not support swap memory limit.")
}
_, err = ioutil.ReadFile(path.Join(cgroupMemoryMountpoint, "memory.oom_control"))
sysInfo.OomKillDisable = err == nil
if !sysInfo.OomKillDisable && !quiet {
logrus.Warnf("Your kernel does not support oom control.")
}
}
if cgroupCpuMountpoint, err := cgroups.FindCgroupMountpoint("cpu"); err != nil {

View file

@ -168,6 +168,7 @@ type HostConfig struct {
CpusetCpus string // CpusetCpus 0-2, 0,1
CpusetMems string // CpusetMems 0-2, 0,1
CpuQuota int64
OomKillDisable bool // Whether to disable OOM Killer or not
Privileged bool
PortBindings nat.PortMap
Links []string

View file

@ -53,6 +53,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
flPublishAll = cmd.Bool([]string{"P", "-publish-all"}, false, "Publish all exposed ports to random ports")
flStdin = cmd.Bool([]string{"i", "-interactive"}, false, "Keep STDIN open even if not attached")
flTty = cmd.Bool([]string{"t", "-tty"}, false, "Allocate a pseudo-TTY")
flOomKillDisable = cmd.Bool([]string{"-oom-kill-disable"}, false, "Disable OOM Killer")
flContainerIDFile = cmd.String([]string{"#cidfile", "-cidfile"}, "", "Write the container ID to the file")
flEntrypoint = cmd.String([]string{"#entrypoint", "-entrypoint"}, "", "Overwrite the default ENTRYPOINT of the image")
flHostname = cmd.String([]string{"h", "-hostname"}, "", "Container host name")
@ -63,7 +64,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
flCpuShares = cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
flCpusetCpus = cmd.String([]string{"#-cpuset", "-cpuset-cpus"}, "", "CPUs in which to allow execution (0-3, 0,1)")
flCpusetMems = cmd.String([]string{"-cpuset-mems"}, "", "MEMs in which to allow execution (0-3, 0,1)")
flCpuQuota = cmd.Int64([]string{"-cpu-quota"}, 0, "Limit the CPU CFS (Completely Fair Scheduler) quota")
flCpuQuota = cmd.Int64([]string{"-cpu-quota"}, 0, "Limit the CPU CFS quota")
flNetMode = cmd.String([]string{"-net"}, "bridge", "Set the Network mode for the container")
flMacAddress = cmd.String([]string{"-mac-address"}, "", "Container MAC address (e.g. 92:d0:c6:0a:29:33)")
flIpcMode = cmd.String([]string{"-ipc"}, "", "IPC namespace to use")
@ -307,6 +308,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
CpusetCpus: *flCpusetCpus,
CpusetMems: *flCpusetMems,
CpuQuota: *flCpuQuota,
OomKillDisable: *flOomKillDisable,
Privileged: *flPrivileged,
PortBindings: portBindings,
Links: flLinks.GetAll(),