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的使用算是有了初步的了解。

相关推荐
福大大架构师每日一题8 小时前
22.1 k8s不同role级别的服务发现
容器·kubernetes·服务发现
weixin_453965009 小时前
[单master节点k8s部署]30.ceph分布式存储(一)
分布式·ceph·kubernetes
weixin_453965009 小时前
[单master节点k8s部署]32.ceph分布式存储(三)
分布式·ceph·kubernetes
tangdou3690986559 小时前
1分钟搞懂K8S中的NodeSelector
云原生·容器·kubernetes
later_rql12 小时前
k8s-集群部署1
云原生·容器·kubernetes
weixin_4539650014 小时前
[单master节点k8s部署]31.ceph分布式存储(二)
分布式·ceph·kubernetes
大G哥17 小时前
记一次K8S 环境应用nginx stable-alpine 解析内部域名失败排查思路
运维·nginx·云原生·容器·kubernetes
妍妍的宝贝18 小时前
k8s 中微服务之 MetailLB 搭配 ingress-nginx 实现七层负载
nginx·微服务·kubernetes
福大大架构师每日一题19 小时前
23.1 k8s监控中标签relabel的应用和原理
java·容器·kubernetes
程序那点事儿19 小时前
k8s 之动态创建pv失败(踩坑)
云原生·容器·kubernetes