欢迎访问我的GitHub
https://github.com/zq2599/blog_demos
内容:所有原创的分类和汇总,及配套源码,涉及Java、Docker、Kubernetes、DevOPS等
本篇概览
- 本文是《kubebuilder实战》系列的第七篇,之前的文章咱们完成了一个Operator的设计、开发、部署、验证过程,为了让整个过程保持简洁并且篇幅不膨胀,实战中刻意跳过了一个重要的知识点:webhook,如今是时候学习它了,这是个很重要的功能;
- 本篇由以下部分构成:
- 介绍webhook;
- 结合前面的elasticweb项目,设计一个使用webhook的场景;
- 准备工作
- 生成webhook
- 开发(配置)
- 开发(编码)
- 部署
- 验证Defaulter(添加默认值)
- 验证Validator(合法性校验)
关于webhook
- 熟悉java开发的读者大多知道过滤器(Servlet Filter),如下图,外部请求会先到达过滤器,做一些统一的操作,例如转码、校验,然后才由真正的业务逻辑处理请求:
- Operator中的webhook,其作用与上述过滤器类似,外部对CRD资源的变更,在Controller处理之前都会交给webhook提前处理,流程如下图,该图来自《Getting Started with Kubernetes | Operator and Operator Framework》:
- 再来看看webhook具体做了哪些事情,如下图,kubernetes官方博客明确指出webhook可以做两件事:修改(mutating)和验证(validating)
- kubebuilder为我们提供了生成webhook的基础文件和代码的工具,与制作API的工具类似,极大地简化了工作量,咱们只需聚焦业务实现即可;
- 基于kubebuilder制作的webhook和controller,如果是同一个资源,那么它们在同一个进程中;
设计实战场景
- 为了让实战有意义,咱们为前面的elasticweb项目上增加需求,让webhook发挥实际作用;
- 如果用户忘记输入总QPS,系统webhook负责设置默认值1300,操作如下图:
- 为了保护系统,给单个pod的QPS设置上限1000,如果外部输入的singlePodQPS值超过1000,就创建资源对象失败,如下图所示:
源码下载
- 本篇实战中的源码可在GitHub下载到,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos):
- 这个git项目中有多个文件夹,kubebuilder相关的应用在kubebuilder文件夹下,如下图红框所示:
- kubebuilder文件夹下有多个子文件夹,本篇对应的源码在elasticweb目录下,如下图红框所示:
准备工作
- 和controller类似,webhook既能在kubernetes环境中运行,也能在kubernetes环境之外运行;
- 如果webhook在kubernetes环境之外运行,是有些麻烦的,需要将证书放在所在环境,默认地址是:
/tmp/k8s-webhook-server/serving-certs/tls.{crt,key}
- 为了省事儿,也为了更接近生产环境的用法,接下来的实战的做法是将webhook部署在kubernetes环境中
- 为了让webhook在kubernetes环境中运行,咱们要做一点准备工作安装cert manager,执行以下操作:
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.2.0/cert-manager.yaml
- 上述操作完成后会新建很多资源,如namespace、rbac、pod等,以pod为例如下:
[root@hedy ~]# kubectl get pods --all-namespacesNAMESPACE NAME READY STATUS RESTARTS AGEcert-manager cert-manager-6588898cb4-nvnz8 1/1 Running 1 5d14hcert-manager cert-manager-cainjector-7bcbdbd99f-q645r 1/1 Running 1 5d14hcert-manager cert-manager-webhook-5fd9f9dd86-98tm9 1/1 Running 1 5d14h...
- 操作完成后,准备工作结束,可以开始实战了;
生成webhook
- 进入elasticweb工程下,执行以下命令创建webhook:
kubebuilder create webhook \--group elasticweb \--version v1 \--kind ElasticWeb \--defaulting \--programmatic-validation
- 上述命令执行完毕后,先去看看main.go文件,如下图红框1所示,自动增加了一段代码,作用是让webhook生效:
- 上图红框2中的elasticweb_webhook.go就是新增文件,内容如下:
package v1
import (
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
)
// log is for logging in this package.
var elasticweblog = logf.Log.WithName("elasticweb-resource")
func (r *ElasticWeb) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
Complete()
}
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// kubebuilder:webhook:path=/mutate-elasticweb-com-bolingcavalry-v1-elasticweb,mutating=true,failurePolicy=fail,groups=elasticweb.com.bolingcavalry,resources=elasticwebs,verbs=create;update,versions=v1,name=melasticweb.kb.io
var _ webhook.Defaulter =