1
0
mirror of https://github.com/kubernetes-sigs/descheduler.git synced 2026-01-28 06:29:29 +01:00

Merge pull request #1317 from SataQiu/fix-log-20231212

fix: topologySpreadConstraint fields in structured logs
This commit is contained in:
Kubernetes Prow Robot
2023-12-15 17:14:15 +01:00
committed by GitHub
2 changed files with 39 additions and 38 deletions

View File

@@ -53,14 +53,15 @@ type topology struct {
// topologySpreadConstraint is an internal version for v1.TopologySpreadConstraint // topologySpreadConstraint is an internal version for v1.TopologySpreadConstraint
// and where the selector is parsed. // and where the selector is parsed.
// This mirrors scheduler: https://github.com/kubernetes/kubernetes/blob/release-1.28/pkg/scheduler/framework/plugins/podtopologyspread/common.go#L37 // This mirrors scheduler: https://github.com/kubernetes/kubernetes/blob/release-1.28/pkg/scheduler/framework/plugins/podtopologyspread/common.go#L37
// Fields are exported for structured logging.
type topologySpreadConstraint struct { type topologySpreadConstraint struct {
maxSkew int32 MaxSkew int32
topologyKey string TopologyKey string
selector labels.Selector Selector labels.Selector
nodeAffinityPolicy v1.NodeInclusionPolicy NodeAffinityPolicy v1.NodeInclusionPolicy
nodeTaintsPolicy v1.NodeInclusionPolicy NodeTaintsPolicy v1.NodeInclusionPolicy
podNodeAffinity nodeaffinity.RequiredNodeAffinity PodNodeAffinity nodeaffinity.RequiredNodeAffinity
podTolerations []v1.Toleration PodTolerations []v1.Toleration
} }
// RemovePodsViolatingTopologySpreadConstraint evicts pods which violate their topology spread constraints // RemovePodsViolatingTopologySpreadConstraint evicts pods which violate their topology spread constraints
@@ -180,9 +181,9 @@ func (d *RemovePodsViolatingTopologySpreadConstraint) Balance(ctx context.Contex
// pre-populate the topologyPair map with all the topologies available from the nodeMap // pre-populate the topologyPair map with all the topologies available from the nodeMap
// (we can't just build it from existing pods' nodes because a topology may have 0 pods) // (we can't just build it from existing pods' nodes because a topology may have 0 pods)
for _, node := range nodeMap { for _, node := range nodeMap {
if val, ok := node.Labels[tsc.topologyKey]; ok { if val, ok := node.Labels[tsc.TopologyKey]; ok {
if matchNodeInclusionPolicies(tsc, node) { if matchNodeInclusionPolicies(tsc, node) {
constraintTopologies[topologyPair{key: tsc.topologyKey, value: val}] = make([]*v1.Pod, 0) constraintTopologies[topologyPair{key: tsc.TopologyKey, value: val}] = make([]*v1.Pod, 0)
} }
} }
} }
@@ -196,7 +197,7 @@ func (d *RemovePodsViolatingTopologySpreadConstraint) Balance(ctx context.Contex
continue continue
} }
// 4. if the pod matches this TopologySpreadConstraint LabelSelector // 4. if the pod matches this TopologySpreadConstraint LabelSelector
if !tsc.selector.Matches(labels.Set(pod.Labels)) { if !tsc.Selector.Matches(labels.Set(pod.Labels)) {
continue continue
} }
@@ -206,12 +207,12 @@ func (d *RemovePodsViolatingTopologySpreadConstraint) Balance(ctx context.Contex
// If ok is false, node is nil in which case node.Labels will panic. In which case a pod is yet to be scheduled. So it's safe to just continue here. // If ok is false, node is nil in which case node.Labels will panic. In which case a pod is yet to be scheduled. So it's safe to just continue here.
continue continue
} }
nodeValue, ok := node.Labels[tsc.topologyKey] nodeValue, ok := node.Labels[tsc.TopologyKey]
if !ok { if !ok {
continue continue
} }
// 6. create a topoPair with key as this TopologySpreadConstraint // 6. create a topoPair with key as this TopologySpreadConstraint
topoPair := topologyPair{key: tsc.topologyKey, value: nodeValue} topoPair := topologyPair{key: tsc.TopologyKey, value: nodeValue}
// 7. add the pod with key as this topoPair // 7. add the pod with key as this topoPair
constraintTopologies[topoPair] = append(constraintTopologies[topoPair], pod) constraintTopologies[topoPair] = append(constraintTopologies[topoPair], pod)
sumPods++ sumPods++
@@ -266,7 +267,7 @@ func topologyIsBalanced(topology map[topologyPair][]*v1.Pod, tsc topologySpreadC
if len(pods) > maxDomainSize { if len(pods) > maxDomainSize {
maxDomainSize = len(pods) maxDomainSize = len(pods)
} }
if int32(maxDomainSize-minDomainSize) > tsc.maxSkew { if int32(maxDomainSize-minDomainSize) > tsc.MaxSkew {
return false return false
} }
} }
@@ -307,7 +308,7 @@ func (d *RemovePodsViolatingTopologySpreadConstraint) balanceDomains(
topologyBalanceNodeFit := utilpointer.BoolDeref(d.args.TopologyBalanceNodeFit, true) topologyBalanceNodeFit := utilpointer.BoolDeref(d.args.TopologyBalanceNodeFit, true)
eligibleNodes := filterEligibleNodes(nodes, tsc) eligibleNodes := filterEligibleNodes(nodes, tsc)
nodesBelowIdealAvg := filterNodesBelowIdealAvg(eligibleNodes, sortedDomains, tsc.topologyKey, idealAvg) nodesBelowIdealAvg := filterNodesBelowIdealAvg(eligibleNodes, sortedDomains, tsc.TopologyKey, idealAvg)
// i is the index for belowOrEqualAvg // i is the index for belowOrEqualAvg
// j is the index for aboveAvg // j is the index for aboveAvg
@@ -323,7 +324,7 @@ func (d *RemovePodsViolatingTopologySpreadConstraint) balanceDomains(
skew := float64(len(sortedDomains[j].pods) - len(sortedDomains[i].pods)) skew := float64(len(sortedDomains[j].pods) - len(sortedDomains[i].pods))
// if k and j are within the maxSkew of each other, move to next belowOrEqualAvg // if k and j are within the maxSkew of each other, move to next belowOrEqualAvg
if int32(skew) <= tsc.maxSkew { if int32(skew) <= tsc.MaxSkew {
i++ i++
continue continue
} }
@@ -337,7 +338,7 @@ func (d *RemovePodsViolatingTopologySpreadConstraint) balanceDomains(
aboveAvg := math.Ceil(float64(len(sortedDomains[j].pods)) - idealAvg) aboveAvg := math.Ceil(float64(len(sortedDomains[j].pods)) - idealAvg)
belowAvg := math.Ceil(idealAvg - float64(len(sortedDomains[i].pods))) belowAvg := math.Ceil(idealAvg - float64(len(sortedDomains[i].pods)))
smallestDiff := math.Min(aboveAvg, belowAvg) smallestDiff := math.Min(aboveAvg, belowAvg)
halfSkew := math.Ceil((skew - float64(tsc.maxSkew)) / 2) halfSkew := math.Ceil((skew - float64(tsc.MaxSkew)) / 2)
movePods := int(math.Min(smallestDiff, halfSkew)) movePods := int(math.Min(smallestDiff, halfSkew))
if movePods <= 0 { if movePods <= 0 {
i++ i++
@@ -475,15 +476,15 @@ func filterEligibleNodes(nodes []*v1.Node, tsc topologySpreadConstraint) []*v1.N
} }
func matchNodeInclusionPolicies(tsc topologySpreadConstraint, node *v1.Node) bool { func matchNodeInclusionPolicies(tsc topologySpreadConstraint, node *v1.Node) bool {
if tsc.nodeAffinityPolicy == v1.NodeInclusionPolicyHonor { if tsc.NodeAffinityPolicy == v1.NodeInclusionPolicyHonor {
// We ignore parsing errors here for backwards compatibility. // We ignore parsing errors here for backwards compatibility.
if match, _ := tsc.podNodeAffinity.Match(node); !match { if match, _ := tsc.PodNodeAffinity.Match(node); !match {
return false return false
} }
} }
if tsc.nodeTaintsPolicy == v1.NodeInclusionPolicyHonor { if tsc.NodeTaintsPolicy == v1.NodeInclusionPolicyHonor {
if _, untolerated := v1helper.FindMatchingUntoleratedTaint(node.Spec.Taints, tsc.podTolerations, doNotScheduleTaintsFilterFunc()); untolerated { if _, untolerated := v1helper.FindMatchingUntoleratedTaint(node.Spec.Taints, tsc.PodTolerations, doNotScheduleTaintsFilterFunc()); untolerated {
return false return false
} }
} }
@@ -510,19 +511,19 @@ func newTopologySpreadConstraint(constraint v1.TopologySpreadConstraint, pod *v1
} }
tsc := topologySpreadConstraint{ tsc := topologySpreadConstraint{
maxSkew: constraint.MaxSkew, MaxSkew: constraint.MaxSkew,
topologyKey: constraint.TopologyKey, TopologyKey: constraint.TopologyKey,
selector: selector, Selector: selector,
nodeAffinityPolicy: v1.NodeInclusionPolicyHonor, // If NodeAffinityPolicy is nil, we treat NodeAffinityPolicy as "Honor". NodeAffinityPolicy: v1.NodeInclusionPolicyHonor, // If NodeAffinityPolicy is nil, we treat NodeAffinityPolicy as "Honor".
nodeTaintsPolicy: v1.NodeInclusionPolicyIgnore, // If NodeTaintsPolicy is nil, we treat NodeTaintsPolicy as "Ignore". NodeTaintsPolicy: v1.NodeInclusionPolicyIgnore, // If NodeTaintsPolicy is nil, we treat NodeTaintsPolicy as "Ignore".
podNodeAffinity: nodeaffinity.GetRequiredNodeAffinity(pod), PodNodeAffinity: nodeaffinity.GetRequiredNodeAffinity(pod),
podTolerations: pod.Spec.Tolerations, PodTolerations: pod.Spec.Tolerations,
} }
if constraint.NodeAffinityPolicy != nil { if constraint.NodeAffinityPolicy != nil {
tsc.nodeAffinityPolicy = *constraint.NodeAffinityPolicy tsc.NodeAffinityPolicy = *constraint.NodeAffinityPolicy
} }
if constraint.NodeTaintsPolicy != nil { if constraint.NodeTaintsPolicy != nil {
tsc.nodeTaintsPolicy = *constraint.NodeTaintsPolicy tsc.NodeTaintsPolicy = *constraint.NodeTaintsPolicy
} }
return tsc, nil return tsc, nil

View File

@@ -1608,20 +1608,20 @@ func TestCheckIdenticalConstraints(t *testing.T) {
selector, _ := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}) selector, _ := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}})
newConstraintSame := topologySpreadConstraint{ newConstraintSame := topologySpreadConstraint{
maxSkew: 2, MaxSkew: 2,
topologyKey: "zone", TopologyKey: "zone",
selector: selector.DeepCopySelector(), Selector: selector.DeepCopySelector(),
} }
newConstraintDifferent := topologySpreadConstraint{ newConstraintDifferent := topologySpreadConstraint{
maxSkew: 3, MaxSkew: 3,
topologyKey: "node", TopologyKey: "node",
selector: selector.DeepCopySelector(), Selector: selector.DeepCopySelector(),
} }
namespaceTopologySpreadConstraint := []topologySpreadConstraint{ namespaceTopologySpreadConstraint := []topologySpreadConstraint{
{ {
maxSkew: 2, MaxSkew: 2,
topologyKey: "zone", TopologyKey: "zone",
selector: selector.DeepCopySelector(), Selector: selector.DeepCopySelector(),
}, },
} }
testCases := []struct { testCases := []struct {