-
Notifications
You must be signed in to change notification settings - Fork 4k
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
New expander: priority expander #1801
New expander: priority expander #1801
Conversation
cluster-autoscaler/FAQ.md
Outdated
@@ -606,6 +606,26 @@ after scale-up. This is useful when you have different classes of nodes, for exa | |||
would match the cluster size. This expander is described in more details | |||
[HERE](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/proposals/pricing.md). Currently it works only for GCE and GKE (patches welcome.) | |||
|
|||
* `priority` - selects the node group that has the highest priority assigned by the user. The priority configuration is based on the values stored in a ConfigMap. This ConfigMap has to be created before cluster autoscaler with priority expander can be started. The ConfigMap must be named `cluster-autoscaler-priority-expander` and it must be placed in the same namespace as cluster autoscaler pod. The format of the [ConfigMap](expander/priority/priority-expander-configmap.yaml) is as follows: |
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.
Can you merge the proposal and this text into a readme.md and put it into the expander directory?
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.
Do you want it only in expander dir and linked here?
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.
Just a brief description and a link, please.
@@ -0,0 +1,31 @@ | |||
# Priority based expander for cluster-autoscaler |
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.
Make it expander documentation.
continue | ||
} | ||
if err := res.parsePrioritiesYAMLString(prioString); err != nil { | ||
klog.Warningf("Wrong configuration for priority expander: %v. Ignoring update.", err) |
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 would also send an event, update status config map, etc. Be extremely noisy in case of misconfiguriation.
@mwielgus Changes are in place. I added events only, as the status-map seemed not to be a good fit to me: it keeps CAS-wide info only, no matter what expander you use. And if I'm not wrong, no other expander keeps status there. Still, if you think it would be beneficial, I can work on it. |
|
You have too many (21) commits in this PR. Please squash them to no more than 3 commits. |
4a80adc
to
8a5aee6
Compare
"merge with master" commit has misleading/ambiguous name. Please rename or squash with "priority expander". |
8a5aee6
to
c5ba4b3
Compare
rebased on master |
@@ -63,8 +63,8 @@ rules: | |||
verbs: ["create"] | |||
- apiGroups: [""] | |||
resources: ["configmaps"] | |||
resourceNames: ["cluster-autoscaler-status"] | |||
verbs: ["delete","get","update"] | |||
resourceNames: ["cluster-autoscaler-status", "cluster-autoscaler-priority-expander"] |
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.
Once this merges we should also update https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/rbac/cluster-autoscaler/cluster-autoscaler-rbac.yaml#L54.
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
/approve
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: mwielgus The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
@mwielgus Thanks for the review! One question though: what is the best approach to backport it, we would need it back in 1.11 (1.3) kubernetes release. |
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.
Sorry I'm late to the party, but I have some comments for the implementation. In particular I think it will fail after the channel is abruptly closed after a few hours - we've already had this problem in both HPA and VPA. Can you create another PR addressing the comments?
return "", nil, errors.New(errMsg) | ||
} | ||
|
||
watcher, err := maps.Watch(metav1.ListOptions{ |
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.
Listers already handle watch cache and all necessary error handling and we use those for all other objects. I don't think we should re-implement this functionality. In particular if you want to use watch directly you need to handle channel closing - in both HPA and VPA we've already run into issues caused by watch channel abruptly closing and we needed to implement a retry logic for this case. I don't see such retry logic in this PR.
That being said - unless you have a very strong reason I strongly recommend using a lister or an informer, rather than directly using watch API.
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 didn't know about any problems using watch API - when is the channel closed? Can you point me to some docs?
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 don't know if there is any documentation on the details. IIRC @jbartosik once run into similar issue, so he may provide more details. The general recommendation is to always use higher-level abstractions provided by client-go library, rather than raw client.
} | ||
|
||
// EventRecorder is an interface to abstract kubernetes event recording. | ||
type EventRecorder interface { |
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 are you redefining this here?
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.
For testability - check unit tests. Have I missed exactly the same interface being already defined elsewhere?
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.
After taking a closer look at unittests - they're very inconsistent with existing unittests. We have utilities we use for making fake nodegroups (https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/test/test_cloud_provider.go) and there is an existing utility for faking event recording (used for example here: https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/processors/status/eventing_scale_up_processor_test.go#L87).
Please use existing tooling for your unittests.
for event := range priorityChangesChan { | ||
cm, ok := event.Object.(*apiv1.ConfigMap) | ||
if !ok { | ||
klog.Exit("Unexpected object type received on the configmap update channel in priority expander") |
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.
You should return an appropriate error (API or Internal), not crash the application.
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.
OK.
fallbackStrategy expander.Strategy | ||
changesChan <-chan watch.Event | ||
priorities map[int][]*regexp.Regexp | ||
padlock sync.RWMutex |
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.
Expander is called once per loop, at most 1 call / 10s (more likely 1 per 15-20s), after a ton of complex calculations done all over CA code. Do we really need async config update? Feels like we could just get configmap from watch cache every time and synchronously check if the config changed - the performance impact should be negligible and the complexity of this expander will greatly reduce.
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.
Hmm, I agree, if there's no plan to make the updates/loops more frequent in the future, probably we can drop the watch and go with fetching the map every time. I'm just not sure about caching - can you point me to some docs? How is stuff cached, for how long and what is your default caching toolset for CAS?
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.
By 'watch cache' I mean using listers or informers. Those are a higher level abstraction for Kubernetes client provided by client-go. They provide a local cache that is backed by a watch on apiserver and updated on any change. So you get fresh data, except you don't have to care about creating goroutines doing the watch and error handling - it's all provided.
The general recommendation is to always use lister or informer over raw client, unless there is a very good reason not to.
I created this PR to update RBAC YAML in kubernetes: kubernetes/kubernetes#75814 |
They should've been fixed in kubernetes#1801, kubernetes#1920
They should've been fixed in kubernetes#1801, kubernetes#1920
They should've been fixed in kubernetes#1801, kubernetes#1920
They should've been fixed in kubernetes#1801, kubernetes#1920
They should've been fixed in kubernetes#1801, kubernetes#1920
They should've been fixed in kubernetes/autoscaler#1801, kubernetes/autoscaler#1920
They should've been fixed in kubernetes#1801, kubernetes#1920
The PR
This commit introduces code, tests and docs for a new expander called 'priority'. The motivation is placed in this proposal. Docs are updated as well in FAQ.
Testing procedure
Full autoamted kubernetes e2e tests were not done. The testing procedure was as follows:
Unit tests
go test ./expander/priority/...
Manual e2e tests