From 89ab14a115636c01463339b6629d29607f8940ad Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 11 Aug 2022 12:09:13 +0200 Subject: [PATCH] libcontainerd/supervisor: make supervisor adjust OOM score for containerd Containerd, like dockerd has a OOMScore configuration option to adjust its own OOM score. In dockerd, this option was added when default installations were not yet running the daemon as a systemd unit, which made it more complicated to set the score, and adding a daemon option was convenient. A binary adjusting its own score has been frowned upon, as it's more logical to make that the responsibility of the process manager _starting_ the daemon, which is what we did for dockerd in 21578530d7291f2e7bc0b90ace2f058df753a443. There have been discussions on deprecating the daemon flag for dockerd, and similar discussions have been happening for containerd. This patch changes how we set the OOM score for the containerd child process, and to have dockerd (supervisor) set the OOM score, as it's acting as process manager in this case (performing a role similar to systemd otherwise). With this patch, the score is still adjusted as usual, but not written to the containerd configuration file; dockerd --oom-score-adjust=-123 cat /proc/$(pidof containerd)/oom_score_adj -123 As a follow-up, we may consider to adjust the containerd OOM score based on the daemon's own score instead of on the `cli.OOMScoreAdjust` configuration so that we will also adjust the score in situations where dockerd's OOM score was set through other ways (systemd or manually adjusting the cgroup). A TODO was added for this. Signed-off-by: Sebastiaan van Stijn --- cmd/dockerd/daemon_unix.go | 3 +++ libcontainerd/supervisor/remote_daemon.go | 20 +++++++++++++++++++ .../supervisor/remote_daemon_options_linux.go | 2 +- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/cmd/dockerd/daemon_unix.go b/cmd/dockerd/daemon_unix.go index 9869043a7f..75583e6058 100644 --- a/cmd/dockerd/daemon_unix.go +++ b/cmd/dockerd/daemon_unix.go @@ -62,6 +62,9 @@ func getDaemonConfDir(_ string) (string, error) { func (cli *DaemonCli) getPlatformContainerdDaemonOpts() ([]supervisor.DaemonOpt, error) { opts := []supervisor.DaemonOpt{ + // TODO(thaJeztah) change this to use /proc/self/oom_score_adj instead, + // which would allow us to set the correct score even if dockerd's score + // was set through other means (such as systemd or "manually"). supervisor.WithOOMScore(cli.Config.OOMScoreAdjust), } diff --git a/libcontainerd/supervisor/remote_daemon.go b/libcontainerd/supervisor/remote_daemon.go index fd46e9ffbe..2df2794b55 100644 --- a/libcontainerd/supervisor/remote_daemon.go +++ b/libcontainerd/supervisor/remote_daemon.go @@ -13,6 +13,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/services/server/config" + "github.com/containerd/containerd/sys" "github.com/docker/docker/pkg/system" "github.com/pelletier/go-toml" "github.com/pkg/errors" @@ -40,6 +41,9 @@ type remote struct { daemonStopCh chan struct{} stateDir string + + // oomScore adjusts the OOM score for the containerd process. + oomScore int } // Daemon represents a running containerd daemon @@ -203,6 +207,10 @@ func (r *remote) startContainerd() error { r.daemonPid = cmd.Process.Pid + if err := r.adjustOOMScore(); err != nil { + r.logger.WithError(err).Warn("failed to adjust OOM score") + } + err = os.WriteFile(filepath.Join(r.stateDir, pidFile), []byte(fmt.Sprintf("%d", r.daemonPid)), 0660) if err != nil { system.KillProcess(r.daemonPid) @@ -214,6 +222,18 @@ func (r *remote) startContainerd() error { return nil } +func (r *remote) adjustOOMScore() error { + if r.oomScore == 0 || r.daemonPid <= 1 { + // no score configured, or daemonPid contains an invalid PID (we don't + // expect containerd to be running as PID 1 :)). + return nil + } + if err := sys.SetOOMScore(r.daemonPid, r.oomScore); err != nil { + return errors.Wrap(err, "failed to adjust OOM score for containerd process") + } + return nil +} + func (r *remote) monitorDaemon(ctx context.Context) { var ( transientFailureCount = 0 diff --git a/libcontainerd/supervisor/remote_daemon_options_linux.go b/libcontainerd/supervisor/remote_daemon_options_linux.go index 14511dbf93..9be34177ed 100644 --- a/libcontainerd/supervisor/remote_daemon_options_linux.go +++ b/libcontainerd/supervisor/remote_daemon_options_linux.go @@ -3,7 +3,7 @@ package supervisor // import "github.com/docker/docker/libcontainerd/supervisor" // WithOOMScore defines the oom_score_adj to set for the containerd process. func WithOOMScore(score int) DaemonOpt { return func(r *remote) error { - r.OOMScore = score + r.oomScore = score return nil } }