Kubernetes Admission Webhook Validating 与 mutating 实践

article/2025/11/11 10:24:14

Kubernetes Admission Webhook Validating 与 mutating 实践

在这里插入图片描述

文章目录

  • Kubernetes Admission Webhook Validating 与 mutating 实践
    • 1. k8s 的配置
    • 2. 构建
    • 3. 部署服务
    • 4. 测试Validating webhook
    • 5. 测试 mutating webhook

1. k8s 的配置

启用 MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook
MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook 默认是不启用的,apiserver 想调用 webhook,还得 enable 相关的能力

[root@master ~]# kubectl get pods kube-apiserver-master.lihao04.virtual -n kube-system -o yaml|grep enable- --enable-admission-plugins=NodeRestriction- --enable-bootstrap-token-auth=trueenableServiceLinks: true

因为 enable-admission-plugins 缺失 feature,我们要 enable

# 修改 /etc/kubernetes/manifests/kube-apiserver.yaml
- --enable-admission-plugins=NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook
修改配置文件后立刻生效
[root@master manifests]# kubectl get pods kube-apiserver-master.lihao04.virtual -n kube-system -o yaml|grep enable- --enable-admission-plugins=NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook- --enable-bootstrap-token-auth=trueenableServiceLinks: true
# 确实重启过
[root@master manifests]# kubectl get pod -n kube-system|grep api
kube-apiserver-master.lihao04.virtual            1/1     Running            0          54s

2. 构建

建项目文件夹:

$ mkdir admission-webhook && cd admission-webhook
# 创建go项目代码目录,设置当前目录为GOPATH路径
$ mkdir src && export GOPATH=$pwd
$ mkdir -p src/github.com/cnych/ && cd src/github.com/cnych/

进入到上面的src/github.com/cnych/目录下面,将项目代码 clone 下面:

$ git clone https://github.com/cnych/admission-webhook-example.git

我们可以看到代码根目录下面有一个build的脚本,只需要提供我们自己的 docker 镜像用户名然后直接构建即可:
注意:192.168.211.41:5000是我的镜像仓库名,方便其他节点拉取镜像

#!/bin/bashexport DOCKER_USER=192.168.211.41:5000
export GO111MODULE=on 
export GOPROXY=https://goproxy.cn
# build webhook
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o admission-webhook-example 
# build docker image
docker build --no-cache -t ${DOCKER_USER}/admission-webhook-example:v1 .
rm -rf admission-webhook-exampledocker push ${DOCKER_USER}/admission-webhook-example:v1
$ ./build

3. 部署服务

为了部署 webhook server,我们需要在我们的 Kubernetes 集群中创建一个 service 和 deployment 资源对象,部署是非常简单的,只是需要配置下服务的 TLS 配置。我们可以在代码根目录下面的 deployment 文件夹下面查看deployment.yaml文件中关于证书的配置声明,会发现从命令行参数中读取的证书和私钥文件是通过一个 secret 对象挂载进来的:

apiVersion: apps/v1
kind: Deployment
metadata:name: admission-webhook-example-deploymentlabels:app: admission-webhook-example
spec:replicas: 1selector:matchLabels:app: admission-webhook-exampletemplate:metadata:labels:app: admission-webhook-examplespec:serviceAccount: admission-webhook-example-sacontainers:- name: admission-webhook-exampleimage: 192.168.211.41:5000/admission-webhook-example:v1
#          imagePullPolicy: Alwaysargs:- -tlsCertFile=/etc/webhook/certs/cert.pem- -tlsKeyFile=/etc/webhook/certs/key.pem- -alsologtostderr- -v=4- 2>&1volumeMounts:- name: webhook-certsmountPath: /etc/webhook/certsreadOnly: truevolumes:- name: webhook-certssecret:secretName: admission-webhook-example-certs

在生产环境中,对于 TLS 证书(特别是私钥)的处理是非常重要的,我们可以使用类似于cert-manager之类的工具来自动处理 TLS 证书,或者将私钥密钥存储在Vault中,而不是直接存在 secret 资源对象中。

我们可以使用任何类型的证书,但是需要注意的是我们这里设置的 CA 证书是需要让 apiserver 能够验证的,我们这里可以重用 Istio 项目中的生成的证书签名请求脚本。通过发送请求到 apiserver,获取认证信息,然后使用获得的结果来创建需要的 secret 对象。

