Admission options spits out admission control#45355
Conversation
|
Hi @p0lyn0mial. Thanks for your PR. I'm waiting for a kubernetes member to verify that this patch is reasonable to test. If it is, they should reply with DetailsInstructions 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. |
| // ApplyTo adds the admission chain to the server configuration | ||
| // note that pluginIntializer is optional, a generic plugin intializer will always be provided and appended | ||
| // to the list of plugin initializers. | ||
| func (a *AdmissionOptions) ApplyTo(pluginInitializer admission.PluginInitializer, authz authorizer.Authorizer, restConfig *rest.Config, serverCfg *server.Config) error { |
There was a problem hiding this comment.
we could also provide two methods one which would require external plugin initialiser (AppyToWithPluginInitailizer) and the other without a plugin initialiser (ApplyTo).
There was a problem hiding this comment.
What if the plugin initializer came last as a ... argument?
| // Overwrite the default for storage data format. | ||
| s.Etcd.DefaultStorageMediaType = "application/vnd.kubernetes.protobuf" | ||
| // Set the default for admission plugins names | ||
| s.Admission.PluginsNames = []string{"AlwaysAdmit"} |
There was a problem hiding this comment.
maybe it is better to append ?
There was a problem hiding this comment.
This is fine. It's my preference.
|
/assign @deads2k |
| } | ||
|
|
||
| // initi generic plugin initalizer | ||
| if a.genericPluginInitializer == nil { |
There was a problem hiding this comment.
note that generic plugin initializer is initialized only once.
There was a problem hiding this comment.
note that generic plugin initializer is initialized only once.
Doc on the method that we lazily init the generic plugin initializer down here.
|
I will add some tests once accepted. |
| return fmt.Errorf("failed to read plugin config: %v", err) | ||
| } | ||
|
|
||
| // initi generic plugin initalizer |
| if err != nil { | ||
| return err | ||
| } | ||
| sharedInformers := informers.NewSharedInformerFactory(clientset, restConfig.Timeout) |
There was a problem hiding this comment.
@sttts @p0lyn0mial This has made our (existing) information flow problem really obvious. To work well, we need the ShareInformers to be shared for an entire API server. They're based on the loopback config, which is set as part of the servingOptions.ApplyTo. What if we had that ApplyTo actually construct the sharedInformers there and used the from outside like we do with the LoopbackClientConfig?
There was a problem hiding this comment.
oh, I didn't realise it's an issue. I think this is due to maintaining cache state in informers - right ?
That means we would have to extend Config structure ? (add SharedInformers) ?
There was a problem hiding this comment.
oh, I didn't realise it's an issue. I think this is due to maintaining cache state in informers - right ?
That means we would have to extend Config structure ? (add SharedInformers) ?
Yeah, it would. In the kube-apiserver we actually use informers (slightly different ones, but I'd expect most to use externals) to wire up our authenticator and authorizer: https://github.com/kubernetes/kubernetes/blob/master/cmd/kube-apiserver/app/server.go#L347-L360 .
We perform similar work in the kube-aggregator: https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go#L111 and its going to come up again in kube-apiextensions-server.
There was a problem hiding this comment.
okay, I will add "external" SharedInformers to Config.
There was a problem hiding this comment.
I don't like this. Creating the loopback client in SecureServingOptions.ApplyTo is already too early IMO because of the effective listen port (which is set only when the server actually starts to listen). With shared imformers we would manifest this even further.
There was a problem hiding this comment.
I don't like this. Creating the loopback client in SecureServingOptions.ApplyTo is already too early IMO because of the effective listen port (which is set only when the server actually starts to listen). With shared imformers we would manifest this even further.
This pull reflects the information flow we have. We use the client to create the informer to create the authentication, authorization, and admission filters which are used to create the server which is used to listen. I don't think I see that flow as likely change and I'd like to avoid having multiple informers floating around.
There was a problem hiding this comment.
@sttts
We would create SharedInformers somewhere here https://github.com/kubernetes/kubernetes/blob/master/cmd/kube-apiserver/app/server.go#L294
Normally kube-apiserver creates them a few lines later
https://github.com/kubernetes/kubernetes/blob/master/cmd/kube-apiserver/app/server.go#L334
We should be safe to do that in SecureServingOptions.ApplyTo what do you think ?
| Control string | ||
| ControlConfigFile string | ||
| Plugins *admission.Plugins | ||
| PluginsNames []string |
| Plugins: plugins, | ||
| Control: "AlwaysAdmit", | ||
| Plugins: plugins, | ||
| PluginsNames: []string{}, |
There was a problem hiding this comment.
seems a little odd to specify both of these and not have names in sync with plugins
There was a problem hiding this comment.
seems a little odd to specify both of these and not have names in sync with plugins
I don't understand your comment. One is a registry of all available admission plugins. The other is an ordered list of the chain you want. They are not equivalent.
There was a problem hiding this comment.
ah, I misread, I thought the names got initialized into the plugins
|
@p0lyn0mial I have created a PR against your branch: p0lyn0mial#1. We have wiring for the internal shared informers already. I have removed your new GenericConfig field and put the new external informers next to the internal informer code. If we think this wiring is ugly, let's do a cleanup as a follow-up. But at least now it is uniform (-ly ugly). |
|
@sttts I described the flow of information like this:
Can you describe an alternative that doesn't involve mutatable authentication, authorization, and admission? You pull doesn't resolve the problem and simply ensures that every API server built will have to wire these pieces together in order to get core, non-optional admission (namespace enforcement) working. That seems burdensome and a likely point of failure. |
|
@deads2k I will look into this cycle issue in a follow-up. I don't want to block this PR because of that. |
|
|
||
| // ApplyTo adds the admission chain to the server configuration | ||
| // the method lazily initializes a generic plugin that is appended to the list of pluginInitializers | ||
| func (a *AdmissionOptions) ApplyTo(authz authorizer.Authorizer, restConfig *rest.Config, serverCfg *server.Config, sharedInformers informers.SharedInformerFactory, pluginInitializers ...admission.PluginInitializer) error { |
There was a problem hiding this comment.
I think you can can get the authorizer, loopbackconfig, and informers from the server.Config, so they don't need separate args.
Indicate what is used from the genericconfig in the method documentation.
| } | ||
|
|
||
| // init generic plugin initalizer | ||
| if a.genericPluginInitializer == nil { |
There was a problem hiding this comment.
Since you're re-using the informers from the config, this block no longer needs to be conditional.
There was a problem hiding this comment.
I think we can go even one step further. genericPluginInitializer doesn't have to be a member variable.
There was a problem hiding this comment.
I think we can go even one step further. genericPluginInitializer doesn't have to be a member variable.
true
| // It comes after all filters and the API handling | ||
| FallThroughHandler *mux.PathRecorderMux | ||
| // SharedInformerFactory provides shared informers for resources | ||
| SharedInformerFactory informers.SharedInformerFactory |
There was a problem hiding this comment.
You need to add a poststarthook to call .Start on these about here: https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apiserver/pkg/server/config.go#L407 . Maybe a name like with something like generic-apiserver-start-informers
There was a problem hiding this comment.
so basically everything that needs to be run in a separate goroutine goes through hooks ?
There was a problem hiding this comment.
Most things. It makes them inspectable. In this case, it makes the lifecycle of the informer factory the responsibility of the library.
|
@p0lyn0mial a few comments. Go ahead and squash into one or two commits. |
319f1d3 to
4818f16
Compare
Automatic merge from submit-queue plumb stopch to post start hook index since many of them are starting go funcs Many post-start hooks require a stop channel to properly terminate their go funcs. @p0lyn0mial I think you need this for #45355 ptal. @ncdc per request @sttts can you review too since Andy is out?
There was a problem hiding this comment.
I think we can tolerate this being nil to start. It's a little weird, but I'm more interested in getting it wired than chasing an initialization flow through federation unit tests.
There was a problem hiding this comment.
alright, that simplifies a lot.
There was a problem hiding this comment.
Add the nil check here so we don't register the post start hook at all if its missing.
ApplyTo adds the admission chain to the server configuration the method lazily initializes a generic plugin that is appended to the list of pluginInitializers. apiserver.Config will hold an instance of SharedInformerFactory to ensure we only have once instance. The field will be initialized in apisever.SecureServingOptions
4818f16 to
8cea69a
Compare
| defer etcdserver.Terminate(t) | ||
|
|
||
| assert.NotNil(config.SwaggerConfig) | ||
| // assert.NotNil(config.OpenAPIConfig) |
There was a problem hiding this comment.
I removed commented lines. Tried to uncomment but the test failed.
|
squashed and ready to be merged. |
|
@k8s-bot ok to test |
|
Looks like hack/update-bazel.sh and hack/update-staging-godeps.sh (no idea why that one changed...) |
|
/lgtm |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: deads2k, p0lyn0mial DetailsNeeds approval from an approver in each of these OWNERS Files:
You can indicate your approval by writing |
|
Automatic merge from submit-queue (batch tested with PRs 45408, 45355, 45528) |
|
@p0lyn0mial PR needs rebase |
What this PR does / why we need it:
This PR adds ApplyTo method to AdmissionOptions struct. The method creates and initialises admission control to the server configuration.
Release note: