summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChao Xu <xuchao@google.com>2017-05-02 13:29:30 -0700
committerChao Xu <xuchao@google.com>2017-05-09 17:33:10 -0700
commitb81ec0a141338dd6e21d43bda422e67a91c1442e (patch)
tree0c709ccc4d355383fdb48b0a05209d145d443ded
parent2a9aa2e5b035026c0347112304f02ae4feeb132b (diff)
proposal for dynamic admission controller configuration
-rw-r--r--contributors/design-proposals/dynamic-admission-control-configuration.md202
1 files changed, 202 insertions, 0 deletions
diff --git a/contributors/design-proposals/dynamic-admission-control-configuration.md b/contributors/design-proposals/dynamic-admission-control-configuration.md
new file mode 100644
index 00000000..bb9b231e
--- /dev/null
+++ b/contributors/design-proposals/dynamic-admission-control-configuration.md
@@ -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".