首先,运行该脚本检查 secret 对象中是否有证书和私钥信息:

$ ./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 对象。

$ kubectl create serviceaccount admission-webhook-example-sa
$ kubectl create -f deployment/deployment.yaml
deployment.apps "admission-webhook-example-deployment" created$ kubectl create -f deployment/service.yaml
service "admission-webhook-example-svc" created

在我们的 webhook 服务运行起来了,它可以接收来自 apiserver 的请求。但是我们还需要在 kubernetes 上创建一些配置资源。首先来配置 validating 这个 webhook,查看 webhook 配置,我们会注意到它里面包含一个CA_BUNDLE的占位符:

clientConfig:service:name: admission-webhook-example-svcnamespace: defaultpath: "/validate"caBundle: ${CA_BUNDLE}

CA 证书应提供给 admission webhook 配置,这样 apiserver 才可以信任 webhook server 提供的 TLS 证书。因为我们上面已经使用 Kubernetes API 签署了证书,所以我们可以使用我们的 kubeconfig 中的 CA 证书来简化操作。代码仓库中也提供了一个小脚本webhook-patch-ca-bundle.sh用来替换 CA_BUNDLE 这个占位符,

#!/bin/bashROOT=$(cd $(dirname $0)/../../; pwd)set -o errexit
set -o nounset
set -o pipefailexport CA_BUNDLE=$(kubectl config view --raw --flatten -o json | jq -r '.clusters[] | .cluster."certificate-authority-data"')if command -v envsubst >/dev/null 2>&1; thenenvsubst
elsesed -e "s|\${CA_BUNDLE}|${CA_BUNDLE}|g"
fi

创建 validating webhook 之前运行该命令即可:

$ cat ./deployment/validatingwebhook.yaml | ./deployment/webhook-patch-ca-bundle.sh > ./deployment/validatingwebhook-ca-bundle.yaml$ cat deployment/validatingwebhook-ca-bundle.yaml 
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingWebhookConfiguration
metadata:name: validation-webhook-example-cfglabels:app: admission-webhook-example
webhooks:- name: required-labels.qikqiak.comclientConfig:service:name: admission-webhook-example-svcnamespace: defaultpath: "/validate"caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1ekNDQWMrZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeE1ERXdOekE0TXpJd05Wb1hEVE14TURFd05UQTRNekl3TlZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTWtVClIybHV4NnVaSWRnQURPdmFvb2YwRkpsT0VkK3JOSHZ2U3hZQ3NaL3FzcGQrN2NFS0Q4TTNRNERQWmJoc2hlR2cKUWg3bEVSL2V3Mm5kL1pFSXIwZEpzakhxMjlwMkpaSzZmZ1hvYWsyV29QVWEwYTRleU50L09TOGpCQUVZdmtrVQpVVlJraVNkbk95WGpZSXgvdzJuOEdFdUZSU3ZNeWx2WExLbkppWkVTRDhTRDA0eE51aUxIRndEUG9FZEEyNGlQCnV6UXdnRjFlTFNYdnNxM1ZrZDNDM1hGL2JKUitWVW9LQjAycGhYc1o4WDRXWkp1T2ZVaHRrOXErbnUxckhhR2IKUjYyQTVoVHlhWHZkblV6T0Z4THg5Yll6MHIwdVJxakRJZ3hKZUNoMGlscFhUYUxJNmVSS29tREViSEkwTlBhTAp2QVJHMERvNTEvTmFXbzhPVFZFQ0F3RUFBYU5DTUVBd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZOTGswU0hiNjBleU9VVEwzZkVPQ2E1Njd5TkZNQTBHQ1NxR1NJYjMKRFFFQkN3VUFBNElCQVFBcSt2c3F5WldYeFZTell3SWlqU0k0Qm1IelpCRWQ0ZGM1Sm1TbDlHK3hCelRwUmJoRQpTZTNwQ3FOeGRYWk9ZZHNnZjFic1VsVFcxMm9HbmhtdVlDTFIwYmcyWDI0YWViam96OGRvNlR2WW1STWRTeTFtCkpnRGlRRDRzdXBYUkQvOVVLdHkrY0FQY3hLdDlWSm9lNE9OeWFEcGNXaWV3UEVZSUNxRWRGVklacnYvT1BZQWQKblJOQzgweVdtZk5jNFlOSFdIZG5SZ0xrS2c1eTBEMVpkR1BMOEFUcnFsVk1hNXd2d3RoZ1V6MHRWN2VFbE1xdgpjNWNid0N2QnI0U291RkgzaHcyR0NvQ0pRNkUzazkycTQ4andmNlJNWGVIMElNMSs4SjltNS9UOVl2Tk1GN1c1Cjc4MnJYZy9Pa1oyY0VETWQ0Ym1GZjFzQUt2MGNiek50SFZuMgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==rules:- operations: [ "CREATE" ]apiGroups: ["apps", ""]apiVersions: ["v1"]resources: ["deployments","services"]namespaceSelector:matchLabels:admission-webhook-example: enabled

