An admission controller is a piece of code that intercepts requests to the Kubernetes API server prior to persistence of the object, but after the request is authenticated and authorized. […] Admission controllers may be “validating”, “mutating”, or both. Mutating controllers may modify the objects they admit; validating controllers may not. […] If any of the controllers in either phase reject the request, the entire request is rejected immediately and an error is returned to the end-user.
大概意思就是说准入控制器是在对象持久化之前用于对 Kubernetes API Server 的请求进行拦截的代码段,在请求经过身份验证和授权之后放行通过。准入控制器可能正在validating、mutating或者都在执行,Mutating 控制器可以修改他们的处理的资源对象,Validating 控制器不会,如果任何一个阶段中的任何控制器拒绝了请求,则会立即拒绝整个请求,并将错误返回给最终的用户。
switch req.Kind.Kind { case"Deployment": var deployment appsv1.Deployment if err := json.Unmarshal(req.Object.Raw, &deployment); err != nil { glog.Errorf("Could not unmarshal raw object: %v", err) return &v1beta1.AdmissionResponse{ Result: &metav1.Status{ Message: err.Error(), }, } } resourceName, resourceNamespace, objectMeta = deployment.Name, deployment.Namespace, &deployment.ObjectMeta availableLabels = deployment.Labels case"Service": var service corev1.Service if err := json.Unmarshal(req.Object.Raw, &service); err != nil { glog.Errorf("Could not unmarshal raw object: %v", err) return &v1beta1.AdmissionResponse{ Result: &metav1.Status{ Message: err.Error(), }, } } resourceName, resourceNamespace, objectMeta = service.Name, service.Namespace, &service.ObjectMeta availableLabels = service.Labels }
if !validationRequired(ignoredNamespaces, objectMeta) { glog.Infof("Skipping validation for %s/%s due to policy check", resourceNamespace, resourceName) return &v1beta1.AdmissionResponse{ Allowed: true, } }
allowed := true var result *metav1.Status glog.Info("available labels:", availableLabels) glog.Info("required labels", requiredLabels) for _, rl := range requiredLabels { if _, ok := availableLabels[rl]; !ok { allowed = false result = &metav1.Status{ Reason: "required labels are not set", } break } }
funcadmissionRequired(ignoredList []string, admissionAnnotationKey string, metadata *metav1.ObjectMeta)bool { // skip special kubernetes system namespaces for _, namespace := range ignoredList { if metadata.Namespace == namespace { glog.Infof("Skip validation for %v for it's in special namespace:%v", metadata.Name, metadata.Namespace) returnfalse } }
switch req.Kind.Kind { case"Deployment": var deployment appsv1.Deployment if err := json.Unmarshal(req.Object.Raw, &deployment); err != nil { glog.Errorf("Could not unmarshal raw object: %v", err) return &v1beta1.AdmissionResponse{ Result: &metav1.Status{ Message: err.Error(), }, } } resourceName, resourceNamespace, objectMeta = deployment.Name, deployment.Namespace, &deployment.ObjectMeta availableLabels = deployment.Labels case"Service": var service corev1.Service if err := json.Unmarshal(req.Object.Raw, &service); err != nil { glog.Errorf("Could not unmarshal raw object: %v", err) return &v1beta1.AdmissionResponse{ Result: &metav1.Status{ Message: err.Error(), }, } } resourceName, resourceNamespace, objectMeta = service.Name, service.Namespace, &service.ObjectMeta availableLabels = service.Labels }
if !mutationRequired(ignoredNamespaces, objectMeta) { glog.Infof("Skipping validation for %s/%s due to policy check", resourceNamespace, resourceName) return &v1beta1.AdmissionResponse{ Allowed: true, } }
$ ./deployment/webhook-create-signed-cert.sh creating certs in tmpdir /var/folders/x3/wjy_1z155pdf8jg_jgpmf6kc0000gn/T/tmp.IboFfX97 Generating RSA private key, 2048 bit long modulus (2 primes) ..................+++++ ........+++++ e is 65537 (0x010001) certificatesigningrequest.certificates.k8s.io/admission-webhook-example-svc.default created NAME AGE REQUESTOR CONDITION admission-webhook-example-svc.default 1s kubernetes-admin Pending certificatesigningrequest.certificates.k8s.io/admission-webhook-example-svc.default approved secret/admission-webhook-example-certs created
$ kubectl get secret admission-webhook-example-certs NAME TYPE DATA AGE admission-webhook-example-certs Opaque 2 28s
一旦 secret 对象创建成功,我们就可以直接创建 deployment 和 service 对象。
1 2 3 4 5
$ kubectl create -f deploy/deployment.yaml deployment.apps "admission-webhook-example-deployment" created
$ kubectl create -f deploy/service.yaml service "admission-webhook-example-svc" created
$ kubectl create -f deploy/sleep.yaml Error from server (required labels are not set): error when creating "sleep.yaml": admission webhook "required-labels.houmin.cc" denied the request: required labels are not set