Bläddra i källkod

Feature: option for disable OOM killer

Add cgroup support for disable OOM killer.

Signed-off-by: Hu Keping <hukeping@huawei.com>
HuKeping 10 år sedan
förälder
incheckning
a4a924e1b6

+ 1 - 0
api/types/types.go

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

+ 8 - 7
daemon/container.go

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

+ 5 - 0
daemon/create.go

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

+ 8 - 7
daemon/execdriver/driver.go

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

+ 1 - 0
daemon/execdriver/driver_linux.go

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

+ 3 - 0
daemon/execdriver/lxc/lxc_template.go

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

+ 1 - 0
daemon/info.go

@@ -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(),

+ 4 - 0
docs/man/docker-create.1.md

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

+ 4 - 0
docs/man/docker-run.1.md

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

+ 3 - 0
docs/sources/reference/api/docker_remote_api_v1.19.md

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

+ 2 - 0
docs/sources/reference/commandline/cli.md

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

+ 22 - 0
docs/sources/reference/run.md

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

+ 7 - 0
pkg/sysinfo/sysinfo.go

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

+ 1 - 0
runconfig/hostconfig.go

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

+ 3 - 1
runconfig/parse.go

@@ -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(),