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

Standard API qps and burst in kubeconfig file. #1629

Closed
wants to merge 1 commit into from

Conversation

deads2k
Copy link
Contributor

@deads2k deads2k commented Mar 23, 2020

Standard API qps and burst in kubeconfig file.

This allows consistent configuration of all client binaries's QPS and burst settings. This becomes more important now that API priority and fairness is alpha and we want people to try it.

@k8s-ci-robot k8s-ci-robot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Mar 23, 2020
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: deads2k

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 kind/kep Categorizes KEP tracking issues and PRs modifying the KEP directory sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. approved Indicates a PR has been approved by an approver from all required OWNERS files. labels Mar 23, 2020
@deads2k deads2k changed the title [wip] make API QPS and burst configureable via kubeconfig Standard API qps and burst in kubeconfig file. Mar 24, 2020
@k8s-ci-robot k8s-ci-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 24, 2020
@k8s-ci-robot
Copy link
Contributor

@deads2k: The following test failed, say /retest to rerun all failed tests:

Test name Commit Details Rerun command
pull-enhancements-verify 224f926 link /test pull-enhancements-verify

Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

type AuthInfo struct {
// ...
// QPS indicates the maximum QPS to the master from this client.
// If it's zero, the created RESTClient will use DefaultQPS: 5
Copy link
Member

Choose a reason for hiding this comment

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

should we clarify a negative QPS will turn off the ratelimiting in the doc?

Copy link

Choose a reason for hiding this comment

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

"Set to -1 to turn off rate limiting. A value of 0 means to use the default limit from the client binary."

Copy link
Member

Choose a reason for hiding this comment

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

-1 can be even confusing given that the QPS is a float32. what's supposed to happen it's other negative values than -1?

Copy link
Member

Choose a reason for hiding this comment

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

Agree with others, clarify how to turn it off, clarify what negative numbers do (if not that).

I don't really want to make this super more complicated than necessary, but making this into a union/one-of block might make sense.

## Summary

Kubernetes REST clients use a simple token bucket rate limiter to control the pace of requests from a client.
We will expose the values already present in the [REST config](https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/client-go/rest/config.go#L114-L120), via a kubeconfig file inside the client stanza.
Copy link
Member

Choose a reason for hiding this comment

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

Line numbers are not stable in the master branch. For a long-lived document like this, it would be better to reference a particular commit. The following URL references the commit to which the master branch currently points. This URL also skips the staging junk, but still suffices to direct the reader to the intended content.

https://github.com/kubernetes/client-go/blob/d4685ebf697c8e0d9c8ae48db6c0ce34221d0326/rest/config.go#L115-L121

## Summary

Kubernetes REST clients use a simple token bucket rate limiter to control the pace of requests from a client.
We will expose the values already present in the [REST config](https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/client-go/rest/config.go#L114-L120), via a kubeconfig file inside the client stanza.
Copy link
Member

Choose a reason for hiding this comment

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

"via a kubeconfig file inside the client stanza" sounds like it is referring to a kubeconfig file that is inside some client stanza --- but I do not think this is what's meant here. I think what's meant is more like "via the user definitions in kubeconfig files". Alternatively, perhaps what is meant is more like "via a kubeconfig file that is added to a ServiceAccount's Secret".

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
We will expose the values already present in the [REST config](https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/client-go/rest/config.go#L114-L120), via a kubeconfig file inside the client stanza.
We will expose the values already present in the [REST config](https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/client-go/rest/config.go#L114-L120), in the client stanza of a kubeconfig file.

Copy link
Member

Choose a reason for hiding this comment

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

you mean "a user stanza"?


## Proposal

Add to the `AuthInfo` section of a kubeconfig.
Copy link
Member

Choose a reason for hiding this comment

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

Why not in the preferences? That would merge just fine and not involve the complicated (and poorly documented) logic involved in merging users --- which does not even meet the need 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.

Why not in the preferences? That would merge just fine and not involve the complicated (and poorly documented) logic involved in merging users --- which does not even meet the need here.

That's a dead field.

This identity spans all the contexts with different namespaces, so it is a closer logical match.
You don't generally want different QPS characteristics based on namespace.

```go
Copy link
Member

Choose a reason for hiding this comment

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

Please include a URL or k/k-relative pathname for the file where this mod would apply.

### in-cluster kubeconfig overrides
The in-cluster config is the automatic configuration that exists within pods.
The client code itself can be written to consume an overrides.kubeconfig file, which will be merged with the standard
kubeconfig merging rules that we use the env var path today.
Copy link
Member

Choose a reason for hiding this comment

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

The merging rules we have today do not allow adding/modifying fields within a user. The first specification of that user is taken as a whole and no part is overridden.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The merging rules we have today do not allow adding/modifying fields within a user. The first specification of that user is taken as a whole and no part is overridden.

No, we merge all of it: https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/client-go/tools/clientcmd/loader.go#L226-L252

You're probably used to selection, but merging is also a thing.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, I looked at that code. You see I raised issues with the poor comment on that function (kubernetes/kubernetes#91092) and the poor user-facing documentation about this (kubernetes/website#20967).

The code in question does not itself answer the question, it just makes a two-handed pile of invocations of mergo.MergeWithOverwrite. The comments on that suggest that merging will be done, but the implementation does not do that. The implementation does not simply look at each layer of structure independently. In the case of a map, the behavior depends on the type of each value. In the case of a map entry whose value is a struct or pointer, the implementation gets to https://github.com/imdario/mergo/blob/v0.3.5/merge.go#L143 --- which replaces the whole value without recursing into it.

I tested, and indeed found that when merging two kubeconfig files that define different fields for a certain user, the result is only the fields of the first kubeconfig file to define that user.

}
```

### in-cluster kubeconfig overrides
Copy link
Member

Choose a reason for hiding this comment

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

The vision here is not entirely clear. I suspect the idea is that the Secret of a ServiceAccount would be extended to have a data member named overrides.kubeconfig containing a kubeconfig file that specifies the QPS and Burst and nothing else, and that anyone who wants to exercise this control has to create a controller that modifies all the ServiceAccount Secret objects. Have I got this right? If so, that's pretty painful to use and requires a controller with extreme privilege.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Have I got this right? If so, that's pretty painful to use and requires a controller with extreme privilege.

Yeah, but anything we do is going to require mutation of that same secret. It isn't to be taken lightly in general. This is about making it possible, I don't think easy is needed.

Copy link
Member

Choose a reason for hiding this comment

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

This QPS limit has to be a property of the service account, so this does seem necessary.

Maybe it's not the only model though, I'll make another comment.

### Graduation Criteria

The API itself is well-known since near the beginning of kube.
We are simply exposing existing values, it will enter as GA.
Copy link
Member

Choose a reason for hiding this comment

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

There is significant novelty here, in the override mechanism.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There is significant novelty here, in the override mechanism.

I don't think so. I built this pre-1.0 so the merging code already exists. This is just about the expression of what merges.

Copy link
Member

@MikeSpreitzer MikeSpreitzer May 15, 2020

Choose a reason for hiding this comment

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

Things are different today, I hear every mother say.


1. Connecting to the kube-apiserver to retrieve a value for default QPS and burst.
No default value is going to be good across all workloads.
It's also mechanicaly weird to create a client to get a client.
Copy link
Member

Choose a reason for hiding this comment

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

I agree this is a bit weird, but it wouldn't have to be a separate request-- we could make apiserver set a header with its desired rate limit, and the client just obeys it after the first request. This might be simpler?

Copy link
Member

Choose a reason for hiding this comment

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

I am actually liking this (return a header) more the longer I think about it. Since we have to recompile all clients anyway...

Copy link
Member

Choose a reason for hiding this comment

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

Yeah.

Copy link
Member

Choose a reason for hiding this comment

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

After more thought I think this is too heavyweight (on API changes -- but so is the main proposal), and it's easy to believe that not all clients would want the same rate limit.

Copy link
Member

Choose a reason for hiding this comment

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

(So I guess this would still be in consideration if it were just about turning off the rate limit, not about setting it.)


## Implementation History

## Drawbacks
Copy link
Member

Choose a reason for hiding this comment

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

Do other, non-go clients parse kubeconfig files?

I assume repeated invocations of kubectl would not respect the limits in aggregate?

Copy link
Member

Choose a reason for hiding this comment

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

I think this is aimed at long-lived clients rather than kubectl. I would not expect client-side rate limits to be relevant to kubectl.

Copy link
Member

Choose a reason for hiding this comment

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

I would not expect that either, but users who see the settings in their kubeconfig files might.

Copy link
Member

Choose a reason for hiding this comment

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

This proposal allows new content in the kubeconfig files that users hold, but does not require it in general nor in the motivating scenario in particular.


### Goals

1. Allow easy and consistent configuration for the existing client-side rate limiting.
Copy link
Member

Choose a reason for hiding this comment

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

Is this our goal, or is our goal to get rid of it completely?

Is this necessary only transitionally, or forever?


## Drawbacks

## Alternatives
Copy link
Member

Choose a reason for hiding this comment

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

Another alternative might be to plumb these via env var. That'd be gross, but very direct.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah.

Copy link
Member

Choose a reason for hiding this comment

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

The go team tends to do things this way, e.g. for disabling their home grown DNS resolver, and also for disabling HTTP2 I think.

The benefit of this is that it only requires one component to change, no API is baked in, we can remove the env var without breaking people who are setting it.

The downside is that it's not very discoverable (but maybe that's OK since we mostly want to use it to run tests).

Copy link
Member

Choose a reason for hiding this comment

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

Anyone setting this should also look at the client's metrics to verify that it's not spending any time blocked on the QPS limiter (I think there's already a metric).

@lavalamp
Copy link
Member

@deads2k, @liggitt, and I have agreed on the "pre-deprecated, global env var" approach. That is, we'll make the client library check for an environment variable and avoid installing the rate limiter if it is set to some value. The purpose of doing it this way is to avoid committing to an API since we aren't sure it'll be useful for a long period of time. So, we will do this with the env var already deprecated and remove it without warning.

Since this won't be a user-visible feature we don't plan on making a KEP for this.

@deads2k
Copy link
Contributor Author

deads2k commented Jun 1, 2020

@deads2k, @liggitt, and I have agreed on the "pre-deprecated, global env var" approach. That is, we'll make the client library check for an environment variable and avoid installing the rate limiter if it is set to some value. The purpose of doing it this way is to avoid committing to an API since we aren't sure it'll be useful for a long period of time. So, we will do this with the env var already deprecated and remove it without warning.

Since this won't be a user-visible feature we don't plan on making a KEP for this.

Agreed

/close

@k8s-ci-robot
Copy link
Contributor

@deads2k: Closed this PR.

In response to this:

@deads2k, @liggitt, and I have agreed on the "pre-deprecated, global env var" approach. That is, we'll make the client library check for an environment variable and avoid installing the rate limiter if it is set to some value. The purpose of doing it this way is to avoid committing to an API since we aren't sure it'll be useful for a long period of time. So, we will do this with the env var already deprecated and remove it without warning.

Since this won't be a user-visible feature we don't plan on making a KEP for this.

Agreed

/close

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

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. kind/kep Categorizes KEP tracking issues and PRs modifying the KEP directory sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants