Skip to content

Commit

Permalink
Fixes a bug with affinity, where OR semantic was treated as AND
Browse files Browse the repository at this point in the history
  • Loading branch information
ellistarn committed Oct 1, 2021
1 parent ea9800f commit 7e86f97
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 10 deletions.
4 changes: 2 additions & 2 deletions pkg/controllers/allocation/scheduling/preferences.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ func (p *Preferences) removePreferredNodeAffinityTerm(ctx context.Context, pod *
terms := pod.Spec.Affinity.NodeAffinity.PreferredDuringSchedulingIgnoredDuringExecution
// Remove the terms if there are any (terms are an OR semantic)
if len(terms) > 0 {
// Sort ascending by weight to remove lightest preferences first
sort.SliceStable(terms, func(i, j int) bool { return terms[i].Weight < terms[j].Weight })
// Sort descending by weight to remove heaviest preferences to try lighter ones
sort.SliceStable(terms, func(i, j int) bool { return terms[i].Weight > terms[j].Weight })
pod.Spec.Affinity.NodeAffinity.PreferredDuringSchedulingIgnoredDuringExecution = terms[1:]
return ptr.String(fmt.Sprintf("spec.affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution[0]=%s", pretty.Concise(terms[0])))
}
Expand Down
17 changes: 10 additions & 7 deletions pkg/scheduling/nodeaffinity.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ limitations under the License.
package scheduling

import (
"sort"

"github.com/awslabs/karpenter/pkg/utils/functional"
v1 "k8s.io/api/core/v1"
)
Expand All @@ -31,14 +33,15 @@ func NodeAffinityFor(pods ...*v1.Pod) (nodeAffinity NodeAffinity) {
if pod.Spec.Affinity == nil || pod.Spec.Affinity.NodeAffinity == nil {
continue
}
// Preferences are treated as requirements. An outer loop will iteratively unconstrain them if unsatisfiable
for _, term := range pod.Spec.Affinity.NodeAffinity.PreferredDuringSchedulingIgnoredDuringExecution {
nodeAffinity = append(nodeAffinity, term.Preference.MatchExpressions...)
// Select heaviest preference and treat as a requirement. An outer loop will iteratively unconstrain them if unsatisfiable.
if preferred := pod.Spec.Affinity.NodeAffinity.PreferredDuringSchedulingIgnoredDuringExecution; len(preferred) > 0 {
sort.Slice(preferred, (func(i int, j int) bool { return preferred[i].Weight > preferred[j].Weight }))
nodeAffinity = append(nodeAffinity, preferred[0].Preference.MatchExpressions...)
}
if pod.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution != nil {
for _, term := range pod.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms {
nodeAffinity = append(nodeAffinity, term.MatchExpressions...)
}
// Select first requirement. An outer loop will iteratively remove OR requirements if unsatisfiable
if pod.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution != nil &&
len(pod.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms) > 0 {
nodeAffinity = append(nodeAffinity, pod.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0].MatchExpressions...)
}
}
return nodeAffinity
Expand Down
3 changes: 2 additions & 1 deletion website/content/en/docs/getting-started/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ metadata:
spec:
provider:
instanceProfile: KarpenterNodeInstanceProfile-${CLUSTER_NAME}
capacityType: spot
capacityTypes:
- spot
cluster:
name: ${CLUSTER_NAME}
endpoint: $(aws eks describe-cluster --name ${CLUSTER_NAME} --query "cluster.endpoint" --output json)
Expand Down

0 comments on commit 7e86f97

Please sign in to comment.