Selaa lähdekoodia

Feature: option for disable OOM killer

Add cgroup support for disable OOM killer.

Signed-off-by: Hu Keping <hukeping@huawei.com>
HuKeping 10 vuotta sitten
vanhempi
commit
a4a924e1b6

+ 1 - 0
api/types/types.go

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

+ 8 - 7
daemon/container.go

@@ -377,13 +377,14 @@ func populateCommand(c *Container, env []string) error {
 	}
 	}
 
 
 	resources := &execdriver.Resources{
 	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{
 	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)
 		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)
 	container, buildWarnings, err := daemon.Create(config, hostConfig, name)
 	if err != nil {
 	if err != nil {
 		if daemon.Graph().IsNotExist(err, config.Image) {
 		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
 // TODO Windows: Factor out ulimit.Rlimit
 type Resources struct {
 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 {
 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.CpusetCpus = c.Resources.CpusetCpus
 		container.Cgroups.CpusetMems = c.Resources.CpusetMems
 		container.Cgroups.CpusetMems = c.Resources.CpusetMems
 		container.Cgroups.CpuQuota = c.Resources.CpuQuota
 		container.Cgroups.CpuQuota = c.Resources.CpuQuota
+		container.Cgroups.OomKillDisable = c.Resources.OomKillDisable
 	}
 	}
 
 
 	return nil
 	return nil

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

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

+ 1 - 0
daemon/info.go

@@ -68,6 +68,7 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
 		IPv4Forwarding:     !daemon.SystemConfig().IPv4ForwardingDisabled,
 		IPv4Forwarding:     !daemon.SystemConfig().IPv4ForwardingDisabled,
 		Debug:              os.Getenv("DEBUG") != "",
 		Debug:              os.Getenv("DEBUG") != "",
 		NFd:                fileutils.GetTotalUsedFds(),
 		NFd:                fileutils.GetTotalUsedFds(),
+		OomKillDisable:     daemon.SystemConfig().OomKillDisable,
 		NGoroutines:        runtime.NumGoroutine(),
 		NGoroutines:        runtime.NumGoroutine(),
 		SystemTime:         time.Now().Format(time.RFC3339Nano),
 		SystemTime:         time.Now().Format(time.RFC3339Nano),
 		ExecutionDriver:    daemon.ExecutionDriver().Name(),
 		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*]]
 [**--mac-address**[=*MAC-ADDRESS*]]
 [**--name**[=*NAME*]]
 [**--name**[=*NAME*]]
 [**--net**[=*"bridge"*]]
 [**--net**[=*"bridge"*]]
+[**--oom-kill-disable**[=*false*]]
 [**-P**|**--publish-all**[=*false*]]
 [**-P**|**--publish-all**[=*false*]]
 [**-p**|**--publish**[=*[]*]]
 [**-p**|**--publish**[=*[]*]]
 [**--pid**[=*[]*]]
 [**--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
                                '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.
                                '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*
 **-P**, **--publish-all**=*true*|*false*
    Publish all exposed ports to random ports on the host interfaces. The default is *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*]]
 [**--mac-address**[=*MAC-ADDRESS*]]
 [**--name**[=*NAME*]]
 [**--name**[=*NAME*]]
 [**--net**[=*"bridge"*]]
 [**--net**[=*"bridge"*]]
+[**--oom-kill-disable**[=*false*]]
 [**-P**|**--publish-all**[=*false*]]
 [**-P**|**--publish-all**[=*false*]]
 [**-p**|**--publish**[=*[]*]]
 [**-p**|**--publish**[=*[]*]]
 [**--pid**[=*[]*]]
 [**--pid**[=*[]*]]
@@ -285,6 +286,9 @@ and foreground Docker containers.
                                'container:<name|id>': reuses another container network stack
                                '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.
                                '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*
 **-P**, **--publish-all**=*true*|*false*
    Publish all exposed ports to random ports on the host interfaces. The default is *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,
                "CpuShares": 512,
                "CpusetCpus": "0,1",
                "CpusetCpus": "0,1",
                "CpusetMems": "0,1",
                "CpusetMems": "0,1",
+               "OomKillDisable": false,
                "PortBindings": { "22/tcp": [{ "HostPort": "11022" }] },
                "PortBindings": { "22/tcp": [{ "HostPort": "11022" }] },
                "PublishAllPorts": false,
                "PublishAllPorts": false,
                "Privileged": false,
                "Privileged": false,
