diff --git a/pkg/controller/daemonset/daemonset_event_handler.go b/pkg/controller/daemonset/daemonset_event_handler.go index f9d3f98299..36a55be90e 100644 --- a/pkg/controller/daemonset/daemonset_event_handler.go +++ b/pkg/controller/daemonset/daemonset_event_handler.go @@ -259,7 +259,9 @@ func (e *nodeEventHandler) Update(evt event.UpdateEvent, q workqueue.RateLimitin ds := &dsList.Items[i] oldShouldRun, oldShouldContinueRunning := nodeShouldRunDaemonPod(oldNode, ds) currentShouldRun, currentShouldContinueRunning := nodeShouldRunDaemonPod(curNode, ds) - if (oldShouldRun != currentShouldRun) || (oldShouldContinueRunning != currentShouldContinueRunning) { + if (oldShouldRun != currentShouldRun) || (oldShouldContinueRunning != currentShouldContinueRunning) || + (NodeShouldUpdateBySelector(oldNode, ds) != NodeShouldUpdateBySelector(curNode, ds)) { + klog.V(6).Infof("update node: %s triggers DaemonSet %s/%s to reconcile.", curNode.Name, ds.GetNamespace(), ds.GetName()) q.Add(reconcile.Request{NamespacedName: types.NamespacedName{ Name: ds.GetName(), Namespace: ds.GetNamespace(), diff --git a/pkg/controller/daemonset/daemonset_util.go b/pkg/controller/daemonset/daemonset_util.go index 4486c75bb3..7f73d71c3c 100644 --- a/pkg/controller/daemonset/daemonset_util.go +++ b/pkg/controller/daemonset/daemonset_util.go @@ -305,3 +305,24 @@ func findUpdatedPodsOnNode(ds *appsv1alpha1.DaemonSet, podsOnNode []*corev1.Pod, } return newPod, oldPod, true } + +// NodeShouldUpdateBySelector checks if the node is selected to upgrade for ds's gray update selector. +// This function does not check NodeShouldRunDaemonPod +func NodeShouldUpdateBySelector(node *corev1.Node, ds *appsv1alpha1.DaemonSet) bool { + switch ds.Spec.UpdateStrategy.Type { + case appsv1alpha1.OnDeleteDaemonSetStrategyType: + return false + case appsv1alpha1.RollingUpdateDaemonSetStrategyType: + if ds.Spec.UpdateStrategy.RollingUpdate == nil || ds.Spec.UpdateStrategy.RollingUpdate.Selector == nil { + return false + } + selector, err := metav1.LabelSelectorAsSelector(ds.Spec.UpdateStrategy.RollingUpdate.Selector) + if err != nil { + // this should not happen if the DaemonSet passed validation + return false + } + return !selector.Empty() && selector.Matches(labels.Set(node.Labels)) + default: + return false + } +} diff --git a/pkg/controller/daemonset/daemonset_util_test.go b/pkg/controller/daemonset/daemonset_util_test.go index 9d5ceb0be5..653afdf56a 100644 --- a/pkg/controller/daemonset/daemonset_util_test.go +++ b/pkg/controller/daemonset/daemonset_util_test.go @@ -650,3 +650,69 @@ func TestGetMaxCreateNum(t *testing.T) { }) } } + +func TestNodeShouldUpdateBySelector(t *testing.T) { + for _, tt := range []struct { + Title string + Node *corev1.Node + Ds *appsv1alpha1.DaemonSet + Expected bool + }{ + { + "node with no label", + newNode("node1", nil), + newDaemonSet("ds1"), + false, + }, + { + "node with label, not selected", + newNode("node1", map[string]string{ + "key1": "value1", + }), + func() *appsv1alpha1.DaemonSet { + ds := newDaemonSet("ds1") + ds.Spec.UpdateStrategy = newStandardRollingUpdateStrategy(map[string]string{ + "key1": "value2", + }) + return ds + }(), + false, + }, + { + "node with label, selected", + newNode("node1", map[string]string{ + "key1": "value1", + }), + func() *appsv1alpha1.DaemonSet { + ds := newDaemonSet("ds1") + ds.Spec.UpdateStrategy = newStandardRollingUpdateStrategy(map[string]string{ + "key1": "value1", + }) + return ds + }(), + true, + }, + } { + t.Logf("\t%s", tt.Title) + should := NodeShouldUpdateBySelector(tt.Node, tt.Ds) + if should != tt.Expected { + t.Errorf("NodeShouldUpdateBySelector() = %v, want %v", should, tt.Expected) + } + } +} + +func newStandardRollingUpdateStrategy(matchLabels map[string]string) appsv1alpha1.DaemonSetUpdateStrategy { + one := intstr.FromInt(1) + strategy := appsv1alpha1.DaemonSetUpdateStrategy{ + Type: appsv1alpha1.RollingUpdateDaemonSetStrategyType, + RollingUpdate: &appsv1alpha1.RollingUpdateDaemonSet{ + MaxUnavailable: &one, + Selector: nil, + Type: appsv1alpha1.StandardRollingUpdateType, + }, + } + if len(matchLabels) > 0 { + strategy.RollingUpdate.Selector = &metav1.LabelSelector{MatchLabels: matchLabels} + } + return strategy +}