mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00

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>
164 lines
4.6 KiB
Go
164 lines
4.6 KiB
Go
//go:build !windows
|
|
// +build !windows
|
|
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
"os"
|
|
"os/signal"
|
|
"path/filepath"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/docker/docker/daemon"
|
|
"github.com/docker/docker/daemon/config"
|
|
"github.com/docker/docker/libcontainerd/supervisor"
|
|
"github.com/docker/docker/libnetwork/portallocator"
|
|
"github.com/docker/docker/pkg/homedir"
|
|
"github.com/pkg/errors"
|
|
"github.com/sirupsen/logrus"
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
func getDefaultDaemonConfigDir() (string, error) {
|
|
if !honorXDG {
|
|
return "/etc/docker", nil
|
|
}
|
|
// NOTE: CLI uses ~/.docker while the daemon uses ~/.config/docker, because
|
|
// ~/.docker was not designed to store daemon configurations.
|
|
// In future, the daemon directory may be renamed to ~/.config/moby-engine (?).
|
|
configHome, err := homedir.GetConfigHome()
|
|
if err != nil {
|
|
return "", nil
|
|
}
|
|
return filepath.Join(configHome, "docker"), nil
|
|
}
|
|
|
|
func getDefaultDaemonConfigFile() (string, error) {
|
|
dir, err := getDefaultDaemonConfigDir()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return filepath.Join(dir, "daemon.json"), nil
|
|
}
|
|
|
|
// setDefaultUmask sets the umask to 0022 to avoid problems
|
|
// caused by custom umask
|
|
func setDefaultUmask() error {
|
|
desiredUmask := 0022
|
|
unix.Umask(desiredUmask)
|
|
if umask := unix.Umask(desiredUmask); umask != desiredUmask {
|
|
return errors.Errorf("failed to set umask: expected %#o, got %#o", desiredUmask, umask)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func getDaemonConfDir(_ string) (string, error) {
|
|
return getDefaultDaemonConfigDir()
|
|
}
|
|
|
|
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),
|
|
}
|
|
|
|
return opts, nil
|
|
}
|
|
|
|
// setupConfigReloadTrap configures the SIGHUP signal to reload the configuration.
|
|
func (cli *DaemonCli) setupConfigReloadTrap() {
|
|
c := make(chan os.Signal, 1)
|
|
signal.Notify(c, unix.SIGHUP)
|
|
go func() {
|
|
for range c {
|
|
cli.reloadConfig()
|
|
}
|
|
}()
|
|
}
|
|
|
|
// getSwarmRunRoot gets the root directory for swarm to store runtime state
|
|
// For example, the control socket
|
|
func (cli *DaemonCli) getSwarmRunRoot() string {
|
|
return filepath.Join(cli.Config.ExecRoot, "swarm")
|
|
}
|
|
|
|
// allocateDaemonPort ensures that there are no containers
|
|
// that try to use any port allocated for the docker server.
|
|
func allocateDaemonPort(addr string) error {
|
|
host, port, err := net.SplitHostPort(addr)
|
|
if err != nil {
|
|
return errors.Wrap(err, "error parsing tcp address")
|
|
}
|
|
|
|
intPort, err := strconv.Atoi(port)
|
|
if err != nil {
|
|
return errors.Wrap(err, "error parsing tcp address")
|
|
}
|
|
|
|
var hostIPs []net.IP
|
|
if parsedIP := net.ParseIP(host); parsedIP != nil {
|
|
hostIPs = append(hostIPs, parsedIP)
|
|
} else if hostIPs, err = net.LookupIP(host); err != nil {
|
|
return errors.Errorf("failed to lookup %s address in host specification", host)
|
|
}
|
|
|
|
pa := portallocator.Get()
|
|
for _, hostIP := range hostIPs {
|
|
if _, err := pa.RequestPort(hostIP, "tcp", intPort); err != nil {
|
|
return errors.Errorf("failed to allocate daemon listening port %d (err: %v)", intPort, err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func newCgroupParent(config *config.Config) string {
|
|
cgroupParent := "docker"
|
|
useSystemd := daemon.UsingSystemd(config)
|
|
if useSystemd {
|
|
cgroupParent = "system.slice"
|
|
}
|
|
if config.CgroupParent != "" {
|
|
cgroupParent = config.CgroupParent
|
|
}
|
|
if useSystemd {
|
|
cgroupParent = cgroupParent + ":" + "docker" + ":"
|
|
}
|
|
return cgroupParent
|
|
}
|
|
|
|
func (cli *DaemonCli) initContainerD(ctx context.Context) (func(time.Duration) error, error) {
|
|
var waitForShutdown func(time.Duration) error
|
|
if cli.Config.ContainerdAddr == "" {
|
|
systemContainerdAddr, ok, err := systemContainerdRunning(honorXDG)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not determine whether the system containerd is running")
|
|
}
|
|
if !ok {
|
|
logrus.Debug("Containerd not running, starting daemon managed containerd")
|
|
opts, err := cli.getContainerdDaemonOpts()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "failed to generate containerd options")
|
|
}
|
|
|
|
r, err := supervisor.Start(ctx, filepath.Join(cli.Config.Root, "containerd"), filepath.Join(cli.Config.ExecRoot, "containerd"), opts...)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "failed to start containerd")
|
|
}
|
|
logrus.Debug("Started daemon managed containerd")
|
|
cli.Config.ContainerdAddr = r.Address()
|
|
|
|
// Try to wait for containerd to shutdown
|
|
waitForShutdown = r.WaitTimeout
|
|
} else {
|
|
cli.Config.ContainerdAddr = systemContainerdAddr
|
|
}
|
|
}
|
|
|
|
return waitForShutdown, nil
|
|
}
|