Implement OomScoreAdj in kubelet

This commit is contained in:
Harry Zhang 2016-01-26 23:03:37 +08:00
parent bc8738c280
commit b4244a079f

View File

@ -62,6 +62,8 @@ const (
minimumDockerAPIVersion = "1.20"
dockerv110APIVersion = "1.21"
// ndots specifies the minimum number of dots that a domain name must contain for the resolver to consider it as FQDN (fully-qualified)
// we want to able to consider SRV lookup names like _dns._udp.kube-dns.default.svc to be considered relative.
// hence, setting ndots to be 5.
@ -503,7 +505,8 @@ func (dm *DockerManager) runContainer(
ipcMode string,
utsMode string,
pidMode string,
restartCount int) (kubecontainer.ContainerID, error) {
restartCount int,
oomScoreAdj int) (kubecontainer.ContainerID, error) {
dockerName := KubeletContainerName{
PodFullName: kubecontainer.GetPodFullName(pod),
@ -584,6 +587,11 @@ func (dm *DockerManager) runContainer(
SecurityOpt: securityOpts,
}
// If current api version is newer than docker 1.10 requested, set OomScoreAdj to HostConfig
if dm.checkDockerAPIVersion(dockerv110APIVersion) >= 0 {
hc.OomScoreAdj = oomScoreAdj
}
if dm.cpuCFSQuota {
// if cpuLimit.Amount is nil, then the appropriate default value is returned to allow full usage of cpu resource.
cpuQuota, cpuPeriod := milliCPUToQuota(cpuLimit.MilliValue())
@ -1473,7 +1481,20 @@ func (dm *DockerManager) runContainerInPod(pod *api.Pod, container *api.Containe
if usesHostNetwork(pod) {
utsMode = namespaceModeHost
}
id, err := dm.runContainer(pod, container, opts, ref, netMode, ipcMode, utsMode, pidMode, restartCount)
// Set OOM score of the container based on the priority of the container.
// Processes in lower-priority pods should be killed first if the system runs out of memory.
// The main pod infrastructure container is considered high priority, since if it is killed the
// whole pod will die.
var oomScoreAdj int
if container.Name == PodInfraContainerName {
oomScoreAdj = qos.PodInfraOOMAdj
} else {
oomScoreAdj = qos.GetContainerOOMScoreAdjust(container, int64(dm.machineInfo.MemoryCapacity))
}
id, err := dm.runContainer(pod, container, opts, ref, netMode, ipcMode, utsMode, pidMode, restartCount, oomScoreAdj)
if err != nil {
return kubecontainer.ContainerID{}, fmt.Errorf("runContainer: %v", err)
}
@ -1512,9 +1533,12 @@ func (dm *DockerManager) runContainerInPod(pod *api.Pod, container *api.Containe
return kubecontainer.ContainerID{}, fmt.Errorf("can't get init PID for container %q", id)
}
if err := dm.applyOOMScoreAdj(container, containerInfo); err != nil {
return kubecontainer.ContainerID{}, fmt.Errorf("failed to apply oom-score-adj to container %q- %v", err, containerInfo.Name)
// Check if current docker version is higher than 1.10. Otherwise, we have to apply OOMScoreAdj instead of using docker API.
err = dm.applyOOMScoreAdjIfNeeded(container, containerInfo)
if err != nil {
return kubecontainer.ContainerID{}, err
}
// The addNDotsOption call appends the ndots option to the resolv.conf file generated by docker.
// This resolv.conf file is shared by all containers of the same pod, and needs to be modified only once per pod.
// we modify it when the pause container is created since it is the first container created in the pod since it holds
@ -1529,6 +1553,38 @@ func (dm *DockerManager) runContainerInPod(pod *api.Pod, container *api.Containe
return id, err
}
func (dm *DockerManager) applyOOMScoreAdjIfNeeded(container *api.Container, containerInfo *docker.Container) error {
// Compare current API version with expected api version
result := dm.checkDockerAPIVersion(dockerv110APIVersion)
// If current api version is older than OOMScoreAdj requested, use the old way.
if result < 0 {
if err := dm.applyOOMScoreAdj(container, containerInfo); err != nil {
return fmt.Errorf("failed to apply oom-score-adj to container %q- %v", err, containerInfo.Name)
}
}
return nil
}
// Check current docker API version against expected version.
// Return:
// 1 : newer than expected version
// -1: older than expected version
// 0 : same version
func (dm *DockerManager) checkDockerAPIVersion(expectedVersion string) int {
apiVersion, err := dm.APIVersion()
if err != nil {
glog.Errorf("failed to get current docker version - %v", err)
}
result, err := apiVersion.Compare(expectedVersion)
if err != nil {
glog.Errorf("failed to compare current docker version %v with OOMScoreAdj supported Docker version %q - %v",
apiVersion, expectedVersion, err)
}
return result
}
func addNDotsOption(resolvFilePath string) error {
if len(resolvFilePath) == 0 {
glog.Errorf("ResolvConfPath is empty.")