proposal for dynamic admission controller configuration
This commit is contained in:
parent
2a9aa2e5b0
commit
b81ec0a141
|
@ -0,0 +1,202 @@
|
||||||
|
# Dynamic admission control configuration
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
[#132](https://github.com/kubernetes/community/pull/132) proposed making
|
||||||
|
admission control extensible. In the proposal, the `initializer admission
|
||||||
|
controller` and the `generic webhook admission controller` are the two
|
||||||
|
controllers that set default initializers and external admission hooks for
|
||||||
|
resources newly created. These two admission controllers are in the same binary
|
||||||
|
as the apiserver. This [section](https://github.com/smarterclayton/community/blob/be132e88f7597ab3927b788a3de6d5ab6de673d2/contributors/design-proposals/admission_control_extension.md#dynamic-configuration)
|
||||||
|
of #132 gave a preliminary design of the dynamic configuration of the list of
|
||||||
|
the default admission controls. This document hashes out the implementation
|
||||||
|
details.
|
||||||
|
|
||||||
|
## Goals
|
||||||
|
|
||||||
|
* Admins are able to predict what initializers/webhooks will be applied to newly
|
||||||
|
created objects.
|
||||||
|
|
||||||
|
* Do not block the entire cluster if the intializers/webhooks are not ready
|
||||||
|
after registration.
|
||||||
|
|
||||||
|
## Specification
|
||||||
|
|
||||||
|
We assume initializers could be "fail open". We need to update #132 if this is
|
||||||
|
accepted.
|
||||||
|
|
||||||
|
The schema is copied from
|
||||||
|
[#132](https://github.com/kubernetes/community/pull/132) with a few
|
||||||
|
modifications.
|
||||||
|
|
||||||
|
```golang
|
||||||
|
type AdmissionControlConfiguration struct {
|
||||||
|
TypeMeta // although this object could simply be serialized like ComponentConfig
|
||||||
|
|
||||||
|
// ResourceInitializers is a list of resources and their default initializers
|
||||||
|
ResourceInitializers []ResourceDefaultInitializer
|
||||||
|
|
||||||
|
ExternalAdmissionHooks []ExternalAdmissionHook
|
||||||
|
}
|
||||||
|
|
||||||
|
// Because the order of initializers matters, and each resource might need
|
||||||
|
// differnt order, the ResourceDefaultInitializers are indexed by Resource.
|
||||||
|
type ResourceDefaultInitializer struct {
|
||||||
|
// Resource identifies the type of resource to be initialized that should be
|
||||||
|
// initialized
|
||||||
|
Resource GroupResource
|
||||||
|
// Initializers are the default names that will be registered to this resource
|
||||||
|
Initializers []Initializer
|
||||||
|
}
|
||||||
|
|
||||||
|
type Initializer struct {
|
||||||
|
// Name is the string that will be registered to the resource that needs
|
||||||
|
// initialization.
|
||||||
|
Name string
|
||||||
|
|
||||||
|
// **Optional for alpha implement**
|
||||||
|
// FailurePolicy defines what happens if there is no initializer controller
|
||||||
|
// takes action. Allowed values are Ignore, or Fail. If "Ignore" is set,
|
||||||
|
// apiserver removes initilizer from the initializers list of the resource
|
||||||
|
// if the timeout is reached; If "Fail" is set, apiserver returns timeout
|
||||||
|
// error if the timeout is reached.
|
||||||
|
FailurePolicy FailurePolicyType
|
||||||
|
|
||||||
|
// **Optional for alpha implement**
|
||||||
|
// If timeout is reached, the intializer is removed from the resource's
|
||||||
|
// initializer list by the apiserver.
|
||||||
|
// Default to XXX seconds.
|
||||||
|
Timeout *int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExternalAdmissionHook struct {
|
||||||
|
// Operations is the list of operations this hook will be invoked on - Create, Update, or *
|
||||||
|
// for all operations. Defaults to '*'.
|
||||||
|
Operations []string
|
||||||
|
// Resources are the resources this hook should be invoked on. '*' is all resources.
|
||||||
|
Resources []string
|
||||||
|
// Subresources are the list of subresources this hook should be invoked on. '*' is all resources.
|
||||||
|
Subresources []string
|
||||||
|
|
||||||
|
// ClientConfig defines how to talk to the hook.
|
||||||
|
ClientConfig AdmissionHookClientConfig
|
||||||
|
|
||||||
|
// FailurePolicy defines how unrecognized errors from the admission endpoint are handled -
|
||||||
|
// allowed values are Ignore, Retry, Fail. Default value is Fail
|
||||||
|
FailurePolicy FailurePolicyType
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdmissionHookClientConfig contains the information to make a TLS
|
||||||
|
// connection with the webhook
|
||||||
|
// **very similar to the schema of kubeconfig**
|
||||||
|
type AdmissionHookClientConfig struct {
|
||||||
|
// Address of the external admission hook, could be a host string,
|
||||||
|
// a host:port pair, or a URL.
|
||||||
|
Address string
|
||||||
|
// ClientCertificate is the path to a client cert file for TLS.
|
||||||
|
ClientCertificate string
|
||||||
|
// ClientCertificateData contains PEM-encoded data from a client cert file
|
||||||
|
for TLS. Overrides ClientCertificate
|
||||||
|
ClientCertificateData []byte
|
||||||
|
// ClientKey is the path to a client key file for TLS.
|
||||||
|
ClientKey string
|
||||||
|
// ClientKeyData contains PEM-encoded data from a client key file for TLS. Overrides ClientKey
|
||||||
|
ClientKeyData []byte
|
||||||
|
// CertificateAuthority is the path to a cert file for the certificate authority.
|
||||||
|
CertificateAuthority string
|
||||||
|
// CertificateAuthorityData contains PEM-encoded certificate authority certificates. Overrides CertificateAuthority
|
||||||
|
CertificateAuthorityData []byte
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Synchronization of AdmissionControlConfiguration (**optional for alpha implement**)
|
||||||
|
|
||||||
|
If the `initializer admission controller` and the `generic webhook admission
|
||||||
|
controller` watch the `AdmissionControlConfiguration` and act upon deltas, their
|
||||||
|
cached version of the configuration might be arbitrarily delayed. This makes it
|
||||||
|
impossible to predicate what initializer/hooks will be applied to newly created
|
||||||
|
objects.
|
||||||
|
|
||||||
|
We considered a few ways to make the behavior of the `initializer admission
|
||||||
|
controller` and the `generic webhook admission controller` predictable.
|
||||||
|
|
||||||
|
(I prefer #2. #1 is inefficient, #3 requires complex schema and is not intuitive)
|
||||||
|
|
||||||
|
#### 1. Always do consistent read
|
||||||
|
|
||||||
|
The `initializer admission controller` and the `generic webhook admission
|
||||||
|
controller` always do consistent read of the `AdmissionControlConfiguration`
|
||||||
|
before applying the configuration to the incoming objects. This adds latency to
|
||||||
|
every CREATE request. Because the two admission controllers are in the same
|
||||||
|
process as the apiserver, the latency mainly consists of the consistent read
|
||||||
|
latency of the backend storage (etcd), and the proto unmarshalling.
|
||||||
|
|
||||||
|
#### 2. Optimized version of #1, do consistent read of a smaller object
|
||||||
|
|
||||||
|
Instead of having the two controllers do consistent read of the entire
|
||||||
|
`AdmissionControlConfiguration` object, we let the registry store the
|
||||||
|
resourceVersion of the `AdmissionControlConfiguration` (perhaps in a configMap),
|
||||||
|
and let the two controllers always do consistent read of the resourceVersion and
|
||||||
|
only read the entire `AdmissionControlConfiguration` if the local version is
|
||||||
|
lower than the stored one.
|
||||||
|
|
||||||
|
#### 3. Don't synchronize, but report what is the cached version
|
||||||
|
|
||||||
|
The main goal is *NOT* to always apply the latest
|
||||||
|
`AdmissionControlConfiguration`, but to make it predictable what
|
||||||
|
initializers/hooks will be applied. If we introduce the
|
||||||
|
`generation/observedGeneration` concept to the `AdmissionControlConfiguration`,
|
||||||
|
then a human (e.g., a cluster admin) can compare the generation with the
|
||||||
|
observedGeneration and predict if all the initializer/hooks listed in the
|
||||||
|
`AdmissionControlConfiguration` will be applied.
|
||||||
|
|
||||||
|
In the HA setup, the `observedGeneration` reported by of every apiserver's
|
||||||
|
`initializer admission controller` and `generic webhook admission controller`
|
||||||
|
are different, so the API needs to record multiple `observedGeneration`.
|
||||||
|
|
||||||
|
A tentative schema:
|
||||||
|
|
||||||
|
```golang
|
||||||
|
Type AdmissionControlConfiguration struct {
|
||||||
|
...
|
||||||
|
// Generation is set by the registry
|
||||||
|
Geneartion int64
|
||||||
|
// ObserverdGenerations is set by `initializer admission controller` and
|
||||||
|
// `generic webhook admission controller` in each apiserver.
|
||||||
|
ObserverdGenerations []ObservedGenerationByServer
|
||||||
|
}
|
||||||
|
|
||||||
|
type ObservedGenerationByServer struct {
|
||||||
|
// Address of this server
|
||||||
|
// This can be a hostname, hostname:port, IP or IP:port
|
||||||
|
Server string
|
||||||
|
// The entity that reports the observedGeneration
|
||||||
|
AdmissionController AdmissionControllerType
|
||||||
|
ObservedGeneration int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type AdmissionControllerType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
InitializerAdmissionController AdmissionControllerType = "initializer admission controller"
|
||||||
|
GenericWebhookAdmissionController AdmissionControllerType = "generic webhook admission controller"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## What if an initializer controller/webhook is not ready after registered? (**optional for alpha implement**)
|
||||||
|
|
||||||
|
This will block the entire cluster. We have a few options:
|
||||||
|
|
||||||
|
1. only allow initializers/webhooks to be created as "fail open". They can
|
||||||
|
upgrade themselves to "fail closed" via the normal Update operation. A human
|
||||||
|
can also update them to "fail closed" later.
|
||||||
|
|
||||||
|
2. less preferred: add readiness check to initializer and webhooks, `initializer
|
||||||
|
admission controller` and `generic webhook admission controller` only apply
|
||||||
|
those have passed readiness check. Specifically, we add `readiness` fields to
|
||||||
|
`AdmissionControllerConfiguration`; then we either create yet another
|
||||||
|
controller to probe for the readiness and update the
|
||||||
|
`AdmissionControllerConfiguration`, or ask each initializer/webhook to update
|
||||||
|
their readiness in the `AdmissionControllerConfigure`. The former is complex.
|
||||||
|
The latter is essentially the same as the first approach, except that we need
|
||||||
|
to introduce the additional concept of "readiness".
|
Loading…
Reference in New Issue