From f237db81f085eafe330924c69d48e9fb951e055c Mon Sep 17 00:00:00 2001 From: Mike Danese Date: Wed, 28 Oct 2015 18:01:34 -0700 Subject: [PATCH] daemonset don't place pods on notready nodes --- pkg/api/resource_helpers.go | 10 ++++++++++ pkg/controller/daemon/controller.go | 7 ++++++- pkg/controller/daemon/controller_test.go | 20 ++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/pkg/api/resource_helpers.go b/pkg/api/resource_helpers.go index 72f3c7f04db..257cb36429b 100644 --- a/pkg/api/resource_helpers.go +++ b/pkg/api/resource_helpers.go @@ -87,3 +87,13 @@ func GetPodReadyCondition(status PodStatus) *PodCondition { } return nil } + +// IsNodeReady returns true if a node is ready; false otherwise. +func IsNodeReady(node *Node) bool { + for _, c := range node.Status.Conditions { + if c.Type == NodeReady { + return c.Status == ConditionTrue + } + } + return false +} diff --git a/pkg/controller/daemon/controller.go b/pkg/controller/daemon/controller.go index fc0d599e54e..132cabeda22 100644 --- a/pkg/controller/daemon/controller.go +++ b/pkg/controller/daemon/controller.go @@ -348,13 +348,18 @@ func (dsc *DaemonSetsController) manage(ds *extensions.DaemonSet) { glog.Errorf("Couldn't get list of nodes when syncing daemon set %+v: %v", ds, err) } var nodesNeedingDaemonPods, podsToDelete []string - for i := range nodeList.Items { + for i, node := range nodeList.Items { // Check if the node satisfies the daemon set's node selector. nodeSelector := labels.Set(ds.Spec.Template.Spec.NodeSelector).AsSelector() shouldRun := nodeSelector.Matches(labels.Set(nodeList.Items[i].Labels)) // If the daemon set specifies a node name, check that it matches with nodeName. nodeName := nodeList.Items[i].Name shouldRun = shouldRun && (ds.Spec.Template.Spec.NodeName == "" || ds.Spec.Template.Spec.NodeName == nodeName) + + // If the node is not ready, don't run on it. + // TODO(mikedanese): remove this once daemonpods forgive nodes + shouldRun = shouldRun && api.IsNodeReady(&node) + daemonPods, isRunning := nodeToDaemonPods[nodeName] if shouldRun && !isRunning { // If daemon pod is supposed to be running on node, but isn't, create daemon pod. diff --git a/pkg/controller/daemon/controller_test.go b/pkg/controller/daemon/controller_test.go index cfc0ec8d255..5b4f68e8c0c 100644 --- a/pkg/controller/daemon/controller_test.go +++ b/pkg/controller/daemon/controller_test.go @@ -84,6 +84,11 @@ func newNode(name string, label map[string]string) *api.Node { Labels: label, Namespace: api.NamespaceDefault, }, + Status: api.NodeStatus{ + Conditions: []api.NodeCondition{ + {Type: api.NodeReady, Status: api.ConditionTrue}, + }, + }, } } @@ -177,6 +182,21 @@ func TestOneNodeDaemonLaunchesPod(t *testing.T) { syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0) } +// DaemonSets should not place onto NotReady nodes +func TestNotReadNodeDaemonDoesNotLaunchPod(t *testing.T) { + manager, podControl := newTestController() + node := newNode("not-ready", nil) + node.Status = api.NodeStatus{ + Conditions: []api.NodeCondition{ + {Type: api.NodeReady, Status: api.ConditionFalse}, + }, + } + manager.nodeStore.Add(node) + ds := newDaemonSet("foo") + manager.dsStore.Add(ds) + syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0) +} + // Controller should not create pods on nodes which have daemon pods, and should remove excess pods from nodes that have extra pods. func TestDealsWithExistingPods(t *testing.T) { manager, podControl := newTestController()