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 21578530d7.

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 <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2022-08-11 12:09:13 +02:00
parent 1d2a669445
commit 89ab14a115
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
3 changed files with 24 additions and 1 deletions

View File

@ -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),
}

View File

@ -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

View File

@ -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
}
}