mirror of
https://github.com/vmware-tanzu/velero.git
synced 2026-06-10 00:03:10 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 323900adcc | |||
| 317ffd069f | |||
| d6d9e4ee16 |
@@ -0,0 +1 @@
|
||||
Make ToSystemAffinity deterministic by sorting MatchLabels keys to avoid spurious affinity spec diffs and restarts
|
||||
+15
-1
@@ -20,6 +20,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -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 {
|
||||
// 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},
|
||||
|
||||
@@ -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{
|
||||
|
||||
Reference in New Issue
Block a user