Fixes: #25073
Update kernel memory on running containers without initialized
is forbidden only on kernel version older than 4.6.
Signed-off-by: Qiang Huang <h.huangqiang@huawei.com>
| ... | ... |
@@ -194,17 +194,6 @@ func getBlkioThrottleDevices(devs []*blkiodev.ThrottleDevice) ([]specs.ThrottleD |
| 194 | 194 |
return throttleDevices, nil |
| 195 | 195 |
} |
| 196 | 196 |
|
| 197 |
-func checkKernelVersion(k, major, minor int) bool {
|
|
| 198 |
- if v, err := kernel.GetKernelVersion(); err != nil {
|
|
| 199 |
- logrus.Warnf("error getting kernel version: %s", err)
|
|
| 200 |
- } else {
|
|
| 201 |
- if kernel.CompareKernelVersion(*v, kernel.VersionInfo{Kernel: k, Major: major, Minor: minor}) < 0 {
|
|
| 202 |
- return false |
|
| 203 |
- } |
|
| 204 |
- } |
|
| 205 |
- return true |
|
| 206 |
-} |
|
| 207 |
- |
|
| 208 | 197 |
func checkKernel() error {
|
| 209 | 198 |
// Check for unsupported kernel versions |
| 210 | 199 |
// FIXME: it would be cleaner to not test for specific versions, but rather |
| ... | ... |
@@ -215,7 +204,7 @@ func checkKernel() error {
|
| 215 | 215 |
// For details see https://github.com/docker/docker/issues/407 |
| 216 | 216 |
// Docker 1.11 and above doesn't actually run on kernels older than 3.4, |
| 217 | 217 |
// due to containerd-shim usage of PR_SET_CHILD_SUBREAPER (introduced in 3.4). |
| 218 |
- if !checkKernelVersion(3, 10, 0) {
|
|
| 218 |
+ if !kernel.CheckKernelVersion(3, 10, 0) {
|
|
| 219 | 219 |
v, _ := kernel.GetKernelVersion() |
| 220 | 220 |
if os.Getenv("DOCKER_NOWARN_KERNEL_VERSION") == "" {
|
| 221 | 221 |
logrus.Fatalf("Your Linux kernel version %s is not supported for running docker. Please upgrade your kernel to 3.10.0 or newer.", v.String())
|
| ... | ... |
@@ -317,7 +306,7 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi |
| 317 | 317 |
if resources.KernelMemory > 0 && resources.KernelMemory < linuxMinMemory {
|
| 318 | 318 |
return warnings, fmt.Errorf("Minimum kernel memory limit allowed is 4MB")
|
| 319 | 319 |
} |
| 320 |
- if resources.KernelMemory > 0 && !checkKernelVersion(4, 0, 0) {
|
|
| 320 |
+ if resources.KernelMemory > 0 && !kernel.CheckKernelVersion(4, 0, 0) {
|
|
| 321 | 321 |
warnings = append(warnings, "You specified a kernel memory limit on a kernel older than 4.0. Kernel memory limits are experimental on older kernels, it won't work as expected and can cause your system to be unstable.") |
| 322 | 322 |
logrus.Warn("You specified a kernel memory limit on a kernel older than 4.0. Kernel memory limits are experimental on older kernels, it won't work as expected and can cause your system to be unstable.")
|
| 323 | 323 |
} |
| ... | ... |
@@ -8,6 +8,7 @@ import ( |
| 8 | 8 |
"strings" |
| 9 | 9 |
|
| 10 | 10 |
"github.com/docker/docker/pkg/integration/checker" |
| 11 |
+ "github.com/docker/docker/pkg/parsers/kernel" |
|
| 11 | 12 |
"github.com/docker/engine-api/types" |
| 12 | 13 |
"github.com/go-check/check" |
| 13 | 14 |
) |
| ... | ... |
@@ -132,26 +133,36 @@ func (s *DockerSuite) TestUpdateKernelMemory(c *check.C) {
|
| 132 | 132 |
func (s *DockerSuite) TestUpdateKernelMemoryUninitialized(c *check.C) {
|
| 133 | 133 |
testRequires(c, DaemonIsLinux, kernelMemorySupport) |
| 134 | 134 |
|
| 135 |
+ isNewKernel := kernel.CheckKernelVersion(4, 6, 0) |
|
| 135 | 136 |
name := "test-update-container" |
| 136 | 137 |
dockerCmd(c, "run", "-d", "--name", name, "busybox", "top") |
| 137 | 138 |
_, _, err := dockerCmdWithError("update", "--kernel-memory", "100M", name)
|
| 138 |
- // Update kernel memory to a running container without kernel memory initialized is not allowed. |
|
| 139 |
- c.Assert(err, check.NotNil) |
|
| 139 |
+ // Update kernel memory to a running container without kernel memory initialized |
|
| 140 |
+ // is not allowed before kernel version 4.6. |
|
| 141 |
+ if !isNewKernel {
|
|
| 142 |
+ c.Assert(err, check.NotNil) |
|
| 143 |
+ } else {
|
|
| 144 |
+ c.Assert(err, check.IsNil) |
|
| 145 |
+ } |
|
| 140 | 146 |
|
| 141 | 147 |
dockerCmd(c, "pause", name) |
| 142 |
- _, _, err = dockerCmdWithError("update", "--kernel-memory", "100M", name)
|
|
| 143 |
- c.Assert(err, check.NotNil) |
|
| 148 |
+ _, _, err = dockerCmdWithError("update", "--kernel-memory", "200M", name)
|
|
| 149 |
+ if !isNewKernel {
|
|
| 150 |
+ c.Assert(err, check.NotNil) |
|
| 151 |
+ } else {
|
|
| 152 |
+ c.Assert(err, check.IsNil) |
|
| 153 |
+ } |
|
| 144 | 154 |
dockerCmd(c, "unpause", name) |
| 145 | 155 |
|
| 146 | 156 |
dockerCmd(c, "stop", name) |
| 147 |
- dockerCmd(c, "update", "--kernel-memory", "100M", name) |
|
| 157 |
+ dockerCmd(c, "update", "--kernel-memory", "300M", name) |
|
| 148 | 158 |
dockerCmd(c, "start", name) |
| 149 | 159 |
|
| 150 |
- c.Assert(inspectField(c, name, "HostConfig.KernelMemory"), checker.Equals, "104857600") |
|
| 160 |
+ c.Assert(inspectField(c, name, "HostConfig.KernelMemory"), checker.Equals, "314572800") |
|
| 151 | 161 |
|
| 152 | 162 |
file := "/sys/fs/cgroup/memory/memory.kmem.limit_in_bytes" |
| 153 | 163 |
out, _ := dockerCmd(c, "exec", name, "cat", file) |
| 154 |
- c.Assert(strings.TrimSpace(out), checker.Equals, "104857600") |
|
| 164 |
+ c.Assert(strings.TrimSpace(out), checker.Equals, "314572800") |
|
| 155 | 165 |
} |
| 156 | 166 |
|
| 157 | 167 |
func (s *DockerSuite) TestUpdateSwapMemoryOnly(c *check.C) {
|
| ... | ... |
@@ -6,6 +6,8 @@ package kernel |
| 6 | 6 |
|
| 7 | 7 |
import ( |
| 8 | 8 |
"bytes" |
| 9 |
+ |
|
| 10 |
+ "github.com/Sirupsen/logrus" |
|
| 9 | 11 |
) |
| 10 | 12 |
|
| 11 | 13 |
// GetKernelVersion gets the current kernel version. |
| ... | ... |
@@ -28,3 +30,16 @@ func GetKernelVersion() (*VersionInfo, error) {
|
| 28 | 28 |
|
| 29 | 29 |
return ParseRelease(string(release)) |
| 30 | 30 |
} |
| 31 |
+ |
|
| 32 |
+// CheckKernelVersion checks if current kernel is newer than (or equal to) |
|
| 33 |
+// the given version. |
|
| 34 |
+func CheckKernelVersion(k, major, minor int) bool {
|
|
| 35 |
+ if v, err := GetKernelVersion(); err != nil {
|
|
| 36 |
+ logrus.Warnf("error getting kernel version: %s", err)
|
|
| 37 |
+ } else {
|
|
| 38 |
+ if CompareKernelVersion(*v, VersionInfo{Kernel: k, Major: major, Minor: minor}) < 0 {
|
|
| 39 |
+ return false |
|
| 40 |
+ } |
|
| 41 |
+ } |
|
| 42 |
+ return true |
|
| 43 |
+} |