mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #14579 from hqhq/hq_add_softlimit
Add support for memory reservation
This commit is contained in:
commit
84b53c8d87
18 changed files with 260 additions and 140 deletions
|
@ -1151,6 +1151,7 @@ _docker_run() {
|
|||
--memory -m
|
||||
--memory-swap
|
||||
--memory-swappiness
|
||||
--memory-reservation
|
||||
--name
|
||||
--net
|
||||
--pid
|
||||
|
|
|
@ -274,6 +274,7 @@ func populateCommand(c *Container, env []string) error {
|
|||
resources := &execdriver.Resources{
|
||||
Memory: c.hostConfig.Memory,
|
||||
MemorySwap: c.hostConfig.MemorySwap,
|
||||
MemoryReservation: c.hostConfig.MemoryReservation,
|
||||
KernelMemory: c.hostConfig.KernelMemory,
|
||||
CPUShares: c.hostConfig.CPUShares,
|
||||
CpusetCpus: c.hostConfig.CpusetCpus,
|
||||
|
|
|
@ -110,6 +110,9 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *runconfig.HostConfig, a
|
|||
// By default, MemorySwap is set to twice the size of Memory.
|
||||
hostConfig.MemorySwap = hostConfig.Memory * 2
|
||||
}
|
||||
if hostConfig.MemoryReservation == 0 && hostConfig.Memory > 0 {
|
||||
hostConfig.MemoryReservation = hostConfig.Memory
|
||||
}
|
||||
}
|
||||
|
||||
// verifyPlatformContainerSettings performs platform-specific validation of the
|
||||
|
@ -154,6 +157,14 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostC
|
|||
return warnings, fmt.Errorf("Invalid value: %v, valid memory swappiness range is 0-100.", swappiness)
|
||||
}
|
||||
}
|
||||
if hostConfig.MemoryReservation > 0 && !sysInfo.MemoryReservation {
|
||||
warnings = append(warnings, "Your kernel does not support memory soft limit capabilities. Limitation discarded.")
|
||||
logrus.Warnf("Your kernel does not support memory soft limit capabilities. Limitation discarded.")
|
||||
hostConfig.MemoryReservation = 0
|
||||
}
|
||||
if hostConfig.Memory > 0 && hostConfig.MemoryReservation > 0 && hostConfig.Memory < hostConfig.MemoryReservation {
|
||||
return warnings, fmt.Errorf("Minimum memory limit should be larger than memory reservation limit, see usage.")
|
||||
}
|
||||
if hostConfig.KernelMemory > 0 && !sysInfo.KernelMemory {
|
||||
warnings = append(warnings, "Your kernel does not support kernel memory limit capabilities. Limitation discarded.")
|
||||
logrus.Warnf("Your kernel does not support kernel memory limit capabilities. Limitation discarded.")
|
||||
|
|
|
@ -143,6 +143,7 @@ type UTS struct {
|
|||
type Resources struct {
|
||||
Memory int64 `json:"memory"`
|
||||
MemorySwap int64 `json:"memory_swap"`
|
||||
MemoryReservation int64 `json:"memory_reservation"`
|
||||
KernelMemory int64 `json:"kernel_memory"`
|
||||
CPUShares int64 `json:"cpu_shares"`
|
||||
CpusetCpus string `json:"cpuset_cpus"`
|
||||
|
|
|
@ -64,7 +64,7 @@ func SetupCgroups(container *configs.Config, c *Command) error {
|
|||
if c.Resources != nil {
|
||||
container.Cgroups.CpuShares = c.Resources.CPUShares
|
||||
container.Cgroups.Memory = c.Resources.Memory
|
||||
container.Cgroups.MemoryReservation = c.Resources.Memory
|
||||
container.Cgroups.MemoryReservation = c.Resources.MemoryReservation
|
||||
container.Cgroups.MemorySwap = c.Resources.MemorySwap
|
||||
container.Cgroups.CpusetCpus = c.Resources.CpusetCpus
|
||||
container.Cgroups.CpusetMems = c.Resources.CpusetMems
|
||||
|
|
|
@ -91,11 +91,13 @@ lxc.mount.entry = {{$value.Source}} {{escapeFstabSpaces $ROOTFS}}/{{escapeFstabS
|
|||
{{if .Resources}}
|
||||
{{if .Resources.Memory}}
|
||||
lxc.cgroup.memory.limit_in_bytes = {{.Resources.Memory}}
|
||||
lxc.cgroup.memory.soft_limit_in_bytes = {{.Resources.Memory}}
|
||||
{{with $memSwap := getMemorySwap .Resources}}
|
||||
lxc.cgroup.memory.memsw.limit_in_bytes = {{$memSwap}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if gt .Resources.MemoryReservation 0}}
|
||||
lxc.cgroup.memory.soft_limit_in_bytes = {{.Resources.MemoryReservation}}
|
||||
{{end}}
|
||||
{{if gt .Resources.KernelMemory 0}}
|
||||
lxc.cgroup.memory.kmem.limit_in_bytes = {{.Resources.KernelMemory}}
|
||||
{{end}}
|
||||
|
|
|
@ -173,6 +173,7 @@ Create a container
|
|||
"LxcConf": {"lxc.utsname":"docker"},
|
||||
"Memory": 0,
|
||||
"MemorySwap": 0,
|
||||
"MemoryReservation": 0,
|
||||
"KernelMemory": 0,
|
||||
"CpuShares": 512,
|
||||
"CpuPeriod": 100000,
|
||||
|
@ -223,6 +224,7 @@ Json Parameters:
|
|||
- **Memory** - Memory limit in bytes.
|
||||
- **MemorySwap** - Total memory limit (memory + swap); set `-1` to disable swap
|
||||
You must use this with `memory` and make the swap value larger than `memory`.
|
||||
- **MemoryReservation** - Memory soft limit in bytes.
|
||||
- **KernelMemory** - Kernel memory limit in bytes.
|
||||
- **CpuShares** - An integer value containing the container's CPU Shares
|
||||
(ie. the relative weight vs other containers).
|
||||
|
@ -398,6 +400,7 @@ Return low-level information on the container `id`
|
|||
"LxcConf": [],
|
||||
"Memory": 0,
|
||||
"MemorySwap": 0,
|
||||
"MemoryReservation": 0,
|
||||
"KernelMemory": 0,
|
||||
"OomKillDisable": false,
|
||||
"NetworkMode": "bridge",
|
||||
|
|
|
@ -50,6 +50,7 @@ Creates a new container.
|
|||
--lxc-conf=[] Add custom lxc options
|
||||
-m, --memory="" Memory limit
|
||||
--mac-address="" Container MAC address (e.g. 92:d0:c6:0a:29:33)
|
||||
--memory-reservation="" Memory soft limit
|
||||
--memory-swap="" Total memory (memory + swap), '-1' to disable swap
|
||||
--memory-swappiness="" Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100.
|
||||
--name="" Assign a name to the container
|
||||
|
|
|
@ -50,6 +50,7 @@ weight=1
|
|||
--lxc-conf=[] Add custom lxc options
|
||||
-m, --memory="" Memory limit
|
||||
--mac-address="" Container MAC address (e.g. 92:d0:c6:0a:29:33)
|
||||
--memory-reservation="" Memory soft limit
|
||||
--memory-swap="" Total memory (memory + swap), '-1' to disable swap
|
||||
--memory-swappiness="" Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100.
|
||||
--name="" Assign a name to the container
|
||||
|
|
|
@ -544,6 +544,7 @@ container:
|
|||
|----------------------------|---------------------------------------------------------------------------------------------|
|
||||
| `-m`, `--memory="" ` | Memory limit (format: `<number>[<unit>]`, where unit = b, k, m or g) |
|
||||
| `--memory-swap=""` | Total memory limit (memory + swap, format: `<number>[<unit>]`, where unit = b, k, m or g) |
|
||||
| `--memory-reservation=""` | Memory soft limit (format: `<number>[<unit>]`, where unit = b, k, m or g) |
|
||||
| `--kernel-memory=""` | Kernel memory limit (format: `<number>[<unit>]`, where unit = b, k, m or g) |
|
||||
| `-c`, `--cpu-shares=0` | CPU shares (relative weight) |
|
||||
| `--cpu-period=0` | Limit the CPU CFS (Completely Fair Scheduler) period |
|
||||
|
@ -629,6 +630,43 @@ 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.
|
||||
|
||||
Memory reservation is a kind of memory soft limit that allows for greater
|
||||
sharing of memory. Under normal circumstances, containers can use as much of
|
||||
the memory as needed and are constrained only by the hard limits set with the
|
||||
`-m`/`--memory` option. When memory reservation is set, Docker detects memory
|
||||
contention or low memory and forces containers to restrict their consumption to
|
||||
a reservation limit.
|
||||
|
||||
Always set the memory reservation value below the hard limit, otherwise the hard
|
||||
limit takes precedence. A reservation of 0 is the same as setting no
|
||||
reservation. By default (without reservation set), memory reservation is the
|
||||
same as the hard memory limit.
|
||||
|
||||
Memory reservation is a soft-limit feature and does not guarantee the limit
|
||||
won't be exceeded. Instead, the feature attempts to ensure that, when memory is
|
||||
heavily contended for, memory is allocated based on the reservation hints/setup.
|
||||
|
||||
The following example limits the memory (`-m`) to 500M and sets the memory
|
||||
reservation to 200M.
|
||||
|
||||
```bash
|
||||
$ docker run -ti -m 500M --memory-reservation 200M ubuntu:14.04 /bin/bash
|
||||
```
|
||||
|
||||
Under this configuration, when the container consumes memory more than 200M and
|
||||
less than 500M, the next system memory reclaim attempts to shrink container
|
||||
memory below 200M.
|
||||
|
||||
The following example set memory reservation to 1G without a hard memory limit.
|
||||
|
||||
```bash
|
||||
$ docker run -ti --memory-reservation 1G ubuntu:14.04 /bin/bash
|
||||
```
|
||||
|
||||
The container can use as much memory as it needs. The memory reservation setting
|
||||
ensures the container doesn't consume too much memory for long time, because
|
||||
every memory reclaim shrinks the container's consumption to the reservation.
|
||||
|
||||
By default, kernel 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
|
||||
|
|
|
@ -327,6 +327,22 @@ func (s *DockerSuite) TestRunWithSwappinessInvalid(c *check.C) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRunWithMemoryReservation(c *check.C) {
|
||||
testRequires(c, memoryReservationSupport)
|
||||
dockerCmd(c, "run", "--memory-reservation", "200M", "busybox", "true")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRunWithMemoryReservationInvalid(c *check.C) {
|
||||
testRequires(c, memoryLimitSupport)
|
||||
testRequires(c, memoryReservationSupport)
|
||||
out, _, err := dockerCmdWithError("run", "-m", "500M", "--memory-reservation", "800M", "busybox", "true")
|
||||
c.Assert(err, check.NotNil)
|
||||
expected := "Minimum memory limit should be larger than memory reservation limit"
|
||||
if !strings.Contains(strings.TrimSpace(out), expected) {
|
||||
c.Fatalf("run container should fail with invalid memory reservation, output: %q", out)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestStopContainerSignal(c *check.C) {
|
||||
out, _ := dockerCmd(c, "run", "--stop-signal", "SIGUSR1", "-d", "busybox", "/bin/sh", "-c", `trap 'echo "exit trapped"; exit 0' USR1; while true; do sleep 1; done`)
|
||||
containerID := strings.TrimSpace(out)
|
||||
|
|
|
@ -45,6 +45,12 @@ var (
|
|||
},
|
||||
"Test requires an environment that supports cgroup memory limit.",
|
||||
}
|
||||
memoryReservationSupport = testRequirement{
|
||||
func() bool {
|
||||
return SysInfo.MemoryReservation
|
||||
},
|
||||
"Test requires an environment that supports cgroup memory reservation.",
|
||||
}
|
||||
swapMemorySupport = testRequirement{
|
||||
func() bool {
|
||||
return SysInfo.SwapLimit
|
||||
|
|
|
@ -40,6 +40,7 @@ docker-create - Create a new container
|
|||
[**--lxc-conf**[=*[]*]]
|
||||
[**-m**|**--memory**[=*MEMORY*]]
|
||||
[**--mac-address**[=*MAC-ADDRESS*]]
|
||||
[**--memory-reservation**[=*MEMORY-RESERVATION*]]
|
||||
[**--memory-swap**[=*MEMORY-SWAP*]]
|
||||
[**--memory-swappiness**[=*MEMORY-SWAPPINESS*]]
|
||||
[**--name**[=*NAME*]]
|
||||
|
@ -196,6 +197,15 @@ system's page size (the value would be very large, that's millions of trillions)
|
|||
**--mac-address**=""
|
||||
Container MAC address (e.g. 92:d0:c6:0a:29:33)
|
||||
|
||||
**--memory-reservation**=""
|
||||
Memory soft limit (format: <number>[<unit>], where unit = b, k, m or g)
|
||||
|
||||
After setting memory reservation, when the system detects memory contention
|
||||
or low memory, containers are forced to restrict their consumption to their
|
||||
reservation. So you should always set the value below **--memory**, otherwise the
|
||||
hard limit will take precedence. By default, memory reservation will be the same
|
||||
as memory limit.
|
||||
|
||||
**--memory-swap**=""
|
||||
Total memory limit (memory + swap)
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ docker-run - Run a command in a new container
|
|||
[**--lxc-conf**[=*[]*]]
|
||||
[**-m**|**--memory**[=*MEMORY*]]
|
||||
[**--mac-address**[=*MAC-ADDRESS*]]
|
||||
[**--memory-reservation**[=*MEMORY-RESERVATION*]]
|
||||
[**--memory-swap**[=*MEMORY-SWAP*]]
|
||||
[**--memory-swappiness**[=*MEMORY-SWAPPINESS*]]
|
||||
[**--name**[=*NAME*]]
|
||||
|
@ -290,6 +291,15 @@ RAM. If a limit of 0 is specified (not using **-m**), the container's memory is
|
|||
not limited. The actual limit may be rounded up to a multiple of the operating
|
||||
system's page size (the value would be very large, that's millions of trillions).
|
||||
|
||||
**--memory-reservation**=""
|
||||
Memory soft limit (format: <number>[<unit>], where unit = b, k, m or g)
|
||||
|
||||
After setting memory reservation, when the system detects memory contention
|
||||
or low memory, containers are forced to restrict their consumption to their
|
||||
reservation. So you should always set the value below **--memory**, otherwise the
|
||||
hard limit will take precedence. By default, memory reservation will be the same
|
||||
as memory limit.
|
||||
|
||||
**--memory-swap**=""
|
||||
Total memory limit (memory + swap)
|
||||
|
||||
|
|
|
@ -31,6 +31,9 @@ type cgroupMemInfo struct {
|
|||
// Whether swap limit is supported or not
|
||||
SwapLimit bool
|
||||
|
||||
// Whether soft limit is supported or not
|
||||
MemoryReservation bool
|
||||
|
||||
// Whether OOM killer disalbe is supported or not
|
||||
OomKillDisable bool
|
||||
|
||||
|
|
|
@ -49,6 +49,10 @@ func checkCgroupMem(quiet bool) cgroupMemInfo {
|
|||
if !quiet && !swapLimit {
|
||||
logrus.Warn("Your kernel does not support swap memory limit.")
|
||||
}
|
||||
memoryReservation := cgroupEnabled(mountPoint, "memory.soft_limit_in_bytes")
|
||||
if !quiet && !memoryReservation {
|
||||
logrus.Warn("Your kernel does not support memory reservation.")
|
||||
}
|
||||
oomKillDisable := cgroupEnabled(mountPoint, "memory.oom_control")
|
||||
if !quiet && !oomKillDisable {
|
||||
logrus.Warnf("Your kernel does not support oom control.")
|
||||
|
@ -65,6 +69,7 @@ func checkCgroupMem(quiet bool) cgroupMemInfo {
|
|||
return cgroupMemInfo{
|
||||
MemoryLimit: true,
|
||||
SwapLimit: swapLimit,
|
||||
MemoryReservation: memoryReservation,
|
||||
OomKillDisable: oomKillDisable,
|
||||
MemorySwappiness: memorySwappiness,
|
||||
KernelMemory: kernelMemory,
|
||||
|
|
|
@ -218,6 +218,7 @@ type HostConfig struct {
|
|||
ContainerIDFile string // File (path) where the containerId is written
|
||||
LxcConf *LxcConfig // Additional lxc configuration
|
||||
Memory int64 // Memory limit (in bytes)
|
||||
MemoryReservation int64 // Memory soft limit (in bytes)
|
||||
MemorySwap int64 // Total memory usage (memory + swap); set `-1` to disable swap
|
||||
KernelMemory int64 // Kernel memory limit (in bytes)
|
||||
CPUShares int64 `json:"CpuShares"` // CPU shares (relative weight vs. other containers)
|
||||
|
|
|
@ -76,6 +76,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
|
|||
flEntrypoint = cmd.String([]string{"#entrypoint", "-entrypoint"}, "", "Overwrite the default ENTRYPOINT of the image")
|
||||
flHostname = cmd.String([]string{"h", "-hostname"}, "", "Container host name")
|
||||
flMemoryString = cmd.String([]string{"m", "-memory"}, "", "Memory limit")
|
||||
flMemoryReservation = cmd.String([]string{"-memory-reservation"}, "", "Memory soft limit")
|
||||
flMemorySwap = cmd.String([]string{"-memory-swap"}, "", "Total memory (memory + swap), '-1' to disable swap")
|
||||
flKernelMemory = cmd.String([]string{"-kernel-memory"}, "", "Kernel memory limit")
|
||||
flUser = cmd.String([]string{"u", "-user"}, "", "Username or UID (format: <name|uid>[:<group|gid>])")
|
||||
|
@ -160,6 +161,14 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
|
|||
}
|
||||
}
|
||||
|
||||
var MemoryReservation int64
|
||||
if *flMemoryReservation != "" {
|
||||
MemoryReservation, err = units.RAMInBytes(*flMemoryReservation)
|
||||
if err != nil {
|
||||
return nil, nil, cmd, err
|
||||
}
|
||||
}
|
||||
|
||||
var memorySwap int64
|
||||
if *flMemorySwap != "" {
|
||||
if *flMemorySwap == "-1" {
|
||||
|
@ -333,6 +342,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
|
|||
ContainerIDFile: *flContainerIDFile,
|
||||
LxcConf: lxcConf,
|
||||
Memory: flMemory,
|
||||
MemoryReservation: MemoryReservation,
|
||||
MemorySwap: memorySwap,
|
||||
KernelMemory: KernelMemory,
|
||||
CPUShares: *flCPUShares,
|
||||
|
|
Loading…
Add table
Reference in a new issue