Kubernetes admission webhooks的深入解析,你能详细解释一下吗?
- 内容介绍
- 文章标签
- 相关推荐
本文共计2727个文字,预计阅读时间需要11分钟。
背景:admission controllers 的特点:- 可定制性:准入功能可根据不同场景进行针对性调整。- 可预防性:准入控制器可以预防问题发生。- 可扩展性:在 Kubernetes 中可扩展使用。
BACKGROUNDadmission controllers的特点:
- 可定制性:准入功能可针对不同的场景进行调整。
- 可预防性:审计则是为了检测问题,而准入控制器可以预防问题发生
- 可扩展性:在kubernetes自有的验证机制外,增加了另外的防线,弥补了RBAC仅能对资源提供安全保证。
下图,显示了用户操作资源的流程,可以看出 admission controllers 作用是在通过身份验证资源持久化之前起到拦截作用。在准入控制器的加入会使kubernetes增加了更高级的安全功能。
这里找到一个大佬博客画的图,通过两张图可以很清晰的了解到admission webhook流程,与官方给出的不一样的地方在于,这里清楚地定位了kubernetes admission webhook 处于准入控制中,RBAC之后,push 之前。
根据官方提供的说法是
Mutating controllers may modify related objects to the requests they admit; validating controllers may not
从结构图中也可以看出,validating 是在持久化之前,而 Mutating 是在结构验证前,根据这些特性我们可以使用 Mutating 修改这个资源对象内容(如增加验证的信息),在 validating 中验证是否合法。
kubernetes中的 admission controllers 由两部分组成:
- 内置在APIServer中的准入控制器 build-in list
- 特殊的控制器;也是内置在APIServer中,但提供一些自定义的功能
- MutatingAdmission
- ValidatingAdmission
Mutating 控制器可以修改他们处理的资源对象,Validating 控制器不会。当在任何一个阶段中的任何控制器拒绝这个了请求,则会立即拒绝整个请求,并将错误返回。
admission webhook由于准入控制器是内置在 kube-apiserver 中的,这种情况下就限制了admission controller的可扩展性。在这种背景下,kubernetes提供了一种可扩展的准入控制器 extensible admission controllers,这种行为叫做动态准入控制 Dynamic Admission Control,而提供这个功能的就是 admission webhook 。
admission webhook 通俗来讲就是 HTTP 回调,通过定义一个10.0.0.1:81/validate" # 这里是外部模式
# service: # service是在cluster-in模式下
# namespace: "default"
# name: "admission-webhook"
# port: 81 # 服务的端口
# path: "/mutate" # path是对应用于验证的接口
# caBundle是提供给 admission webhook CA证书
caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle containing the CA that signed the webhook's serving certificate>...tLS0K"
admissionReviewVersions: ["v1"]
sideEffects: None
timeoutSeconds: 5 # 1-30s直接,表示请求api的超时时间
注:对于webhook,也可以引入外部的服务,并非必须部署到集群内部
对于外部服务来讲,需要 clientConfig 中的 service , 更换为 url ; 通过 url 参数可以将一个外部的服务引入
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
...
webhooks:
- name: my-webhook.example.com
clientConfig:
url: "my-webhook.example.com:9443/my-webhook-path"
...
注:这里的url规则必须准守下列形式:
scheme://host:port/path- 使用了url 时,这里不应填写集群内的服务
scheme必须是 goproxy.cn,direct RUN \ sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories && \ apk add upx && \ GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags "-s -w" -o webhook main.go && \ upx -1 webhook && \ chmod +x webhook FROM alpine AS runner WORKDIR /go/admission COPY --from=builder /admission/webhook . VOLUME ["/admission"]集群内部部署所需的资源清单
apiVersion: v1 kind: Service metadata: name: admission-webhook labels: app: admission-webhook spec: ports: - port: 81 targetPort: 81 selector: app: simple-webhook --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: simple-webhook name: simple-webhook spec: replicas: 1 selector: matchLabels: app: simple-webhook template: metadata: labels: app: simple-webhook spec: containers: - image: cylonchau/simple-webhook:v0.0.2 imagePullPolicy: IfNotPresent name: webhook command: ["./webhook"] env: - name: "TLS_CERT" value: "./tls/tls.crt" - name: "TLS_KEY" value: "./tls/tls.key" - name: NS_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.namespace ports: - containerPort: 81 volumeMounts: - name: tlsdir mountPath: /go/admission/tls readOnly: true volumes: - name: tlsdir secret: secretName: webhook --- apiVersion: admissionregistration.k8s.io/v1 kind: MutatingWebhookConfiguration metadata: name: "pod-policy.example.com" webhooks: - name: "pod-policy.example.com" rules: - apiGroups: ["apps"] # 拦截资源的Group "" 表示 core。"*" 表示所有。 apiVersions: ["v1"] # 拦截资源的版本 operations: ["CREATE"] # 什么请求下拦截 resources: ["deployments"] # 拦截什么资源 scope: "Namespaced" # 生效的范围,cluster还是namespace "*"表示没有范围限制。 clientConfig: # 我们部署的webhook服务, url: "10.0.0.1:81/mutate" # service: # service是在cluster-in模式下 # namespace: "default" # name: "admission-webhook" # port: 81 # 服务的端口 # path: "/mutate" # path是对应用于验证的接口 # caBundle是提供给 admission webhook CA证书 caBundle: Put you CA (base64 encode) in here admissionReviewVersions: ["v1"] sideEffects: None timeoutSeconds: 5 # 1-30s直接,表示请求api的超时时间 --- apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: name: "valipod-policy.example.com" webhooks: - name: "valipod-policy.example.com" rules: - apiGroups: ["apps"] # 拦截资源的Group "" 表示 core。"*" 表示所有。 apiVersions: ["v1"] # 拦截资源的版本 operations: ["CREATE"] # 什么请求下拦截 resources: ["deployments"] # 拦截什么资源 scope: "Namespaced" # 生效的范围,cluster还是namespace "*"表示没有范围限制。 clientConfig: # 我们部署的webhook服务, # service: # service是在cluster-in模式下 # namespace: "default" # name: "admission-webhook" # port: 81 # 服务的端口 # path: "/mutate" # path是对应用于验证的接口 # caBundle是提供给 admission webhook CA证书 caBundle: Put you CA (base64 encode) in here admissionReviewVersions: ["v1"] sideEffects: None timeoutSeconds: 5 # 1-30s直接,表示请求api的超时时间这里需要主义的问题证书问题
如果需要
cluster-in,那么则需要对对应webhookconfig资源配置service;如果使用的是外部部署,则需要配置对应访问地址,如:"xxxx:port/method"这两种方式的证书均需要对应的
subjectAltName,cluster-in模式 需要对应service名称,如,至少包含serviceName.NS.svc这一个域名。下面就是证书类问题的错误
Failed calling webhook, failing closed pod-policy.example.com: failed calling webhook "pod-policy.example.com": Post admission-webhook.default.svc:81/mutate?timeout=5s: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "admission-webhook-ca")相应信息问题
上面我们了解到的APIServer是去发出
v1admission.AdmissionReview也就是 Request 和 Response类型的,所以,为了更清晰的表示出问题所在,需要对响应格式中的Reason与Message配置,这也就是我们在客户端看到的报错信息。
&metav1.Status{ Code: http.StatusForbidden, Reason: func() metav1.StatusReason { return metav1.StatusReasonForbidden }(), Message: fmt.Sprintf("the resource %s couldn't to allow entry.", deploy.Kind), }通过上面的设置用户可以看到下列错误
$ kubectl apply -f nginx.yaml Error from server (Forbidden): error when creating "nginx.yaml": admission webhook "valipod-policy.example.com" denied the request: the resource Deployment couldn't to allow entry.注:必须的参数还包含,UID,allowed,这两个是必须的,上面阐述的只是对用户友好的提示信息
下面的报错就是对相应格式设置错误
Error from server (InternalError): error when creating "nginx.yaml": Internal error occurred: failed calling webhook "pod-policy.example.com": the server rejected our request for an unknown reason相应信息版本问题
相应信息也需要指定一个版本,这个与请求来的结构中拿即可
admissionResp.APIVersion = admission.APIVersion admissionResp.Kind = admission.Kind下面是没有为对应相应信息配置对应KV的值出现的报错
Error from server (InternalError): error when creating "nginx.yaml": Internal error occurred: failed calling webhook "pod-policy.example.com": expected webhook response of admission.k8s.io/v1, Kind=AdmissionReview, got /, Kind=关于patch
kubernetes中patch使用的是特定的规范,如
jsonpatchkubernetes当前唯一支持的
patchType是JSONPatch。 有关更多详细信息,请参见 JSON patch对于
jsonpatch是一个固定的类型,在go中必须定义其结构体
{ "op": "add", // 做什么操作 "path": "/spec/replicas", // 操作的路径 "value": 3 // 对应添加的key value }下面就是字符串类型设置为布尔型产生的报错
Error from server (InternalError): error when creating "nginx.yaml": Internal error occurred: v1.Deployment.ObjectMeta: v1.ObjectMeta.Annotations: ReadString: expects " or n, but found t, error found in #10 byte of ...|t/Allow":true},"crea|..., bigger context ...|tadata":{"annotations":{"nginx-deployment/Allow":true},"creationTimestamp":null,"managedFields":[{"m|..准备证书Ubuntu
touch ./demoCAindex.txt touch ./demoCA/serial touch ./demoCA/crlnumber echo 01 > ./demoCA/serial mkdir ./demoCA/newcerts openssl genrsa -out cakey.pem 2048 openssl req -new \ -x509 \ -key cakey.pem \ -out cacert.pem \ -days 3650 \ -subj "/CN=admission webhook ca" openssl genrsa -out tls.key 2048 openssl req -new \ -key tls.key \ -subj "/CN=admission webhook client" \ -reqexts webhook \ -config <(cat /etc/ssl/openssl.cnf \ <(printf "[webhook]\nsubjectAltName=DNS: admission-webhook, DNS: admission-webhook.default.svc, DNS: admission-webhook.default.svc.cluster.local, IP:10.0.0.1, IP:10.0.0.4")) \ -out tls.csr sed -i 's/= match/= optional/g' /etc/ssl/openssl.cnf openssl ca \ -in tls.csr \ -cert cacert.pem \ -keyfile cakey.pem \ -out tls.crt \ -days 300 \ -extensions webhook \ -extfile <(cat /etc/ssl/openssl.cnf \ <(printf "[webhook]\nsubjectAltName=DNS: admission-webhook, DNS: admission-webhook.default.svc, DNS: admission-webhook.default.svc.cluster.local, IP:10.0.0.1, IP:10.0.0.4"))CentOS
touch /etc/pki/CA/index.txt touch /etc/pki/CA/serial # 下一个要颁发的编号 16进制 touch /etc/pki/CA/crlnumber echo 01 > /etc/pki/CA/serial openssl req -new \ -x509 \ -key cakey.pem \ -out cacert.pem \ -days 3650 \ -subj "/CN=admission webhook ca" openssl genrsa -out tls.key 2048 openssl req -new \ -key tls.key \ -subj "/CN=admission webhook client" \ -reqexts webhook \ -config <(cat /etc/pki/tls/openssl.cnf \ <(printf "[webhook]\nsubjectAltName=DNS: admission-webhook, DNS: admission-webhook.default.svc, DNS: admission-webhook.default.svc.cluster.local, IP:10.0.0.1, IP:10.0.0.4")) \ -out tls.csr sed -i 's/= match/= optional/g' /etc/ssl/openssl.cnf openssl ca \ -in tls.csr \ -cert cacert.pem \ -keyfile cakey.pem \ -out tls.crt \ -days 300 \ -extensions webhook \ -extfile <(cat /etc/pki/tls/openssl.cnf \ <(printf "[webhook]\nsubjectAltName=DNS: admission-webhook, DNS: admission-webhook.default.svc, DNS: admission-webhook.default.svc.cluster.local, IP:10.0.0.1, IP:10.0.0.4"))通过部署测试结果可以看到我们自己注入的 annotation
nginx-deployment/Allow: true,在该示例中,仅为演示过程,而不是真的策略,实际环境中可以根据情况进行定制自己的策略。结果可以看出,当在
mutating中不通过,即缺少对应的 annotation 标签 , 则validating会不允许准入
$ kubectl describe deploy nginx-deployment Name: nginx-deployment Namespace: default CreationTimestamp: Mon, 11 Jul 2022 20:25:16 +0800 Labels: <none> Annotations: deployment.kubernetes.io/revision: 1 nginx-deployment/Allow: true Selector: app=nginx Replicas: 1 desired | 1 updated | 1 total | 1 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=nginx Containers: nginx: Image: nginx:1.14.2Reference
extensible admission controllers
K8S client-go Patch example
admission controllers response
a guide to kubernetes admission controllers
本文共计2727个文字,预计阅读时间需要11分钟。
背景:admission controllers 的特点:- 可定制性:准入功能可根据不同场景进行针对性调整。- 可预防性:准入控制器可以预防问题发生。- 可扩展性:在 Kubernetes 中可扩展使用。
BACKGROUNDadmission controllers的特点:
- 可定制性:准入功能可针对不同的场景进行调整。
- 可预防性:审计则是为了检测问题,而准入控制器可以预防问题发生
- 可扩展性:在kubernetes自有的验证机制外,增加了另外的防线,弥补了RBAC仅能对资源提供安全保证。
下图,显示了用户操作资源的流程,可以看出 admission controllers 作用是在通过身份验证资源持久化之前起到拦截作用。在准入控制器的加入会使kubernetes增加了更高级的安全功能。
这里找到一个大佬博客画的图,通过两张图可以很清晰的了解到admission webhook流程,与官方给出的不一样的地方在于,这里清楚地定位了kubernetes admission webhook 处于准入控制中,RBAC之后,push 之前。
根据官方提供的说法是
Mutating controllers may modify related objects to the requests they admit; validating controllers may not
从结构图中也可以看出,validating 是在持久化之前,而 Mutating 是在结构验证前,根据这些特性我们可以使用 Mutating 修改这个资源对象内容(如增加验证的信息),在 validating 中验证是否合法。
kubernetes中的 admission controllers 由两部分组成:
- 内置在APIServer中的准入控制器 build-in list
- 特殊的控制器;也是内置在APIServer中,但提供一些自定义的功能
- MutatingAdmission
- ValidatingAdmission
Mutating 控制器可以修改他们处理的资源对象,Validating 控制器不会。当在任何一个阶段中的任何控制器拒绝这个了请求,则会立即拒绝整个请求,并将错误返回。
admission webhook由于准入控制器是内置在 kube-apiserver 中的,这种情况下就限制了admission controller的可扩展性。在这种背景下,kubernetes提供了一种可扩展的准入控制器 extensible admission controllers,这种行为叫做动态准入控制 Dynamic Admission Control,而提供这个功能的就是 admission webhook 。
admission webhook 通俗来讲就是 HTTP 回调,通过定义一个10.0.0.1:81/validate" # 这里是外部模式
# service: # service是在cluster-in模式下
# namespace: "default"
# name: "admission-webhook"
# port: 81 # 服务的端口
# path: "/mutate" # path是对应用于验证的接口
# caBundle是提供给 admission webhook CA证书
caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle containing the CA that signed the webhook's serving certificate>...tLS0K"
admissionReviewVersions: ["v1"]
sideEffects: None
timeoutSeconds: 5 # 1-30s直接,表示请求api的超时时间
注:对于webhook,也可以引入外部的服务,并非必须部署到集群内部
对于外部服务来讲,需要 clientConfig 中的 service , 更换为 url ; 通过 url 参数可以将一个外部的服务引入
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
...
webhooks:
- name: my-webhook.example.com
clientConfig:
url: "my-webhook.example.com:9443/my-webhook-path"
...
注:这里的url规则必须准守下列形式:
scheme://host:port/path- 使用了url 时,这里不应填写集群内的服务
scheme必须是 goproxy.cn,direct RUN \ sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories && \ apk add upx && \ GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags "-s -w" -o webhook main.go && \ upx -1 webhook && \ chmod +x webhook FROM alpine AS runner WORKDIR /go/admission COPY --from=builder /admission/webhook . VOLUME ["/admission"]集群内部部署所需的资源清单
apiVersion: v1 kind: Service metadata: name: admission-webhook labels: app: admission-webhook spec: ports: - port: 81 targetPort: 81 selector: app: simple-webhook --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: simple-webhook name: simple-webhook spec: replicas: 1 selector: matchLabels: app: simple-webhook template: metadata: labels: app: simple-webhook spec: containers: - image: cylonchau/simple-webhook:v0.0.2 imagePullPolicy: IfNotPresent name: webhook command: ["./webhook"] env: - name: "TLS_CERT" value: "./tls/tls.crt" - name: "TLS_KEY" value: "./tls/tls.key" - name: NS_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.namespace ports: - containerPort: 81 volumeMounts: - name: tlsdir mountPath: /go/admission/tls readOnly: true volumes: - name: tlsdir secret: secretName: webhook --- apiVersion: admissionregistration.k8s.io/v1 kind: MutatingWebhookConfiguration metadata: name: "pod-policy.example.com" webhooks: - name: "pod-policy.example.com" rules: - apiGroups: ["apps"] # 拦截资源的Group "" 表示 core。"*" 表示所有。 apiVersions: ["v1"] # 拦截资源的版本 operations: ["CREATE"] # 什么请求下拦截 resources: ["deployments"] # 拦截什么资源 scope: "Namespaced" # 生效的范围,cluster还是namespace "*"表示没有范围限制。 clientConfig: # 我们部署的webhook服务, url: "10.0.0.1:81/mutate" # service: # service是在cluster-in模式下 # namespace: "default" # name: "admission-webhook" # port: 81 # 服务的端口 # path: "/mutate" # path是对应用于验证的接口 # caBundle是提供给 admission webhook CA证书 caBundle: Put you CA (base64 encode) in here admissionReviewVersions: ["v1"] sideEffects: None timeoutSeconds: 5 # 1-30s直接,表示请求api的超时时间 --- apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: name: "valipod-policy.example.com" webhooks: - name: "valipod-policy.example.com" rules: - apiGroups: ["apps"] # 拦截资源的Group "" 表示 core。"*" 表示所有。 apiVersions: ["v1"] # 拦截资源的版本 operations: ["CREATE"] # 什么请求下拦截 resources: ["deployments"] # 拦截什么资源 scope: "Namespaced" # 生效的范围,cluster还是namespace "*"表示没有范围限制。 clientConfig: # 我们部署的webhook服务, # service: # service是在cluster-in模式下 # namespace: "default" # name: "admission-webhook" # port: 81 # 服务的端口 # path: "/mutate" # path是对应用于验证的接口 # caBundle是提供给 admission webhook CA证书 caBundle: Put you CA (base64 encode) in here admissionReviewVersions: ["v1"] sideEffects: None timeoutSeconds: 5 # 1-30s直接,表示请求api的超时时间这里需要主义的问题证书问题
如果需要
cluster-in,那么则需要对对应webhookconfig资源配置service;如果使用的是外部部署,则需要配置对应访问地址,如:"xxxx:port/method"这两种方式的证书均需要对应的
subjectAltName,cluster-in模式 需要对应service名称,如,至少包含serviceName.NS.svc这一个域名。下面就是证书类问题的错误
Failed calling webhook, failing closed pod-policy.example.com: failed calling webhook "pod-policy.example.com": Post admission-webhook.default.svc:81/mutate?timeout=5s: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "admission-webhook-ca")相应信息问题
上面我们了解到的APIServer是去发出
v1admission.AdmissionReview也就是 Request 和 Response类型的,所以,为了更清晰的表示出问题所在,需要对响应格式中的Reason与Message配置,这也就是我们在客户端看到的报错信息。
&metav1.Status{ Code: http.StatusForbidden, Reason: func() metav1.StatusReason { return metav1.StatusReasonForbidden }(), Message: fmt.Sprintf("the resource %s couldn't to allow entry.", deploy.Kind), }通过上面的设置用户可以看到下列错误
$ kubectl apply -f nginx.yaml Error from server (Forbidden): error when creating "nginx.yaml": admission webhook "valipod-policy.example.com" denied the request: the resource Deployment couldn't to allow entry.注:必须的参数还包含,UID,allowed,这两个是必须的,上面阐述的只是对用户友好的提示信息
下面的报错就是对相应格式设置错误
Error from server (InternalError): error when creating "nginx.yaml": Internal error occurred: failed calling webhook "pod-policy.example.com": the server rejected our request for an unknown reason相应信息版本问题
相应信息也需要指定一个版本,这个与请求来的结构中拿即可
admissionResp.APIVersion = admission.APIVersion admissionResp.Kind = admission.Kind下面是没有为对应相应信息配置对应KV的值出现的报错
Error from server (InternalError): error when creating "nginx.yaml": Internal error occurred: failed calling webhook "pod-policy.example.com": expected webhook response of admission.k8s.io/v1, Kind=AdmissionReview, got /, Kind=关于patch
kubernetes中patch使用的是特定的规范,如
jsonpatchkubernetes当前唯一支持的
patchType是JSONPatch。 有关更多详细信息,请参见 JSON patch对于
jsonpatch是一个固定的类型,在go中必须定义其结构体
{ "op": "add", // 做什么操作 "path": "/spec/replicas", // 操作的路径 "value": 3 // 对应添加的key value }下面就是字符串类型设置为布尔型产生的报错
Error from server (InternalError): error when creating "nginx.yaml": Internal error occurred: v1.Deployment.ObjectMeta: v1.ObjectMeta.Annotations: ReadString: expects " or n, but found t, error found in #10 byte of ...|t/Allow":true},"crea|..., bigger context ...|tadata":{"annotations":{"nginx-deployment/Allow":true},"creationTimestamp":null,"managedFields":[{"m|..准备证书Ubuntu
touch ./demoCAindex.txt touch ./demoCA/serial touch ./demoCA/crlnumber echo 01 > ./demoCA/serial mkdir ./demoCA/newcerts openssl genrsa -out cakey.pem 2048 openssl req -new \ -x509 \ -key cakey.pem \ -out cacert.pem \ -days 3650 \ -subj "/CN=admission webhook ca" openssl genrsa -out tls.key 2048 openssl req -new \ -key tls.key \ -subj "/CN=admission webhook client" \ -reqexts webhook \ -config <(cat /etc/ssl/openssl.cnf \ <(printf "[webhook]\nsubjectAltName=DNS: admission-webhook, DNS: admission-webhook.default.svc, DNS: admission-webhook.default.svc.cluster.local, IP:10.0.0.1, IP:10.0.0.4")) \ -out tls.csr sed -i 's/= match/= optional/g' /etc/ssl/openssl.cnf openssl ca \ -in tls.csr \ -cert cacert.pem \ -keyfile cakey.pem \ -out tls.crt \ -days 300 \ -extensions webhook \ -extfile <(cat /etc/ssl/openssl.cnf \ <(printf "[webhook]\nsubjectAltName=DNS: admission-webhook, DNS: admission-webhook.default.svc, DNS: admission-webhook.default.svc.cluster.local, IP:10.0.0.1, IP:10.0.0.4"))CentOS
touch /etc/pki/CA/index.txt touch /etc/pki/CA/serial # 下一个要颁发的编号 16进制 touch /etc/pki/CA/crlnumber echo 01 > /etc/pki/CA/serial openssl req -new \ -x509 \ -key cakey.pem \ -out cacert.pem \ -days 3650 \ -subj "/CN=admission webhook ca" openssl genrsa -out tls.key 2048 openssl req -new \ -key tls.key \ -subj "/CN=admission webhook client" \ -reqexts webhook \ -config <(cat /etc/pki/tls/openssl.cnf \ <(printf "[webhook]\nsubjectAltName=DNS: admission-webhook, DNS: admission-webhook.default.svc, DNS: admission-webhook.default.svc.cluster.local, IP:10.0.0.1, IP:10.0.0.4")) \ -out tls.csr sed -i 's/= match/= optional/g' /etc/ssl/openssl.cnf openssl ca \ -in tls.csr \ -cert cacert.pem \ -keyfile cakey.pem \ -out tls.crt \ -days 300 \ -extensions webhook \ -extfile <(cat /etc/pki/tls/openssl.cnf \ <(printf "[webhook]\nsubjectAltName=DNS: admission-webhook, DNS: admission-webhook.default.svc, DNS: admission-webhook.default.svc.cluster.local, IP:10.0.0.1, IP:10.0.0.4"))通过部署测试结果可以看到我们自己注入的 annotation
nginx-deployment/Allow: true,在该示例中,仅为演示过程,而不是真的策略,实际环境中可以根据情况进行定制自己的策略。结果可以看出,当在
mutating中不通过,即缺少对应的 annotation 标签 , 则validating会不允许准入
$ kubectl describe deploy nginx-deployment Name: nginx-deployment Namespace: default CreationTimestamp: Mon, 11 Jul 2022 20:25:16 +0800 Labels: <none> Annotations: deployment.kubernetes.io/revision: 1 nginx-deployment/Allow: true Selector: app=nginx Replicas: 1 desired | 1 updated | 1 total | 1 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=nginx Containers: nginx: Image: nginx:1.14.2Reference
extensible admission controllers
K8S client-go Patch example
admission controllers response
a guide to kubernetes admission controllers

