Configured resource-only container /docker-daemon with 70% of node memory

capacity. This is a workaround to docker memory leakage issue.
This commit is contained in:
Dawn Chen 2015-06-17 11:36:27 -07:00
parent 56083489e3
commit ca95eb75e9
5 changed files with 35 additions and 8 deletions

View File

@ -28,6 +28,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/cadvisor"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/util/errors"
"github.com/docker/libcontainer/cgroups" "github.com/docker/libcontainer/cgroups"
@ -36,6 +37,13 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
) )
const (
// The percent of the machine memory capacity. The value is used to calculate
// docker memory resource container's hardlimit to workaround docker memory
// leakage issue. Please see kubernetes/issues/9881 for more detail.
DockerMemoryLimitThresholdPercent = 70
)
// A non-user container tracked by the Kubelet. // A non-user container tracked by the Kubelet.
type systemContainer struct { type systemContainer struct {
// Absolute name of the container. // Absolute name of the container.
@ -69,13 +77,31 @@ var _ containerManager = &containerManagerImpl{}
// TODO(vmarmol): Add limits to the system containers. // TODO(vmarmol): Add limits to the system containers.
// Takes the absolute name of the specified containers. // Takes the absolute name of the specified containers.
// Empty container name disables use of the specified container. // Empty container name disables use of the specified container.
func newContainerManager(dockerDaemonContainerName, systemContainerName, kubeletContainerName string) (containerManager, error) { func newContainerManager(cadvisorInterface cadvisor.Interface, dockerDaemonContainerName, systemContainerName, kubeletContainerName string) (containerManager, error) {
systemContainers := []*systemContainer{} systemContainers := []*systemContainer{}
if dockerDaemonContainerName != "" { if dockerDaemonContainerName != "" {
cont := newSystemContainer(dockerDaemonContainerName) cont := newSystemContainer(dockerDaemonContainerName)
info, err := cadvisorInterface.MachineInfo()
var capacity = api.ResourceList{}
if err != nil {
} else {
capacity = CapacityFromMachineInfo(info)
}
memoryLimit := (int64(capacity.Memory().Value() * DockerMemoryLimitThresholdPercent / 100))
glog.Infof("Configure resource-only container %s with memory limit: %d", dockerDaemonContainerName, memoryLimit)
dockerContainer := &fs.Manager{
Cgroups: &configs.Cgroup{
Name: dockerDaemonContainerName,
Memory: memoryLimit,
MemorySwap: -1,
AllowAllDevices: true,
},
}
cont.ensureStateFunc = func(manager *fs.Manager) error { cont.ensureStateFunc = func(manager *fs.Manager) error {
return ensureDockerInContainer(-900, createManager(dockerDaemonContainerName)) return ensureDockerInContainer(cadvisorInterface, -900, dockerContainer)
} }
systemContainers = append(systemContainers, cont) systemContainers = append(systemContainers, cont)
} }
@ -162,7 +188,7 @@ func (cm *containerManagerImpl) SystemContainersLimit() api.ResourceList {
} }
// Ensures that the Docker daemon is in the desired container. // Ensures that the Docker daemon is in the desired container.
func ensureDockerInContainer(oomScoreAdj int, manager *fs.Manager) error { func ensureDockerInContainer(cadvisor cadvisor.Interface, oomScoreAdj int, manager *fs.Manager) error {
// What container is Docker in? // What container is Docker in?
out, err := exec.Command("pidof", "docker").Output() out, err := exec.Command("pidof", "docker").Output()
if err != nil { if err != nil {

View File

@ -22,6 +22,7 @@ import (
"fmt" "fmt"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/cadvisor"
) )
type unsupportedContainerManager struct { type unsupportedContainerManager struct {
@ -37,6 +38,6 @@ func (unsupportedContainerManager) SystemContainersLimit() api.ResourceList {
return api.ResourceList{} return api.ResourceList{}
} }
func newContainerManager(dockerDaemonContainer, systemContainer, kubeletContainer string) (containerManager, error) { func newContainerManager(cadvisorInterface cadvisor.Interface, dockerDaemonContainer, systemContainer, kubeletContainer string) (containerManager, error) {
return &unsupportedContainerManager{}, nil return &unsupportedContainerManager{}, nil
} }

View File

@ -309,7 +309,7 @@ func NewMainKubelet(
// Setup container manager, can fail if the devices hierarchy is not mounted // Setup container manager, can fail if the devices hierarchy is not mounted
// (it is required by Docker however). // (it is required by Docker however).
containerManager, err := newContainerManager(dockerDaemonContainer, systemContainer, resourceContainer) containerManager, err := newContainerManager(cadvisorInterface, dockerDaemonContainer, systemContainer, resourceContainer)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create the Container Manager: %v", err) return nil, fmt.Errorf("failed to create the Container Manager: %v", err)
} }

View File

@ -133,7 +133,7 @@ func newTestKubelet(t *testing.T) *TestKubelet {
t: t, t: t,
} }
kubelet.volumeManager = newVolumeManager() kubelet.volumeManager = newVolumeManager()
kubelet.containerManager, _ = newContainerManager("", "", "") kubelet.containerManager, _ = newContainerManager(mockCadvisor, "", "", "")
return &TestKubelet{kubelet, fakeDocker, mockCadvisor, fakeKubeClient, fakeMirrorClient} return &TestKubelet{kubelet, fakeDocker, mockCadvisor, fakeKubeClient, fakeMirrorClient}
} }
@ -243,7 +243,7 @@ func newTestKubeletWithFakeRuntime(t *testing.T) *TestKubeletWithFakeRuntime {
t: t, t: t,
} }
kubelet.volumeManager = newVolumeManager() kubelet.volumeManager = newVolumeManager()
kubelet.containerManager, _ = newContainerManager("", "", "") kubelet.containerManager, _ = newContainerManager(mockCadvisor, "", "", "")
return &TestKubeletWithFakeRuntime{kubelet, fakeRuntime, mockCadvisor, fakeKubeClient, fakeMirrorClient} return &TestKubeletWithFakeRuntime{kubelet, fakeRuntime, mockCadvisor, fakeKubeClient, fakeMirrorClient}
} }

View File

@ -89,7 +89,7 @@ func TestRunOnce(t *testing.T) {
os: kubecontainer.FakeOS{}, os: kubecontainer.FakeOS{},
volumeManager: newVolumeManager(), volumeManager: newVolumeManager(),
} }
kb.containerManager, _ = newContainerManager("", "", "") kb.containerManager, _ = newContainerManager(cadvisor, "", "", "")
kb.networkPlugin, _ = network.InitNetworkPlugin([]network.NetworkPlugin{}, "", network.NewFakeHost(nil)) kb.networkPlugin, _ = network.InitNetworkPlugin([]network.NetworkPlugin{}, "", network.NewFakeHost(nil))
if err := kb.setupDataDirs(); err != nil { if err := kb.setupDataDirs(); err != nil {