This adds an `--oom-score-adjust` flag to the daemon so that the value
provided can be set for the docker daemon's process. The default value
for the flag is -500. This will allow the docker daemon to have a
less chance of being killed before containers do. The default value for
processes is 0 with a min/max of -1000/1000.
-500 is a good middle ground because it is less than the default for
most processes and still not -1000 which basically means never kill this
process in an OOM condition on the host machine. The only processes on
my machine that have a score less than -500 are dbus at -900 and sshd
and xfce( my window manager ) at -1000. I don't think docker should be
set lower, by default, than dbus or sshd so that is why I chose -500.
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
(cherry picked from commit a894aec8d81de5484152a76d76b80809df9edd71)
Signed-off-by: Tibor Vass <tibor@docker.com>
... | ... |
@@ -61,6 +61,7 @@ func (cli *DaemonCli) setupConfigReloadTrap() { |
61 | 61 |
func (cli *DaemonCli) getPlatformRemoteOptions() []libcontainerd.RemoteOption { |
62 | 62 |
opts := []libcontainerd.RemoteOption{ |
63 | 63 |
libcontainerd.WithDebugLog(cli.Config.Debug), |
64 |
+ libcontainerd.WithOOMScore(cli.Config.OOMScoreAdjust), |
|
64 | 65 |
} |
65 | 66 |
if cli.Config.ContainerdAddr != "" { |
66 | 67 |
opts = append(opts, libcontainerd.WithRemoteAddr(cli.Config.ContainerdAddr)) |
... | ... |
@@ -34,6 +34,7 @@ type Config struct { |
34 | 34 |
Ulimits map[string]*units.Ulimit `json:"default-ulimits,omitempty"` |
35 | 35 |
Runtimes map[string]types.Runtime `json:"runtimes,omitempty"` |
36 | 36 |
DefaultRuntime string `json:"default-runtime,omitempty"` |
37 |
+ OOMScoreAdjust int `json:"oom-score-adjust,omitempty"` |
|
37 | 38 |
} |
38 | 39 |
|
39 | 40 |
// bridgeConfig stores all the bridge driver specific |
... | ... |
@@ -90,6 +91,7 @@ func (config *Config) InstallFlags(cmd *flag.FlagSet, usageFn func(string) strin |
90 | 90 |
config.Runtimes = make(map[string]types.Runtime) |
91 | 91 |
cmd.Var(runconfigopts.NewNamedRuntimeOpt("runtimes", &config.Runtimes, stockRuntimeName), []string{"-add-runtime"}, usageFn("Register an additional OCI compatible runtime")) |
92 | 92 |
cmd.StringVar(&config.DefaultRuntime, []string{"-default-runtime"}, stockRuntimeName, usageFn("Default OCI runtime to be used")) |
93 |
+ cmd.IntVar(&config.OOMScoreAdjust, []string{"-oom-score-adjust"}, -500, usageFn("Set the oom_score_adj for the daemon")) |
|
93 | 94 |
|
94 | 95 |
config.attachExperimentalFlags(cmd, usageFn) |
95 | 96 |
} |
... | ... |
@@ -432,7 +432,11 @@ func NewDaemon(config *Config, registryService registry.Service, containerdRemot |
432 | 432 |
} |
433 | 433 |
} |
434 | 434 |
|
435 |
- if err = setupDaemonRoot(config, realRoot, rootUID, rootGID); err != nil { |
|
435 |
+ if err := setupDaemonRoot(config, realRoot, rootUID, rootGID); err != nil { |
|
436 |
+ return nil, err |
|
437 |
+ } |
|
438 |
+ |
|
439 |
+ if err := setupDaemonProcess(config); err != nil { |
|
436 | 440 |
return nil, err |
437 | 441 |
} |
438 | 442 |
|
... | ... |
@@ -1146,3 +1146,19 @@ func rootFSToAPIType(rootfs *image.RootFS) types.RootFS { |
1146 | 1146 |
Layers: layers, |
1147 | 1147 |
} |
1148 | 1148 |
} |
1149 |
+ |
|
1150 |
+// setupDaemonProcess sets various settings for the daemon's process |
|
1151 |
+func setupDaemonProcess(config *Config) error { |
|
1152 |
+ // setup the daemons oom_score_adj |
|
1153 |
+ return setupOOMScoreAdj(config.OOMScoreAdjust) |
|
1154 |
+} |
|
1155 |
+ |
|
1156 |
+func setupOOMScoreAdj(score int) error { |
|
1157 |
+ f, err := os.OpenFile("/proc/self/oom_score_adj", os.O_WRONLY, 0) |
|
1158 |
+ if err != nil { |
|
1159 |
+ return err |
|
1160 |
+ } |
|
1161 |
+ _, err = f.WriteString(strconv.Itoa(score)) |
|
1162 |
+ f.Close() |
|
1163 |
+ return err |
|
1164 |
+} |
... | ... |
@@ -54,9 +54,10 @@ weight = -1 |
54 | 54 |
--label=[] Set key=value labels to the daemon |
55 | 55 |
--log-driver="json-file" Default driver for container logs |
56 | 56 |
--log-opt=[] Log driver specific options |
57 |
- --mtu=0 Set the containers network MTU |
|
58 | 57 |
--max-concurrent-downloads=3 Set the max concurrent downloads for each pull |
59 | 58 |
--max-concurrent-uploads=5 Set the max concurrent uploads for each push |
59 |
+ --mtu=0 Set the containers network MTU |
|
60 |
+ --oom-score-adjust=-500 Set the oom_score_adj for the daemon |
|
60 | 61 |
--disable-legacy-registry Do not contact legacy registries |
61 | 62 |
-p, --pidfile="/var/run/docker.pid" Path to use for daemon PID file |
62 | 63 |
--raw-logs Full timestamps without ANSI coloring |
... | ... |
@@ -1057,6 +1058,7 @@ This is a full example of the allowed configuration options on Linux: |
1057 | 1057 |
"insecure-registries": [], |
1058 | 1058 |
"disable-legacy-registry": false, |
1059 | 1059 |
"default-runtime": "runc", |
1060 |
+ "oom-score-adjust": -500, |
|
1060 | 1061 |
"runtimes": { |
1061 | 1062 |
"runc": { |
1062 | 1063 |
"path": "runc" |
... | ... |
@@ -54,6 +54,7 @@ type remote struct { |
54 | 54 |
runtimeArgs []string |
55 | 55 |
daemonWaitCh chan struct{} |
56 | 56 |
liveRestore bool |
57 |
+ oomScore int |
|
57 | 58 |
} |
58 | 59 |
|
59 | 60 |
// New creates a fresh instance of libcontainerd remote. |
... | ... |
@@ -402,7 +403,10 @@ func (r *remote) runContainerdDaemon() error { |
402 | 402 |
return err |
403 | 403 |
} |
404 | 404 |
logrus.Infof("New containerd process, pid: %d", cmd.Process.Pid) |
405 |
- |
|
405 |
+ if err := setOOMScore(cmd.Process.Pid, r.oomScore); err != nil { |
|
406 |
+ utils.KillProcess(cmd.Process.Pid) |
|
407 |
+ return err |
|
408 |
+ } |
|
406 | 409 |
if _, err := f.WriteString(fmt.Sprintf("%d", cmd.Process.Pid)); err != nil { |
407 | 410 |
utils.KillProcess(cmd.Process.Pid) |
408 | 411 |
return err |
... | ... |
@@ -417,6 +421,16 @@ func (r *remote) runContainerdDaemon() error { |
417 | 417 |
return nil |
418 | 418 |
} |
419 | 419 |
|
420 |
+func setOOMScore(pid, score int) error { |
|
421 |
+ f, err := os.OpenFile(fmt.Sprintf("/proc/%d/oom_score_adj", pid), os.O_WRONLY, 0) |
|
422 |
+ if err != nil { |
|
423 |
+ return err |
|
424 |
+ } |
|
425 |
+ _, err = f.WriteString(strconv.Itoa(score)) |
|
426 |
+ f.Close() |
|
427 |
+ return err |
|
428 |
+} |
|
429 |
+ |
|
420 | 430 |
// WithRemoteAddr sets the external containerd socket to connect to. |
421 | 431 |
func WithRemoteAddr(addr string) RemoteOption { |
422 | 432 |
return rpcAddr(addr) |
... | ... |
@@ -510,3 +524,18 @@ func (l liveRestore) Apply(r Remote) error { |
510 | 510 |
} |
511 | 511 |
return fmt.Errorf("WithLiveRestore option not supported for this remote") |
512 | 512 |
} |
513 |
+ |
|
514 |
+// WithOOMScore defines the oom_score_adj to set for the containerd process. |
|
515 |
+func WithOOMScore(score int) RemoteOption { |
|
516 |
+ return oomScore(score) |
|
517 |
+} |
|
518 |
+ |
|
519 |
+type oomScore int |
|
520 |
+ |
|
521 |
+func (o oomScore) Apply(r Remote) error { |
|
522 |
+ if remote, ok := r.(*remote); ok { |
|
523 |
+ remote.oomScore = int(o) |
|
524 |
+ return nil |
|
525 |
+ } |
|
526 |
+ return fmt.Errorf("WithOOMScore option not supported for this remote") |
|
527 |
+} |