Merge pull request #20169 from vishh/20117

Auto commit by PR queue bot
This commit is contained in:
k8s-merge-robot 2016-02-08 15:25:45 -08:00
commit 14653d6b5a
3 changed files with 62 additions and 26 deletions

View File

@ -1357,6 +1357,38 @@ func containerAndPodFromLabels(inspect *docker.Container) (pod *api.Pod, contain
return return
} }
func (dm *DockerManager) applyOOMScoreAdj(container *api.Container, containerInfo *docker.Container) error {
cgroupName, err := dm.procFs.GetFullContainerName(containerInfo.State.Pid)
if err != nil {
if err == os.ErrNotExist {
// Container exited. We cannot do anything about it. Ignore this error.
glog.V(2).Infof("Failed to apply OOM score adj on container %q with ID %q. Init process does not exist.", containerInfo.Name, containerInfo.ID)
return nil
}
return err
}
// 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.
// TODO: Cache this value.
var oomScoreAdj int
if containerInfo.Name == PodInfraContainerName {
oomScoreAdj = qos.PodInfraOOMAdj
} else {
oomScoreAdj = qos.GetContainerOOMScoreAdjust(container, int64(dm.machineInfo.MemoryCapacity))
}
if err = dm.oomAdjuster.ApplyOOMScoreAdjContainer(cgroupName, oomScoreAdj, 5); err != nil {
if err == os.ErrNotExist {
// Container exited. We cannot do anything about it. Ignore this error.
glog.V(2).Infof("Failed to apply OOM score adj on container %q with ID %q. Init process does not exist.", containerInfo.Name, containerInfo.ID)
return nil
}
return err
}
return nil
}
// Run a single container from a pod. Returns the docker container ID // Run a single container from a pod. Returns the docker container ID
// If do not need to pass labels, just pass nil. // If do not need to pass labels, just pass nil.
func (dm *DockerManager) runContainerInPod(pod *api.Pod, container *api.Container, netMode, ipcMode, pidMode string, restartCount int) (kubecontainer.ContainerID, error) { func (dm *DockerManager) runContainerInPod(pod *api.Pod, container *api.Container, netMode, ipcMode, pidMode string, restartCount int) (kubecontainer.ContainerID, error) {
@ -1418,24 +1450,9 @@ func (dm *DockerManager) runContainerInPod(pod *api.Pod, container *api.Containe
return kubecontainer.ContainerID{}, fmt.Errorf("can't get init PID for container %q", id) return kubecontainer.ContainerID{}, fmt.Errorf("can't get init PID for container %q", id)
} }
// Set OOM score of the container based on the priority of the container. if err := dm.applyOOMScoreAdj(container, containerInfo); err != nil {
// Processes in lower-priority pods should be killed first if the system runs out of memory. return kubecontainer.ContainerID{}, fmt.Errorf("failed to apply oom-score-adj to container %q- %v", err, containerInfo.Name)
// 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))
} }
cgroupName, err := dm.procFs.GetFullContainerName(containerInfo.State.Pid)
if err != nil {
return kubecontainer.ContainerID{}, fmt.Errorf("GetFullContainerName: %v", err)
}
if err = dm.oomAdjuster.ApplyOOMScoreAdjContainer(cgroupName, oomScoreAdj, 5); err != nil {
return kubecontainer.ContainerID{}, fmt.Errorf("ApplyOOMScoreAdjContainer: %v", err)
}
// The addNDotsOption call appends the ndots option to the resolv.conf file generated by docker. // 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. // 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 // we modify it when the pause container is created since it is the first container created in the pod since it holds

View File

