Kubernetes Operator(三)使用kubebuilder构建一个你的Webhook

kubebuilder构建一个你的Webhook

准入控制器简介

在编写Webhook之前,我们得知道准入控制器是干嘛的~

准入控制器 它会在请求通过认证和鉴权之后、对象被持久化之前 拦截到达 API 服务器的请求。 准入控制器可以执行验证(Validating 和/或变更(Mutating 操作。 变更(mutating)控制器可以根据被其接受的请求更改相关对象;验证(validating)控制器则不行。

准入控制器限制创建、删除、修改对象的请求。 准入控制器也可以阻止自定义动作,例如通过 API 服务器代理连接到 Pod 的请求。 准入控制器不会 (也不能)阻止读取(getwatchlist)对象的请求。

自带的准入控制器:

  • DefaultIngressClass

  • DefaultStorageClass

  • OwnerReferencesPermissionEnforcement

  • PersistentVolumeClaimResize

  • ServiceAccount

  • ValidatingAdmissionWebhook:此准入控制器调用与请求匹配的所有验证性 Webhook。 匹配的 Webhook 将被并行调用。如果其中任何一个拒绝请求,则整个请求将失败。

  • MutatingAdmissionWebhookMutatingAdmissionWebhook,顾名思义,仅在变更阶段运行。此准入控制器调用任何与请求匹配的变更(Mutating) Webhook。匹配的 Webhook 将被顺序调用。 每一个 Webhook 都可以自由修改对象。

Webhook快速实践

准入 Webhook 是一种用于接收准入请求并对其进行处理的 HTTP 回调机制。 可以定义两种类型的准入 Webhook, 即验证性质的准入 ValidatingAdmissionWebhook变更性质的准入 MutatingAdmissionWebhook

当 Kubernetes 接收到新的或更新的资源对象时,MutatingAdmissionWebhook 会首先被调用,允许对资源对象进行修改。然后,ValidatingAdmissionWebhook 被调用,用于对修改后的资源对象进行验证和校验,确保其符合所定义的规则和要求。

创建ValidatingAdmissionWebhook

承接上篇,我们创建一个webhook

bash 复制代码
# conversion webhook
kubebuilder create webhook --group app --version v1 --kind Webservice --defaulting --programmatic-validation

      --conversion                if set, scaffold the conversion webhook 转换
      --defaulting                if set, scaffold the defaulting webhook 预设
      --programmatic-validation   if set, scaffold the validating webhook 验证
# 创建 MutatingAdmissionWebhook
# kubebuilder create webhook --group app --version v1 --kind Webservice --conversion

修改api/v1/webservice_webhook.go,我们找到// TODO(user)的地方,来写我们自己的逻辑,例如我们定义Replicas必须大于1

go 复制代码
func (r *Webservice) Default() {
	webservicelog.Info("default", "name", r.Name)

	// TODO(user): fill in your defaulting logic.
	// 校验Replicas必须大于1,如果Replicas小于等于1,则设置Replicas为2
	if r.Spec.Replicas <= 1 && r.Spec.Replicas != 0 {
		r.Spec.Replicas = 2
	}
}

app.webservice-operator.163.com/v1 版本下的 webservices 资源create;update;delete的时候调用webhook

go 复制代码
// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
//+kubebuilder:webhook:path=/validate-app-webservice-operator-163-com-v1-webservice,mutating=false,failurePolicy=fail,sideEffects=None,groups=app.webservice-operator.163.com,resources=webservices,verbs=create;update,versions=v1,name=vwebservice.kb.io,admissionReviewVersions=v1

ValidateCreateValidateUpdateValidateDelete方法将分别在创建、更新和删除时进行验证。我们也可以在里面定义自己的逻辑

go 复制代码
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (r *Webservice) ValidateCreate() error {
	webservicelog.Info("validate create", "name", r.Name)

	// TODO(user): fill in your validation logic upon object creation.
	return nil
}

// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (r *Webservice) ValidateUpdate(old runtime.Object) error {
	webservicelog.Info("validate update", "name", r.Name)

	// TODO(user): fill in your validation logic upon object update.
	return nil
}

// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
func (r *Webservice) ValidateDelete() error {
	webservicelog.Info("validate delete", "name", r.Name)

	// TODO(user): fill in your validation logic upon object deletion.
	return nil
}

部署

和operator一样的,我们需要生成CR或CRD等清单和安装CRD

shell 复制代码
# 生成CR或CRD等清单
make manifests
# 安装CRD
make install

如果webhook在kubernetes环境之外运行,需要生成对应的证书放在所在环境,默认地址是:/tmp/k8s-webhook-server/serving-certs/tls.{crt,key}

我们一般使用cert-manager-webhook为我们的webhook服务器自动配置证书,直接把服务部署到集群进行验证,但是在部署的时候一定要注意影响,因为失败会拦截请求。

shell 复制代码
$ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.yaml
# 验证部署
$ kubectl get pod -n cert-manager
NAME                                       READY   STATUS    RESTARTS   AGE
cert-manager-7865d8497c-z9hqz              1/1     Running   0          5m22s
cert-manager-cainjector-7769cd8976-hdv28   1/1     Running   0          5m22s
cert-manager-webhook-7768cfb496-n8dnx      1/1     Running   0          5m22s
$ kubectl get ValidatingWebhookConfiguration  cert-manager-webhook -oyaml
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  annotations:
    cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca
$ kubectl get MutatingWebhookConfiguration cert-manager-webhook -oyaml
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
  annotations:
    cert-manager.io/inject-ca-from-secret: cert-manager/cert-manager-webhook-ca

编辑config/default/kustomization.yaml,带WEBHOOKCERTMANAGER的都取消注释即可

yaml 复制代码
bases:
- ../crd
- ../rbac
- ../manager
- ../webhook
- ../certmanager

patchesStrategicMerge:
- manager_auth_proxy_patch.yaml
- manager_webhook_patch.yaml
- webhookcainjection_patch.yaml

vars:
- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR
  objref:
    kind: Certificate
    group: cert-manager.io
    version: v1
    name: serving-cert # this name should match the one in certificate.yaml
  fieldref:
    fieldpath: metadata.namespace
- name: CERTIFICATE_NAME
  objref:
    kind: Certificate
    group: cert-manager.io
    version: v1
    name: serving-cert # this name should match the one in certificate.yaml
- name: SERVICE_NAMESPACE # namespace of the service
  objref:
    kind: Service
    version: v1
    name: webhook-service
  fieldref:
    fieldpath: metadata.namespace
- name: SERVICE_NAME
  objref:
    kind: Service
    version: v1
    name: webhook-service

编辑config/crd/kustomization.yaml

go 复制代码
patchesStrategicMerge:
- patches/webhook_in_webservices.yaml
- patches/cainjection_in_webservices.yaml

构建镜像,推送到仓库中

shell 复制代码
$ make docker-build docker-push IMG=xxx/webserviceshook:v1

部署

shell 复制代码
$ make deploy IMG=xxx/webserviceshook:v1
namespace/operator-demo-system created
customresourcedefinition.apiextensions.k8s.io/webservices.app.webservice-operator.163.com created
serviceaccount/operator-demo-controller-manager created
role.rbac.authorization.k8s.io/operator-demo-leader-election-role created
clusterrole.rbac.authorization.k8s.io/operator-demo-manager-role created
clusterrole.rbac.authorization.k8s.io/operator-demo-metrics-reader created
clusterrole.rbac.authorization.k8s.io/operator-demo-proxy-role created
rolebinding.rbac.authorization.k8s.io/operator-demo-leader-election-rolebinding created
clusterrolebinding.rbac.authorization.k8s.io/operator-demo-manager-rolebinding created
clusterrolebinding.rbac.authorization.k8s.io/operator-demo-proxy-rolebinding created
service/operator-demo-controller-manager-metrics-service created
service/operator-demo-webhook-service created
deployment.apps/operator-demo-controller-manager created
certificate.cert-manager.io/operator-demo-serving-cert created
issuer.cert-manager.io/operator-demo-selfsigned-issuer created
mutatingwebhookconfiguration.admissionregistration.k8s.io/operator-demo-mutating-webhook-configuration created
validatingwebhookconfiguration.admissionregistration.k8s.io/operator-demo-validating-webhook-configuration created

$ kubectl get po -n operator-demo-system
NAME                                               READY   STATUS    RESTARTS   AGE
operator-demo-controller-manager-86ff9b7bb-lg4wl   2/2     Running   0          60s

验证

测试我们的逻辑是否正常运行

shell 复制代码
# 我们设置replicas: 1,逻辑就是我们不允许1个副本
$ kubectl apply  -f config/samples/app_v1_webservice.yaml
webservice.app.webservice-operator.163.com/webservice-sample created
$ kubectl get deploy
NAME                READY   UP-TO-DATE   AVAILABLE   AGE
webservice-sample   2/2     2            2           3m58s # 成功修改成2

如果遇到一个提示x509证书问题

shell 复制代码
$ kubectl apply  -f config/samples/app_v1_webservice.yaml
Error from server (InternalError): error when creating "config/samples/app_v1_webservice.yaml": Internal error occurred: failed calling webhook "mwebservice.kb.io": failed to call webhook: Post "https://operator-demo-webhook-service.operator-demo-system.svc:443/mutate-app-webservice-operator-163-com-v1-webservice?timeout=10s": x509: certificate signed by unknown authority

# 我们验证secret有没有创建出来,创建出来了大多是cert-manager的问题,解决方法是重新部署cert-manager,并且检查代码config下的相关注释有没有放开
$ kubectl get secret -n operator-demo-system  webhook-server-cert
NAME                  TYPE                DATA   AGE
webhook-server-cert   kubernetes.io/tls   3      8m2s

到此我们对kubebuilder的使用算是有了初步的了解。

相关推荐
bukeyiwanshui9 小时前
20260626 k8sControllers介绍
云原生·容器·kubernetes
能有时光10 小时前
] K8s 核心组件使用指南
云原生·容器·kubernetes
云烟成雨TD12 小时前
Kubernetes 系列【13】控制器:可视化操作 Deployment
云原生·容器·kubernetes
运维老郭1 天前
【K8s运维实战】Kubernetes临时存储卷实战:emptyDir核心用法与gitRepo弃用迁移指南
运维·云原生·kubernetes
gs801401 天前
记一次多 Agent 架构在单节点 K8s 触发的 PID 耗尽与 Pod 驱逐(Evicted)大摸排
容器·架构·kubernetes
bukeyiwanshui1 天前
20260701 k8s Metric Server
容器·贪心算法·kubernetes
Zhu7581 天前
在k8s集群部署ApacheHadoop单节点单数据副本
云原生·容器·kubernetes
摇滚侠1 天前
云原生 Java 架构师的第一课 K8s+Docker+KubeSphere+DevOps 51-60
java·云原生·kubernetes
bukeyiwanshui1 天前
20260703 K8s ECShop商城项目
云原生·容器·kubernetes