执行完成后可以查看validatingwebhook-ca-bundle.yaml文件中的CA_BUNDLE占位符的值是否已经被替换掉了。需要注意的是 clientConfig 里面的 path 路径是/validate,因为我们代码在是将 validate 和 mutate 集成在一个服务中的。
然后就是需要配置一些 RBAC 规则,我们想在 deploymentservice 创建时拦截 API 请求,所以apiGroupsapiVersions对应的值分别为apps/v1对应 deploymentv1对应 service。对于 RBAC 的配置方法可以查看我们前面的文章:Kubernetes RBAC 详解

webhook 的最后一部分是配置一个namespaceSelector,我们可以为 webhook 工作的命名空间定义一个 selector,这个配置不是必须的,比如我们这里添加了下面的配置:

namespaceSelector:matchLabels:admission-webhook-example: enabled

则我们的 webhook 会只适用于设置了admission-webhook-example=enabled标签的 namespace, 您可以在Kubernetes参考文档中查看此资源配置的完整布局。

所以,首先需要在default这个 namespace 中添加该标签:

$ kubectl label namespace default admission-webhook-example=enabled
namespace "default" labeled

最后,创建这个 validating webhook 配置对象,这会动态地将 webhook 添加到 webhook 链上,所以一旦创建资源,就会拦截请求然后调用我们的 webhook 服务:

$ kubectl create -f deployment/validatingwebhook-ca-bundle.yaml
validatingwebhookconfiguration.admissionregistration.k8s.io "validation-webhook-example-cfg" created

4. 测试Validating webhook

现在让我们创建一个 deployment 资源来验证下是否有效,代码仓库下有一个sleep.yaml的资源清单文件,直接创建即可:

$ kubectl create -f sleep.yaml 
Error from server (required labels are not set): error when creating "sleep.yaml": admission webhook "required-labels.qikqiak.com" denied the request: required labels are not set

正常情况下创建的时候会出现上面的错误信息,然后部署另外一个sleep-with-labels.yaml的资源清单:

$ kubectl create -f deployment/sleep-with-labels.yaml
deployment.apps "sleep" created

可以看到可以正常部署,先我们将上面的 deployment 删除,然后部署另外一个sleep-no-validation.yaml资源清单,该清单中不存在所需的标签,但是配置了admission-webhook-example.qikqiak.com/validate=false这样的 annotation,正常也是可以正常创建的:

$ kubectl delete deployment sleep
$ kubectl create -f deployment/sleep-no-validation.yaml
deployment.apps "sleep" created

5. 测试 mutating webhook

首先,我们将上面的 validating webhook 删除,防止对 mutating 产生干扰,然后部署新的配置。 mutating webhookvalidating webhook 配置基本相同,但是 webook server 的路径是/mutate,同样的我们也需要先填充上CA_BUNDLE这个占位符。

$ kubectl delete validatingwebhookconfiguration validation-webhook-example-cfg
validatingwebhookconfiguration.admissionregistration.k8s.io "validation-webhook-example-cfg" deleted$ cat ./deployment/mutatingwebhook.yaml | ./deployment/webhook-patch-ca-bundle.sh > ./deployment/mutatingwebhook-ca-bundle.yaml$ kubectl create -f deployment/mutatingwebhook-ca-bundle.yaml
mutatingwebhookconfiguration.admissionregistration.k8s.io "mutating-webhook-example-cfg" created

现在我们可以再次部署上面的sleep应用程序,然后查看是否正确添加 label 标签:

