3.3.6 WebHook
1. WebHook是什么
WebHook与过滤器的作用类似,任何对 CRD进行变更的操作都会交由 WebHook提前处理,处理完后,才会转给 Controller 继续处理,WebHook流程如图 3-6所示。
图 3—6WebHook 流程
根据 Kubernetes官方博客的介绍,WebHook 具有以下两个功能。
(1) 修改(Mutating):对CRD 进行修改,如为资源自动打标签等。
(2) 验证(Validating):对 CRD进行验证,如判断该字段的设定是否在取值范围内。引用 Kubernetes 官方博客的一张图来说明 Mutating及Validating 操作所在的位置,如
图3-7所示。
具体说明如下。
图 3—7 Mutatng及 Vaidatng 严作所在的位置
(1)APIServer接收到 API请求。
(2)请求经过认证、鉴权。
(3) 执行 MutatingAdmission的 WebHookList。
(4) 对请求对象的 Schema进行校验。
(5) 执行 ValidatingAdmission的 WebHookList。
(6) 最后写入 ETCD。
2. Controller-runtime中的 WebHook框架
Controller-runtime为用户提供了一个简单快捷的WebHook框架,可通过该框架,快速创建 WebHook,并将处理函数注入 WebHookServer中,通过 WebHook 的处理函数,即可实现 CRD的修改和验证操作。
(1) Server的创建
通过Controller-runtime提供的WebHookServer包,可快速地构建出一个HTTPServer,该 Server用于接收来自 Kube-APIServer的请求,并将请求转发到对应的 Handler进行处理。
WebHookServer主要用于保存注册的WebHook(见代码清单3-46)。
typeServerstruct{
...
//下⾯的webhooks会跟踪所有已注册的webhooks,以便进⾏依赖注⼊,并在重复的Webhook
注册时提供更好的告警
webhooksmap[string]http.Handler
...
}
开发者可通过 WebHook包中的 func(s*Server)Register(pathstring, hookhttp.Handler){},将开发好的 WebHook注册到 Server中,WebHook其实就是一个 HTTP请求的处理函数。
(2) Handler 的实现
开发者在实现 Handler的时候,只需要实现 WebHook包定义好的 Interface即可(见代码清单3-47)。
//HandlerFunc函数⽤来实现 Handler接⼝
typeHandlerFuncfunc(context.Context,Request)Response
在此基础上,WebHook包提供了 Handler 函数返回体的各种封装,开发者可基于这些封装实现自定义的业务逻辑。
对于 Admission的 WebHook,定义了两种最基本的返回体封装函数。
(1) 允许:该封装函数表明对CRD的某种操作是允许的(见代码清单3-48)。
funcAllowed(reasonstring)Response{returnValidationResponse(true,reason)
}
(2) 拒绝:该封装函数表明对CRD的某种操作是拒绝的(见代码清单3-49)。
funcDenied(reasonstring)Response{returnValidationResponse(false,reason)
}
3. WebHook示例
基于前面的介绍,本节将给出一个WebHook的简单示例(见代码清单3-50)。
//创建Manager
mgr,err:=ctrl.NewManager(ctrl.GetConfigOrDie(),ctrl.Options{})
iferr!=nil{
panic(err)
}
//创建 WebHook ServerhookServer:= &Server{
Port:8443,
}
if err:=mgr.Add(hookServer);err!=nil{panic(err)
}
//创建 WebHook的处理函数
validatingHook:=&Admission{
Handler:admission.HandlerFunc(func(ctxcontext.Context,req
AdmissionRequest)AdmissionResponse{
returnDenied("noneshallpass!")
}),
}
//将Handler注册到WebHookServer中
hookServer.Register("/validating",validatingHook)
//启动Manager,启动 WebHookServer
err=mgr.Start(ctrl.SetupSignalHandler())iferr!=nil{
panic(err)
}