@ -21,6 +21,7 @@ package oom
import ( import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os"
"path" "path"
"strconv" "strconv"
@ -48,7 +49,18 @@ func getPids(cgroupName string) ([]int, error) {
return fsManager.GetPids() return fsManager.GetPids()
} }
func syscallNotExists(err error) bool {
if err == nil {
return false
}
if e, ok := err.(*os.SyscallError); ok && os.IsNotExist(e) {
return true
}
return false
}
// Writes 'value' to /proc/<pid>/oom_score_adj. PID = 0 means self // Writes 'value' to /proc/<pid>/oom_score_adj. PID = 0 means self
// Returns os.ErrNotExist if the `pid` does not exist.
func applyOOMScoreAdj(pid int, oomScoreAdj int) error { func applyOOMScoreAdj(pid int, oomScoreAdj int) error {
if pid < 0 { if pid < 0 {
return fmt.Errorf("invalid PID %d specified for oom_score_adj", pid) return fmt.Errorf("invalid PID %d specified for oom_score_adj", pid)
@ -61,20 +73,18 @@ func applyOOMScoreAdj(pid int, oomScoreAdj int) error {
pidStr = strconv.Itoa(pid) pidStr = strconv.Itoa(pid)
} }
oomScoreAdjPath := path.Join("/proc", pidStr, "oom_score_adj")
maxTries := 2 maxTries := 2
oomScoreAdjPath := path.Join("/proc", pidStr, "oom_score_adj")
value := strconv.Itoa(oomScoreAdj)
var err error var err error
for i := 0; i < maxTries; i++ { for i := 0; i < maxTries; i++ {
_, readErr := ioutil.ReadFile(oomScoreAdjPath) if err = ioutil.WriteFile(oomScoreAdjPath, []byte(value), 0700); err != nil {
if readErr != nil { if syscallNotExists(err) {
err = fmt.Errorf("failed to read oom_score_adj: %v", readErr) return os.ErrNotExist
} else if writeErr := ioutil.WriteFile(oomScoreAdjPath, []byte(strconv.Itoa(oomScoreAdj)), 0700); writeErr != nil { }
err = fmt.Errorf("failed to set oom_score_adj to %d: %v", oomScoreAdj, writeErr) err = fmt.Errorf("failed to apply oom-score-adj to pid %d (%v)", err)
} else {
return nil
} }
} }
return err return err
} }
@ -86,6 +96,10 @@ func (oomAdjuster *OOMAdjuster) applyOOMScoreAdjContainer(cgroupName string, oom
continueAdjusting := false continueAdjusting := false
pidList, err := oomAdjuster.pidLister(cgroupName) pidList, err := oomAdjuster.pidLister(cgroupName)
if err != nil { if err != nil {
if syscallNotExists(err) {
// Nothing to do since the container doesn't exist anymore.
return os.ErrNotExist
}
continueAdjusting = true continueAdjusting = true
glog.Errorf("Error getting process list for cgroup %s: %+v", cgroupName, err) glog.Errorf("Error getting process list for cgroup %s: %+v", cgroupName, err)
} else if len(pidList) == 0 { } else if len(pidList) == 0 {
@ -97,6 +111,7 @@ func (oomAdjuster *OOMAdjuster) applyOOMScoreAdjContainer(cgroupName string, oom
if err = oomAdjuster.ApplyOOMScoreAdj(pid, oomScoreAdj); err == nil { if err = oomAdjuster.ApplyOOMScoreAdj(pid, oomScoreAdj); err == nil {
adjustedProcessSet[pid] = true adjustedProcessSet[pid] = true
} }
// Processes can come and go while we try to apply oom score adjust value. So ignore errors here.
} }
} }
} }

View File

@ -19,6 +19,7 @@ package procfs
import ( import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os"
"path" "path"
"strconv" "strconv"
"strings" "strings"
@ -48,6 +49,9 @@ func (pfs *ProcFS) GetFullContainerName(pid int) (string, error) {
filePath := path.Join("/proc", strconv.Itoa(pid), "cgroup") filePath := path.Join("/proc", strconv.Itoa(pid), "cgroup")
content, err := ioutil.ReadFile(filePath) content, err := ioutil.ReadFile(filePath)
if err != nil { if err != nil {
if e, ok := err.(*os.SyscallError); ok && os.IsNotExist(e) {
return "", os.ErrNotExist
}
return "", err return "", err
} }
return containerNameFromProcCgroup(string(content)) return containerNameFromProcCgroup(string(content))