Add oom score adj in new CRI implementation.

This commit is contained in:
Random-Liu 2016-09-24 19:07:43 -07:00
parent 5b3860ce0b
commit 2141e230a6
7 changed files with 33 additions and 6 deletions

View File

@ -25,6 +25,7 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
"k8s.io/kubernetes/pkg/kubelet/qos"
) )
const ( const (
@ -32,7 +33,6 @@ const (
// Various default sandbox resources requests/limits. // Various default sandbox resources requests/limits.
defaultSandboxCPUshares int64 = 2 defaultSandboxCPUshares int64 = 2
defaultSandboxOOMScore int = -999
// Termination grace period // Termination grace period
defaultSandboxGracePeriod int = 10 defaultSandboxGracePeriod int = 10
@ -263,5 +263,6 @@ func setSandboxResources(hc *dockercontainer.HostConfig) {
CPUShares: defaultSandboxCPUshares, CPUShares: defaultSandboxCPUshares,
// Use docker's default cpu quota/period. // Use docker's default cpu quota/period.
} }
hc.OomScoreAdj = defaultSandboxOOMScore // TODO: Get rid of the dependency on kubelet internal package.
hc.OomScoreAdj = qos.PodInfraOOMAdj
} }

View File

@ -555,6 +555,7 @@ func NewMainKubelet(kubeCfg *componentconfig.KubeletConfiguration, kubeDeps *Kub
kubecontainer.FilterEventRecorder(kubeDeps.Recorder), kubecontainer.FilterEventRecorder(kubeDeps.Recorder),
klet.livenessManager, klet.livenessManager,
containerRefManager, containerRefManager,
machineInfo,
klet.podManager, klet.podManager,
kubeDeps.OSInterface, kubeDeps.OSInterface,
klet.networkPlugin, klet.networkPlugin,
@ -649,6 +650,7 @@ func NewMainKubelet(kubeCfg *componentconfig.KubeletConfiguration, kubeDeps *Kub
kubecontainer.FilterEventRecorder(kubeDeps.Recorder), kubecontainer.FilterEventRecorder(kubeDeps.Recorder),
klet.livenessManager, klet.livenessManager,
containerRefManager, containerRefManager,
machineInfo,
klet.podManager, klet.podManager,
kubeDeps.OSInterface, kubeDeps.OSInterface,
klet.networkPlugin, klet.networkPlugin,

View File

@ -21,6 +21,7 @@ import (
"net/http" "net/http"
"time" "time"
cadvisorapi "github.com/google/cadvisor/info/v1"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/record" "k8s.io/kubernetes/pkg/client/record"
"k8s.io/kubernetes/pkg/credentialprovider" "k8s.io/kubernetes/pkg/credentialprovider"
@ -90,13 +91,14 @@ func (f *fakePodGetter) GetPodByUID(uid types.UID) (*api.Pod, bool) {
return pod, found return pod, found
} }
func NewFakeKubeRuntimeManager(runtimeService internalApi.RuntimeService, imageService internalApi.ImageManagerService, networkPlugin network.NetworkPlugin, osInterface kubecontainer.OSInterface) (*kubeGenericRuntimeManager, error) { func NewFakeKubeRuntimeManager(runtimeService internalApi.RuntimeService, imageService internalApi.ImageManagerService, machineInfo *cadvisorapi.MachineInfo, networkPlugin network.NetworkPlugin, osInterface kubecontainer.OSInterface) (*kubeGenericRuntimeManager, error) {
recorder := &record.FakeRecorder{} recorder := &record.FakeRecorder{}
kubeRuntimeManager := &kubeGenericRuntimeManager{ kubeRuntimeManager := &kubeGenericRuntimeManager{
recorder: recorder, recorder: recorder,
cpuCFSQuota: false, cpuCFSQuota: false,
livenessManager: proberesults.NewManager(), livenessManager: proberesults.NewManager(),
containerRefManager: kubecontainer.NewRefManager(), containerRefManager: kubecontainer.NewRefManager(),
machineInfo: machineInfo,
osInterface: osInterface, osInterface: osInterface,
networkPlugin: networkPlugin, networkPlugin: networkPlugin,
runtimeHelper: &fakeRuntimeHelper{}, runtimeHelper: &fakeRuntimeHelper{},

View File

@ -34,6 +34,7 @@ import (
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
"k8s.io/kubernetes/pkg/kubelet/dockershim" "k8s.io/kubernetes/pkg/kubelet/dockershim"
"k8s.io/kubernetes/pkg/kubelet/events" "k8s.io/kubernetes/pkg/kubelet/events"
"k8s.io/kubernetes/pkg/kubelet/qos"
"k8s.io/kubernetes/pkg/kubelet/util/format" "k8s.io/kubernetes/pkg/kubelet/util/format"
"k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/types"
utilruntime "k8s.io/kubernetes/pkg/util/runtime" utilruntime "k8s.io/kubernetes/pkg/util/runtime"
@ -144,7 +145,7 @@ func (m *kubeGenericRuntimeManager) generateContainerConfig(container *api.Conta
Stdin: &container.Stdin, Stdin: &container.Stdin,
StdinOnce: &container.StdinOnce, StdinOnce: &container.StdinOnce,
Tty: &container.TTY, Tty: &container.TTY,
Linux: m.generateLinuxContainerConfig(container), Linux: m.generateLinuxContainerConfig(container, pod),
} }
// set privileged and readonlyRootfs // set privileged and readonlyRootfs
@ -173,7 +174,7 @@ func (m *kubeGenericRuntimeManager) generateContainerConfig(container *api.Conta
} }
// generateLinuxContainerConfig generates linux container config for kubelet runtime api. // generateLinuxContainerConfig generates linux container config for kubelet runtime api.
func (m *kubeGenericRuntimeManager) generateLinuxContainerConfig(container *api.Container) *runtimeApi.LinuxContainerConfig { func (m *kubeGenericRuntimeManager) generateLinuxContainerConfig(container *api.Container, pod *api.Pod) *runtimeApi.LinuxContainerConfig {
linuxConfig := &runtimeApi.LinuxContainerConfig{ linuxConfig := &runtimeApi.LinuxContainerConfig{
Resources: &runtimeApi.LinuxContainerResources{}, Resources: &runtimeApi.LinuxContainerResources{},
} }
@ -183,6 +184,8 @@ func (m *kubeGenericRuntimeManager) generateLinuxContainerConfig(container *api.
cpuRequest := container.Resources.Requests.Cpu() cpuRequest := container.Resources.Requests.Cpu()
cpuLimit := container.Resources.Limits.Cpu() cpuLimit := container.Resources.Limits.Cpu()
memoryLimit := container.Resources.Limits.Memory().Value() memoryLimit := container.Resources.Limits.Memory().Value()
oomScoreAdj := int64(qos.GetContainerOOMScoreAdjust(pod, container,
int64(m.machineInfo.MemoryCapacity)))
// If request is not specified, but limit is, we want request to default to limit. // If request is not specified, but limit is, we want request to default to limit.
// API server does this for new containers, but we repeat this logic in Kubelet // API server does this for new containers, but we repeat this logic in Kubelet
// for containers running on existing Kubernetes clusters. // for containers running on existing Kubernetes clusters.
@ -197,6 +200,10 @@ func (m *kubeGenericRuntimeManager) generateLinuxContainerConfig(container *api.
if memoryLimit != 0 { if memoryLimit != 0 {
linuxConfig.Resources.MemoryLimitInBytes = &memoryLimit linuxConfig.Resources.MemoryLimitInBytes = &memoryLimit
} }
// Set OOM score of the container based on qos policy. Processes in lower-priority pods should
// be killed first if the system runs out of memory.
linuxConfig.Resources.OomScoreAdj = &oomScoreAdj
if m.cpuCFSQuota { if m.cpuCFSQuota {
// if cpuLimit.Amount is nil, then the appropriate default value is returned // if cpuLimit.Amount is nil, then the appropriate default value is returned
// to allow full usage of cpu resource. // to allow full usage of cpu resource.

View File

@ -24,6 +24,7 @@ import (
"github.com/coreos/go-semver/semver" "github.com/coreos/go-semver/semver"
"github.com/golang/glog" "github.com/golang/glog"
cadvisorapi "github.com/google/cadvisor/info/v1"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/record" "k8s.io/kubernetes/pkg/client/record"
@ -68,6 +69,9 @@ type kubeGenericRuntimeManager struct {
osInterface kubecontainer.OSInterface osInterface kubecontainer.OSInterface
containerRefManager *kubecontainer.RefManager containerRefManager *kubecontainer.RefManager
// machineInfo contains the machine information.
machineInfo *cadvisorapi.MachineInfo
// Container GC manager // Container GC manager
containerGC *containerGC containerGC *containerGC
@ -102,6 +106,7 @@ func NewKubeGenericRuntimeManager(
recorder record.EventRecorder, recorder record.EventRecorder,
livenessManager proberesults.Manager, livenessManager proberesults.Manager,
containerRefManager *kubecontainer.RefManager, containerRefManager *kubecontainer.RefManager,
machineInfo *cadvisorapi.MachineInfo,
podGetter podGetter, podGetter podGetter,
osInterface kubecontainer.OSInterface, osInterface kubecontainer.OSInterface,
networkPlugin network.NetworkPlugin, networkPlugin network.NetworkPlugin,
@ -120,6 +125,7 @@ func NewKubeGenericRuntimeManager(
cpuCFSQuota: cpuCFSQuota, cpuCFSQuota: cpuCFSQuota,
livenessManager: livenessManager, livenessManager: livenessManager,
containerRefManager: containerRefManager, containerRefManager: containerRefManager,
machineInfo: machineInfo,
osInterface: osInterface, osInterface: osInterface,
networkPlugin: networkPlugin, networkPlugin: networkPlugin,
runtimeHelper: runtimeHelper, runtimeHelper: runtimeHelper,

View File

@ -22,6 +22,7 @@ import (
"testing" "testing"
"time" "time"
cadvisorapi "github.com/google/cadvisor/info/v1"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/componentconfig" "k8s.io/kubernetes/pkg/apis/componentconfig"
@ -42,6 +43,10 @@ var (
func createTestRuntimeManager() (*apitest.FakeRuntimeService, *apitest.FakeImageService, *kubeGenericRuntimeManager, error) { func createTestRuntimeManager() (*apitest.FakeRuntimeService, *apitest.FakeImageService, *kubeGenericRuntimeManager, error) {
fakeRuntimeService := apitest.NewFakeRuntimeService() fakeRuntimeService := apitest.NewFakeRuntimeService()
fakeImageService := apitest.NewFakeImageService() fakeImageService := apitest.NewFakeImageService()
// Only an empty machineInfo is needed here, because in unit test all containers are besteffort,
// data in machineInfo is not used. If burstable containers are used in unit test in the future,
// we may want to set memory capacity.
machineInfo := &cadvisorapi.MachineInfo{}
networkPlugin, _ := network.InitNetworkPlugin( networkPlugin, _ := network.InitNetworkPlugin(
[]network.NetworkPlugin{}, []network.NetworkPlugin{},
"", "",
@ -51,7 +56,7 @@ func createTestRuntimeManager() (*apitest.FakeRuntimeService, *apitest.FakeImage
network.UseDefaultMTU, network.UseDefaultMTU,
) )
osInterface := &containertest.FakeOS{} osInterface := &containertest.FakeOS{}
manager, err := NewFakeKubeRuntimeManager(fakeRuntimeService, fakeImageService, networkPlugin, osInterface) manager, err := NewFakeKubeRuntimeManager(fakeRuntimeService, fakeImageService, machineInfo, networkPlugin, osInterface)
return fakeRuntimeService, fakeImageService, manager, err return fakeRuntimeService, fakeImageService, manager, err
} }

View File

@ -21,6 +21,10 @@ import (
) )
const ( const (
// PodInfraOOMAdj is very docker specific. For arbitrary runtime, it may not make
// sense to set sandbox level oom score, e.g. a sandbox could only be a namespace
// without a process.
// TODO: Handle infra container oom score adj in a runtime agnostic way.
PodInfraOOMAdj int = -998 PodInfraOOMAdj int = -998
KubeletOOMScoreAdj int = -999 KubeletOOMScoreAdj int = -999
DockerOOMScoreAdj int = -999 DockerOOMScoreAdj int = -999