$ kubectl create -f deployment/sleep.yaml
deployment.apps "sleep" created$ kubectl get  deploy sleep -o yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:annotations:admission-webhook-example.qikqiak.com/status: mutateddeployment.kubernetes.io/revision: "1"creationTimestamp: 2018-09-24T11:35:50Zgeneration: 1labels:app.kubernetes.io/component: not_availableapp.kubernetes.io/instance: not_availableapp.kubernetes.io/managed-by: not_availableapp.kubernetes.io/name: not_availableapp.kubernetes.io/part-of: not_availableapp.kubernetes.io/version: not_available
...

最后,我们重新创建 validating webhook,来一起测试。现在,尝试再次创建 sleep 应用。正常是可以创建成功的,我们可以查看下admission-controllers 的文档

准入控制分两个阶段进行,第一阶段,运行 mutating admission 控制器,第二阶段运行 validating admission控制器。

所以 mutating webhook 在第一阶段添加上缺失的 labels 标签,然后 validating webhook 在第二阶段就不会拒绝这个 deployment 了,因为标签已经存在了,用not_available设置他们的值。

$ kubectl create -f deployment/validatingwebhook-ca-bundle.yaml
validatingwebhookconfiguration.admissionregistration.k8s.io "validation-webhook-example-cfg" created$ kubectl create -f deployment/sleep.yaml
deployment.apps "sleep" created

参考:

  • https://banzaicloud.com/blog/k8s-admission-webhooks/
  • https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#what-are-they

相关阅读:

  • k8s准入控制器【1】–介绍
  • k8s准入控制器【2】–动态准入控制
  • k8s 准入控制器【3】–编写和部署准入控制器Webhook–根据标签才可创建pod
  • k8s 准入控制器【4】–编写和部署准入控制器 Webhook–以非root运行pod
  • kubeadm部署安装k8sv1.18.1详解
  • go语言入门安装与hello world

http://chatgpt.dhexx.cn/article/rqKAQl7H.shtml

相关文章

Eclipse开发工具中validating长时间卡住不动

编辑Java代码或update 新建Maven项目后,Eclipse开发工具总会停留在validating状态,超长时间的验证代码严重影响程序员心情和工作进度,那么接下来演示如何关闭该功能: 1、点击Window->点击Preferences->点击Validation&#…

validating java_如何禁用Eclipse的Validating

使用Eclipse开发项目,在加载项目、刷新项目、修改了某个代码的时候,经常出现Eclipse正在Validating的提示。项目比较大文件(js)较多的情况下,甚至出现Validating几分钟的盛况。在这几分钟内,性能较差的电脑几乎出现鼠标停滞屏幕僵…

eclipse 的validating长时间卡住不动

方法一、直接关闭 每次maven的update project之后或者是从外部导入一个文件时,总是在validating,超长时间的验证代码,尤其是动态css和JavaScript,让程序员等待久严重影响心情和工作进度,所以将其关闭或是禁用。 如何…

关于eclipse 的validating

一、关闭 每次maven的update project之后,总是在validating,超长时间的验证代码,尤其是动态css和JavaScript,让程序员等待久严重影响心情和工作进度,所以将其关闭或是禁用。 如何关闭,操作步骤如下&#xf…

Eclipse使用时遇到一直在Validating中的解决办法

第一次从服务器检出大型web项目时出现了validating中,一直卡死不动,因此百度查找了很多说法和解决方案,先总结如下: 一、什么是Eclipse的Validating? Eclipse安装之后一般是默认设置好了validation,允许软件对当前项…

LabVIEW编程LabVIEW开发研华通用驱动XNavi 例程与相关资料

LabVIEW编程LabVIEW开发研华通用驱动XNavi 例程与相关资料 研华通用驱动XNavi,XNavi支持DAQNavi的所有产品,提供驱动,并包括多种语言的例程,当然也包括LabVIEW。联网的计算机在安装XNavi后,可直接下载安装。同时也有离…

LabVIEW串口通信

目录 1、串口写入数据 2、串口读取数据 3、清除缓存区 4、设置缓存区 5、数据超时 6、数据终止符 串口通信(Serial Communications)的概念非常简单,串口按位(bit)发送和接收字节的通信方式。在LabVIEW中串口通信…

下载安装LabVIEW

