Adding oom_score_adj as a container config param.
Signed-off-by: Vishnu Kannan <vishnuk@google.com>
This commit is contained in:
parent
b1e7041957
commit
cc232c4707
|
@ -127,6 +127,12 @@ type Config struct {
|
||||||
// If Rlimits are not set, the container will inherit rlimits from the parent process
|
// If Rlimits are not set, the container will inherit rlimits from the parent process
|
||||||
Rlimits []Rlimit `json:"rlimits"`
|
Rlimits []Rlimit `json:"rlimits"`
|
||||||
|
|
||||||
|
// OomScoreAdj specifies the adjustment to be made by the kernel when calculating oom scores
|
||||||
|
// for a process. Valid values are between the range [-1000, '1000'], where processes with
|
||||||
|
// higher scores are preferred for being killed.
|
||||||
|
// More information about kernel oom score calculation here: https://lwn.net/Articles/317814/
|
||||||
|
OomScoreAdj int `json:"oom_score_adj"`
|
||||||
|
|
||||||
// AdditionalGroups specifies the gids that should be added to supplementary groups
|
// AdditionalGroups specifies the gids that should be added to supplementary groups
|
||||||
// in addition to those that the user belongs to.
|
// in addition to those that the user belongs to.
|
||||||
AdditionalGroups []string `json:"additional_groups"`
|
AdditionalGroups []string `json:"additional_groups"`
|
||||||
|
|
|
@ -5,7 +5,9 @@ package libcontainer
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
@ -238,6 +240,11 @@ func setupRlimits(config *configs.Config) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setOomScoreAdj(oomScoreAdj int) error {
|
||||||
|
path := "/proc/self/oom_score_adj"
|
||||||
|
return ioutil.WriteFile(path, []byte(strconv.Itoa(oomScoreAdj)), 0700)
|
||||||
|
}
|
||||||
|
|
||||||
// killCgroupProcesses freezes then iterates over all the processes inside the
|
// killCgroupProcesses freezes then iterates over all the processes inside the
|
||||||
// manager's cgroups sending a SIGKILL to each process then waiting for them to
|
// manager's cgroups sending a SIGKILL to each process then waiting for them to
|
||||||
// exit.
|
// exit.
|
||||||
|
|
|
@ -878,3 +878,45 @@ func TestMountCgroupRW(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestOomScoreAdj(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
root, err := newTestRoot()
|
||||||
|
ok(t, err)
|
||||||
|
defer os.RemoveAll(root)
|
||||||
|
|
||||||
|
rootfs, err := newRootfs()
|
||||||
|
ok(t, err)
|
||||||
|
defer remove(rootfs)
|
||||||
|
|
||||||
|
config := newTemplateConfig(rootfs)
|
||||||
|
config.OomScoreAdj = 200
|
||||||
|
|
||||||
|
factory, err := libcontainer.New(root, libcontainer.Cgroupfs)
|
||||||
|
ok(t, err)
|
||||||
|
|
||||||
|
container, err := factory.Create("test", config)
|
||||||
|
ok(t, err)
|
||||||
|
defer container.Destroy()
|
||||||
|
|
||||||
|
var stdout bytes.Buffer
|
||||||
|
pconfig := libcontainer.Process{
|
||||||
|
Args: []string{"sh", "-c", "cat /proc/self/oom_score_adj"},
|
||||||
|
Env: standardEnvironment,
|
||||||
|
Stdin: nil,
|
||||||
|
Stdout: &stdout,
|
||||||
|
}
|
||||||
|
err = container.Start(&pconfig)
|
||||||
|
ok(t, err)
|
||||||
|
|
||||||
|
// Wait for process
|
||||||
|
waitProcess(&pconfig, t)
|
||||||
|
outputOomScoreAdj := strings.TrimSpace(string(stdout.Bytes()))
|
||||||
|
|
||||||
|
// Check that the oom_score_adj matches the value that was set as part of config.
|
||||||
|
if outputOomScoreAdj != strconv.Itoa(config.OomScoreAdj) {
|
||||||
|
t.Fatalf("Expected oom_score_adj %d; got %q", config.OomScoreAdj, outputOomScoreAdj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -332,3 +333,49 @@ func TestExecinPassExtraFiles(t *testing.T) {
|
||||||
t.Fatalf("expected second pipe to receive '2', got '%s'", out2)
|
t.Fatalf("expected second pipe to receive '2', got '%s'", out2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestExecInOomScoreAdj(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rootfs, err := newRootfs()
|
||||||
|
ok(t, err)
|
||||||
|
defer remove(rootfs)
|
||||||
|
config := newTemplateConfig(rootfs)
|
||||||
|
config.OomScoreAdj = 200
|
||||||
|
container, err := newContainer(config)
|
||||||
|
ok(t, err)
|
||||||
|
defer container.Destroy()
|
||||||
|
|
||||||
|
stdinR, stdinW, err := os.Pipe()
|
||||||
|
ok(t, err)
|
||||||
|
process := &libcontainer.Process{
|
||||||
|
Args: []string{"cat"},
|
||||||
|
Env: standardEnvironment,
|
||||||
|
Stdin: stdinR,
|
||||||
|
}
|
||||||
|
err = container.Start(process)
|
||||||
|
stdinR.Close()
|
||||||
|
defer stdinW.Close()
|
||||||
|
ok(t, err)
|
||||||
|
|
||||||
|
buffers := newStdBuffers()
|
||||||
|
ps := &libcontainer.Process{
|
||||||
|
Args: []string{"/bin/sh", "-c", "cat /proc/self/oom_score_adj"},
|
||||||
|
Env: standardEnvironment,
|
||||||
|
Stdin: buffers.Stdin,
|
||||||
|
Stdout: buffers.Stdout,
|
||||||
|
Stderr: buffers.Stderr,
|
||||||
|
}
|
||||||
|
err = container.Start(ps)
|
||||||
|
ok(t, err)
|
||||||
|
waitProcess(ps, t)
|
||||||
|
|
||||||
|
stdinW.Close()
|
||||||
|
waitProcess(process, t)
|
||||||
|
|
||||||
|
out := buffers.Stdout.String()
|
||||||
|
if oomScoreAdj := strings.TrimSpace(out); oomScoreAdj != strconv.Itoa(config.OomScoreAdj) {
|
||||||
|
t.Fatalf("expected oomScoreAdj to be %d, got %s", config.OomScoreAdj, oomScoreAdj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -21,6 +21,9 @@ func (l *linuxSetnsInit) Init() error {
|
||||||
if err := setupRlimits(l.config.Config); err != nil {
|
if err := setupRlimits(l.config.Config); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := setOomScoreAdj(l.config.Config.OomScoreAdj); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if l.config.Config.Seccomp != nil {
|
if l.config.Config.Seccomp != nil {
|
||||||
if err := seccomp.InitSeccomp(l.config.Config.Seccomp); err != nil {
|
if err := seccomp.InitSeccomp(l.config.Config.Seccomp); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -47,6 +47,10 @@ func (l *linuxStandardInit) Init() error {
|
||||||
if err := setupRlimits(l.config.Config); err != nil {
|
if err := setupRlimits(l.config.Config); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := setOomScoreAdj(l.config.Config.OomScoreAdj); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
label.Init()
|
label.Init()
|
||||||
// InitializeMountNamespace() can be executed only for a new mount namespace
|
// InitializeMountNamespace() can be executed only for a new mount namespace
|
||||||
if l.config.Config.Namespaces.Contains(configs.NEWNS) {
|
if l.config.Config.Namespaces.Contains(configs.NEWNS) {
|
||||||
|
|
Loading…
Reference in New Issue