diff --git a/pkg/controller/daemon/controller.go b/pkg/controller/daemon/controller.go index f89fb77b2c..5302cdda78 100644 --- a/pkg/controller/daemon/controller.go +++ b/pkg/controller/daemon/controller.go @@ -674,6 +674,9 @@ func (dsc *DaemonSetsController) nodeShouldRunDaemonPod(node *api.Node, ds *exte if pod.Spec.NodeName != node.Name { continue } + if pod.Status.Phase == api.PodSucceeded || pod.Status.Phase == api.PodFailed { + continue + } // ignore pods that belong to the daemonset when taking into account wheter // a daemonset should bind to a node. if pds := dsc.getPodDaemonSet(pod); pds != nil && ds.Name == pds.Name { diff --git a/pkg/controller/daemon/controller_test.go b/pkg/controller/daemon/controller_test.go index 861f9df830..61b08c85ca 100644 --- a/pkg/controller/daemon/controller_test.go +++ b/pkg/controller/daemon/controller_test.go @@ -240,6 +240,35 @@ func TestInsufficentCapacityNodeDaemonDoesNotLaunchPod(t *testing.T) { syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0) } +func TestSufficentCapacityWithTerminatedPodsDaemonLaunchesPod(t *testing.T) { + podSpec := api.PodSpec{ + NodeName: "too-much-mem", + Containers: []api.Container{{ + Resources: api.ResourceRequirements{ + Requests: api.ResourceList{ + api.ResourceMemory: resource.MustParse("75M"), + api.ResourceCPU: resource.MustParse("75m"), + }, + }, + }}, + } + manager, podControl := newTestController() + node := newNode("too-much-mem", nil) + node.Status.Allocatable = api.ResourceList{ + api.ResourceMemory: resource.MustParse("100M"), + api.ResourceCPU: resource.MustParse("200m"), + } + manager.nodeStore.Add(node) + manager.podStore.Add(&api.Pod{ + Spec: podSpec, + Status: api.PodStatus{Phase: api.PodSucceeded}, + }) + ds := newDaemonSet("foo") + ds.Spec.Template.Spec = podSpec + manager.dsStore.Add(ds) + syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0) +} + // DaemonSets should place onto nodes with sufficient free resource func TestSufficentCapacityNodeDaemonLaunchesPod(t *testing.T) { podSpec := api.PodSpec{