下载安装LabVIEW 介绍下载安装流程下载安装 后续 介绍 LabVIEW 是 工程 师 用来 开发 自动 化 研究、 验证 和 生产 测试 系统 的 图形 化 编 程 环境。Labview作为图形化编程语言,图形控件拖拽式编程,显得更加直观形象,也很容易上手学习。 …

labview自制对话框

自制对话框 前言一、环境二、实现1.找图标2.新建VI,并进行以下设置3.界面布局3.1.放置一个字符串控件用于消息提示3.2.放置一个“确定”和一个“取消”按钮3.3.添加图标显示---画龙点睛3.4.适当调整布局 4.封装4.1.程序框图4.2接口 三、效果 前言 labview提供的对话…

LabView 下载与安装

labview2014是目前labview软件的最新版本,新版本增加了多个VI服务器对象,增加了多个vi脚本对象,增加了labview第三方许可和激活工具包,同时针对程序框图、编辑环境、应用程序生成器、web服务、触摸面板功能、前面板等进行了改进和优化,让用户可以更好的随时随地快速采集、…

labview 各版本及其模块工具下载汇总

labview 各版本模块工具汇总: http://download.ni.com/#evaluation/labview/ekit/other/downloader/http://download.ni.com/#evaluation/labview/ekit/other/downloader/—————————————————————————————————————————— …

VIPM安装超时无法连接到LabVIEW

首先,在LabVIEW中完成以下步骤以配置与VI服务器的连接。 单击工具选项以启动“选项”对话框。从左侧的“类别”部分中选择VI服务器 。勾选“协议”部分的TCP / IP复选框。记住端口号 。3363是默认端口号。您不需要使用默认值,但LabVIEW和VIPM必须被设置…

Labview2015安装教程

1、下载解压文件后,点进去刚刚解压的文件中,找到2015 LV这个软件,右键以管理员身份运行。 2、进去后,点击确定后就可以运行 3、选择第一个Unzip,勾选这两个选择 4、之后弹出这个确认消息,点击确定 5、点…

LabView2019的安装与卸载

LabView2019的安装 注:此版本为英文版,如需要要中文版的请参考LabView2018的安装 1. 下载网盘里面的LabView2019.zip压缩包 百度网盘链接:https://pan.baidu.com/s/1gyiFn5nOdPkLdp-1kRwwHA 提取码:labv    阿里云盘链接&…

labview 界面乱码问题解决

labview 界面乱码问题解决 **首先,打开控制面板的时钟、语言和区域,然后点击更改显示语言 ** 接着分别在格式、位置、管理这三个地方更改为中文(简体,新加坡)、新加坡、中文(简体,新加坡&#…

ubuntu下,下载及安装labview(涉及挂载.iso文件)的方法

在ubuntu环境下安装labview,本文总结了自己在安装过程中遇到的一些问题及解决方法,作为学习记录的同时,也分享一下供大家参考。主要涉及以下几个方面: 1、下载linux系统的安装包 2、.iso安装包的挂载及“只读权限”问题处理 3、…

LabView2018的安装

百度网盘链接:https://pan.baidu.com/s/1gyiFn5nOdPkLdp-1kRwwHA 提取码:labv    阿里云盘链接:https://www.aliyundrive.com/s/vBKNYBdLsXV 阿里云盘无法分享压缩包,因此改了文件格式,下载完后缀名改回.zip即可 安装…

labview插件下载

官方下载地址http://download.ni.com/#evaluation/labview/ekit/other/downloader/ labview 注册机 链接:https://pan.baidu.com/s/1VKEGFIYrLEk85FQdEe-OVQ 提取码:acsj NI LabVIEW软件可以通过多种方式与任何可编程逻辑控制器(PLC&#x…

LabVIEW下载 安装 和谐 与卸载教程

一. 简介 LabVIEW是一种程序开发环境,由美国国家仪器(NI)公司研制开发,类似于C和BASIC开发环境,但是LabVIEW与其他计算机语言的显著区别是:其他计算机语言都是采用基于文本的语言产生代码,而La…

使用Modbus将LabVIEW连接到任何PLC

使用Modbus将LabVIEW连接到任何PLC NI LabVIEW软件可以通过多种方式与可编程逻辑控制器(PLC)通信。 Modbus是Modicon于1979年发布的用于与PLC进行通信的串行通信协议,后来被扩展为TCP协议。 Modbus由于其可用性而成为业界事实上的标准通信协议…