@@ -194,6 +195,7 @@ Json Parameters:
 -   **Cpuset** - The same as CpusetCpus, but deprecated, please don't use.
 -   **Cpuset** - The same as CpusetCpus, but deprecated, please don't use.
 -   **CpusetCpus** - String value containing the cgroups CpusetCpus to 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.
 -   **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.
 -   **AttachStdin** - Boolean value, attaches to stdin.
 -   **AttachStdout** - Boolean value, attaches to stdout.
 -   **AttachStdout** - Boolean value, attaches to stdout.
 -   **AttachStderr** - Boolean value, attaches to stderr.
 -   **AttachStderr** - Boolean value, attaches to stderr.
@@ -354,6 +356,7 @@ Return low-level information on the container `id`
 			"LxcConf": [],
 			"LxcConf": [],
 			"Memory": 0,
 			"Memory": 0,
 			"MemorySwap": 0,
 			"MemorySwap": 0,
+			"OomKillDisable": false,
 			"NetworkMode": "bridge",
 			"NetworkMode": "bridge",
 			"PortBindings": {},
 			"PortBindings": {},
 			"Privileged": false,
 			"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)
       --mac-address=""           Container MAC address (e.g. 92:d0:c6:0a:29:33)
       --name=""                  Assign a name to the container
       --name=""                  Assign a name to the container
       --net="bridge"             Set the Network mode for 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-all=false    Publish all exposed ports to random ports
       -p, --publish=[]           Publish a container's port(s) to the host
       -p, --publish=[]           Publish a container's port(s) to the host
       --privileged=false         Give extended privileges to this container
       --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
       --memory-swap=""           Total memory (memory + swap), '-1' to disable swap
       --name=""                  Assign a name to the container
       --name=""                  Assign a name to the container
       --net="bridge"             Set the Network mode for 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-all=false    Publish all exposed ports to random ports
       -p, --publish=[]           Publish a container's port(s) to the host
       -p, --publish=[]           Publish a container's port(s) to the host
       --pid=""                   PID namespace to use
       --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-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.
     --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
     --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
 ### 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
 We set both memory and swap memory, so the processes in the container can use
 300M memory and 700M swap memory.
 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
 ### CPU share constraint
 
 
 By default, all containers get the same proportion of CPU cycles. This proportion
 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
 	CpuCfsQuota            bool
 	IPv4ForwardingDisabled bool
 	IPv4ForwardingDisabled bool
 	AppArmor               bool
 	AppArmor               bool
+	OomKillDisable         bool
 }
 }
 
 
 // New returns a new SysInfo, using the filesystem to detect which features the kernel supports.
 // 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 {
 		if !sysInfo.SwapLimit && !quiet {
 			logrus.Warn("Your kernel does not support swap memory limit.")
 			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 {
 	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
 	CpusetCpus      string // CpusetCpus 0-2, 0,1
 	CpusetMems      string // CpusetMems 0-2, 0,1
 	CpusetMems      string // CpusetMems 0-2, 0,1
 	CpuQuota        int64
 	CpuQuota        int64
+	OomKillDisable  bool // Whether to disable OOM Killer or not
 	Privileged      bool
 	Privileged      bool
 	PortBindings    nat.PortMap
 	PortBindings    nat.PortMap
 	Links           []string
 	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")
 		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")
 		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")
 		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")
 		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")
 		flEntrypoint      = cmd.String([]string{"#entrypoint", "-entrypoint"}, "", "Overwrite the default ENTRYPOINT of the image")
 		flHostname        = cmd.String([]string{"h", "-hostname"}, "", "Container host name")
 		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)")
 		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)")
 		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)")
 		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")
 		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)")
 		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")
 		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,
 		CpusetCpus:      *flCpusetCpus,
 		CpusetMems:      *flCpusetMems,
 		CpusetMems:      *flCpusetMems,
 		CpuQuota:        *flCpuQuota,
 		CpuQuota:        *flCpuQuota,
+		OomKillDisable:  *flOomKillDisable,
 		Privileged:      *flPrivileged,
 		Privileged:      *flPrivileged,
 		PortBindings:    portBindings,
 		PortBindings:    portBindings,
 		Links:           flLinks.GetAll(),
 		Links:           flLinks.GetAll(),