Skip to content
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

Merged

Conversation

piontec
Copy link
Contributor

@piontec piontec commented Mar 18, 2019

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:

  1. Unit tests
    go test ./expander/priority/...

  2. Manual e2e tests

    • I started a test cluster and connected the new cluster-autoscaler binary to it
    • checked for selection of the correct node group
    • check for handling of ConfigMap reloads

@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Mar 18, 2019
@@ -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:
Copy link
Contributor

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?

Copy link
Contributor Author

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?

Copy link
Contributor

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
Copy link
Contributor

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)
Copy link
Contributor

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.

@piontec
Copy link
Contributor Author

piontec commented Mar 21, 2019

@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.

@mwielgus
Copy link
Contributor

!!! 'golint' problems: 
/home/travis/gopath/src/k8s.io/autoscaler/cluster-autoscaler/expander/priority/priority.go:181:6: exported type EventRecorder should have comment or be unexported

@mwielgus
Copy link
Contributor

You have too many (21) commits in this PR. Please squash them to no more than 3 commits.

@piontec piontec force-pushed the feature/priority_expander branch from 4a80adc to 8a5aee6 Compare March 22, 2019 09:21
@mwielgus
Copy link
Contributor

"merge with master" commit has misleading/ambiguous name. Please rename or squash with "priority expander".

@piontec piontec force-pushed the feature/priority_expander branch from 8a5aee6 to c5ba4b3 Compare March 22, 2019 09:43
@piontec
Copy link
Contributor Author

piontec commented Mar 22, 2019

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"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

@mwielgus mwielgus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm
/approve

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Mar 25, 2019
@k8s-ci-robot
Copy link
Contributor

[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 /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Mar 25, 2019
@k8s-ci-robot k8s-ci-robot merged commit 3c64796 into kubernetes:master Mar 25, 2019
@piontec
Copy link
Contributor Author

piontec commented Mar 25, 2019

@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.

@piontec piontec deleted the feature/priority_expander branch March 25, 2019 13:21
Copy link
Contributor

@MaciekPytel MaciekPytel left a 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{
Copy link
Contributor

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.

Copy link
Contributor Author

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?

Copy link
Contributor

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 {
Copy link
Contributor

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?

Copy link
Contributor Author

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?

Copy link
Contributor

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")
Copy link
Contributor

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.

Copy link
Contributor Author

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
Copy link
Contributor

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.

Copy link
Contributor Author

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?

Copy link
Contributor

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.

@piontec
Copy link
Contributor Author

piontec commented Mar 28, 2019

I created this PR to update RBAC YAML in kubernetes: kubernetes/kubernetes#75814

k8s-ci-robot added a commit that referenced this pull request Nov 28, 2019
Cherry pick #1801 #1843 #1889 #1920 to 1.14: Priority Expander
ghost pushed a commit to Capillary/autoscaler that referenced this pull request Jan 28, 2021
umialpha pushed a commit to umialpha/autoscaler that referenced this pull request Mar 26, 2021
aksentyev pushed a commit to aksentyev/autoscaler that referenced this pull request Apr 9, 2021
piotrnosek pushed a commit to piotrnosek/autoscaler that referenced this pull request Nov 30, 2021
himanshu-kun pushed a commit to himanshu-kun/autoscaler that referenced this pull request Apr 11, 2022
galina-tochilkin pushed a commit to mtp-devops/3d-party-helm that referenced this pull request Aug 17, 2022
tim-smart pushed a commit to arisechurch/autoscaler that referenced this pull request Nov 22, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants