Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelogs/unreleased/9898-kaovilai
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Make ToSystemAffinity deterministic by sorting MatchLabels keys to avoid spurious affinity spec diffs and restarts
16 changes: 15 additions & 1 deletion pkg/util/kube/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"fmt"
"io"
"os"
"sort"
"strings"
"time"

Expand Down Expand Up @@ -236,7 +237,20 @@ func CollectPodLogs(ctx context.Context, podGetter corev1client.CoreV1Interface,
func ToSystemAffinity(loadAffinity *LoadAffinity, volumeTopology *corev1api.NodeSelector) *corev1api.Affinity {
requirements := []corev1api.NodeSelectorRequirement{}
if loadAffinity != nil {
for k, v := range loadAffinity.NodeSelector.MatchLabels {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you could instead sort the final requirements, which looks more clear in the code

// MatchLabels is a map, so its iteration order is not deterministic.
// Sort the keys so the generated requirements (and therefore the
// resulting affinity) have a stable order. This output may be embedded
// into objects that are reconciled continuously (e.g. DaemonSet pod
// templates), where an order-only difference would be treated as a spec
// change and trigger unnecessary rollouts/restarts.
keys := make([]string, 0, len(loadAffinity.NodeSelector.MatchLabels))
for k := range loadAffinity.NodeSelector.MatchLabels {
keys = append(keys, k)
}
sort.Strings(keys)

for _, k := range keys {
v := loadAffinity.NodeSelector.MatchLabels[k]
requirements = append(requirements, corev1api.NodeSelectorRequirement{
Key: k,
Values: []string{v},
Expand Down
39 changes: 39 additions & 0 deletions pkg/util/kube/pod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,45 @@ func TestToSystemAffinity(t *testing.T) {
},
},
},
{
name: "with multiple match labels are sorted by key",
loadAffinity: &LoadAffinity{
NodeSelector: metav1.LabelSelector{
MatchLabels: map[string]string{
"key-c": "value-c",
"key-a": "value-a",
"key-b": "value-b",
},
},
},
expected: &corev1api.Affinity{
NodeAffinity: &corev1api.NodeAffinity{
RequiredDuringSchedulingIgnoredDuringExecution: &corev1api.NodeSelector{
NodeSelectorTerms: []corev1api.NodeSelectorTerm{
{
MatchExpressions: []corev1api.NodeSelectorRequirement{
{
Key: "key-a",
Values: []string{"value-a"},
Operator: corev1api.NodeSelectorOpIn,
},
{
Key: "key-b",
Values: []string{"value-b"},
Operator: corev1api.NodeSelectorOpIn,
},
{
Key: "key-c",
Values: []string{"value-c"},
Operator: corev1api.NodeSelectorOpIn,
},
},
},
},
},
},
},
},
{
name: "with olume topology",
volumeTopology: &corev1api.NodeSelector{
Expand Down
Loading