-
Notifications
You must be signed in to change notification settings - Fork 979
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reoriented WellKnownLabels API parameters around generic requirements #747
Conversation
✔️ Deploy Preview for karpenter-docs-prod canceled. 🔨 Explore the source changes: af2032a 🔍 Inspect the deploy log: https://app.netlify.com/sites/karpenter-docs-prod/deploys/6171f2dc1eee370008614747 |
Can you post a sample Provisioner using this? |
3b1311e
to
f927ad9
Compare
f927ad9
to
f543907
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lgtm overall, just a few minor comments
return c.Requirements.GetLabelValues(v1.LabelTopologyZone) | ||
} | ||
|
||
/// InstanceTypes for the constraints |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extra /
@@ -20,7 +20,7 @@ import ( | |||
|
|||
"github.com/awslabs/karpenter/pkg/apis/provisioning/v1alpha4" | |||
"github.com/awslabs/karpenter/pkg/cloudprovider" | |||
"k8s.io/api/core/v1" | |||
v1 "k8s.io/api/core/v1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An epic battle with my linter -- which I lost. Will fix.
if err := constraints.Constrain(ctx); err != nil { | ||
return nil, fmt.Errorf("applying constraints, %w", err) | ||
} | ||
constraints.Requirements = constraints.CombineRequirements() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems a bit odd for the constraints struct not to handle this itself (as opposed to the Scheduler reaching in and doing it?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit tricky since we're reusing the same struct throughout the codebase (Constraints), which is optimized for user expression. I wanted to avoid CombineRequirements() in a tight for-each-pod loop, as it may execute ~10,000s of times. Perhaps this optimization is unnecessary. It definitely does feel like a hack and I really dislike the mutation.
Here are the options I see:
- Mutate the existing struct (current approach)
- Create a new concept that wraps constraints for Scheduling
Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's worth optimizing, for sure. I think if it worked something like:
requirements := contraints.CombineRequirements() // makes copy and compresses
// ...
if err := s.Topology.Inject(ctx, requirements, pods); err != nil {
return nil, fmt.Errorf("injecting topology, %w", err)
}
That could work. If you want to do option #2, something like (ignore bad naming):
// Call this before using constraints in a tight loop
constraints.Compress()
Which would do substantially the same thing you're doing today, but would be hidden by the constraints thingy (object?) itself, rather than the client code knowing how to do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the first example, we would need to pass these combined requirements (along w/ provider, taints, and labels) into the per-pod scheduling logic. By the time we're passing those 4 things, we might as well use the constraints object, since it has those exact fields.
I like the second approach you noted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ended up doing a hybrid approach:
constraints = constraints.Compress()
This avoids mutation and returns a compressed copy, which we use for the rest of provisioning.
labels: | ||
additionalProperties: | ||
type: string | ||
description: Labels will be applied to every node launched by the | ||
Provisioner. | ||
description: Labels are layered with Requirements and applied to every |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me, Labels
is a little confusing. Should this actually just be NodeSelectors
to denote that it has some sort of requirements logic in it. I think propagating out labels for a nodeSelector spec makes intuitive sense too, wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
discussed offline
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/lgtm
1. Issue, if available:
2. Description of changes:
Experimental API Change/Proposal.
Behavior
Motivation
NotIn
semantic at the provisioner level (e.g. excluding specific instance types)Future
Preferences
field, to configure soft constraints at the provisioner level. I punted on this complexity for this PR.Example Provisioner
3. Does this change impact docs?
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.