mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-26 05:03:09 +00:00
service controller: only sync LB node pools when relevant fields change
Signed-off-by: Andrew Sy Kim <kim.andrewsy@gmail.com>
This commit is contained in:
parent
5983660ed7
commit
80a8a8df1c
@ -176,6 +176,20 @@ func New(
|
|||||||
s.nodeSyncLoop()
|
s.nodeSyncLoop()
|
||||||
},
|
},
|
||||||
UpdateFunc: func(old, cur interface{}) {
|
UpdateFunc: func(old, cur interface{}) {
|
||||||
|
oldNode, ok := old.(*v1.Node)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
curNode, ok := cur.(*v1.Node)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !shouldSyncNode(oldNode, curNode) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
s.nodeSyncLoop()
|
s.nodeSyncLoop()
|
||||||
},
|
},
|
||||||
DeleteFunc: func(old interface{}) {
|
DeleteFunc: func(old interface{}) {
|
||||||
@ -649,6 +663,30 @@ func getNodeConditionPredicate() NodeConditionPredicate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func shouldSyncNode(oldNode, newNode *v1.Node) bool {
|
||||||
|
if oldNode.Spec.Unschedulable != newNode.Spec.Unschedulable {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(oldNode.Labels, newNode.Labels) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodeReadyConditionStatus(oldNode) != nodeReadyConditionStatus(newNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func nodeReadyConditionStatus(node *v1.Node) v1.ConditionStatus {
|
||||||
|
for _, condition := range node.Status.Conditions {
|
||||||
|
if condition.Type != v1.NodeReady {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return condition.Status
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// nodeSyncLoop handles updating the hosts pointed to by all load
|
// nodeSyncLoop handles updating the hosts pointed to by all load
|
||||||
// balancers whenever the set of nodes in the cluster changes.
|
// balancers whenever the set of nodes in the cluster changes.
|
||||||
func (s *Controller) nodeSyncLoop() {
|
func (s *Controller) nodeSyncLoop() {
|
||||||
|
@ -1486,3 +1486,122 @@ func TestListWithPredicate(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_shouldSyncNode(t *testing.T) {
|
||||||
|
testcases := []struct {
|
||||||
|
name string
|
||||||
|
oldNode *v1.Node
|
||||||
|
newNode *v1.Node
|
||||||
|
shouldSync bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "spec.unschedable field changed",
|
||||||
|
oldNode: &v1.Node{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "node",
|
||||||
|
},
|
||||||
|
Spec: v1.NodeSpec{
|
||||||
|
Unschedulable: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
newNode: &v1.Node{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "node",
|
||||||
|
},
|
||||||
|
Spec: v1.NodeSpec{
|
||||||
|
Unschedulable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
shouldSync: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "labels changed",
|
||||||
|
oldNode: &v1.Node{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "node",
|
||||||
|
Labels: map[string]string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
newNode: &v1.Node{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "node",
|
||||||
|
Labels: map[string]string{
|
||||||
|
labelNodeRoleExcludeBalancer: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
shouldSync: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ready condition changed",
|
||||||
|
oldNode: &v1.Node{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "node",
|
||||||
|
},
|
||||||
|
Status: v1.NodeStatus{
|
||||||
|
Conditions: []v1.NodeCondition{
|
||||||
|
{
|
||||||
|
Type: v1.NodeReady,
|
||||||
|
Status: v1.ConditionTrue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
newNode: &v1.Node{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "node",
|
||||||
|
},
|
||||||
|
Status: v1.NodeStatus{
|
||||||
|
Conditions: []v1.NodeCondition{
|
||||||
|
{
|
||||||
|
Type: v1.NodeReady,
|
||||||
|
Status: v1.ConditionFalse,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
shouldSync: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "not relevant condition changed and no ready condition",
|
||||||
|
oldNode: &v1.Node{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "node",
|
||||||
|
},
|
||||||
|
Status: v1.NodeStatus{
|
||||||
|
Conditions: []v1.NodeCondition{
|
||||||
|
{
|
||||||
|
Type: v1.NodeNetworkUnavailable,
|
||||||
|
Status: v1.ConditionTrue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
newNode: &v1.Node{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "node",
|
||||||
|
},
|
||||||
|
Status: v1.NodeStatus{
|
||||||
|
Conditions: []v1.NodeCondition{
|
||||||
|
{
|
||||||
|
Type: v1.NodeNetworkUnavailable,
|
||||||
|
Status: v1.ConditionFalse,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
shouldSync: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testcase := range testcases {
|
||||||
|
t.Run(testcase.name, func(t *testing.T) {
|
||||||
|
shouldSync := shouldSyncNode(testcase.oldNode, testcase.newNode)
|
||||||
|
if shouldSync != testcase.shouldSync {
|
||||||
|
t.Logf("actual shouldSyncNode: %v", shouldSync)
|
||||||
|
t.Logf("expected shouldSyncNode: %v", testcase.shouldSync)
|
||||||
|
t.Errorf("unexpected result from shouldSyncNode")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user