CRD Admission Webhook

前言

前面的文章中,实现了Unit资源对象实例持久化之后的controller管理的过程。除此之外,Kubernetes额外支持了一些很有趣且实用的功能,例如经常被用在资源准入控制上的Adminssion Webhook,它是对APIServer接收准入请求的扩展。详情请参考官方文档:

extensible-admission-controllers

认识Adminssion Webhook

什么是Adminssion Webhook?

在官方文档里对的话来说就是:

Admission webhooks are HTTP callbacks that receive admission requests and do something with them. You can define two types of admission webhooks, validating admission webhook and mutating admission webhook. Mutating admission webhooks are invoked first, and can modify objects sent to the API server to enforce custom defaults. After all object modifications are complete, and after the incoming object is validated by the API server, validating admission webhooks are invoked and can reject requests to enforce custom policies.

一句话概括:Adminssion Webhook是APIServer接收到资源准入请求后执行的回调钩子

在K8s中,追求一切皆资源,Webhook也是一种GVK,可以动态地向APIServer注入/修改/更新钩子。

Adminssion Webhook的作用

Adminssion Webhook可以用作:在资源对象实例持久化之前,将 Kubernetes APIServer 的请求进行拦截,加入自定义的逻辑再处理之后,再返回给APIServer,更形象一点说,即是对APIServer接收的请求进行拦截和“篡改”

Adminssion Webhook的分类

mutating webhook

可用作一些"篡改"的逻辑,例如修改pod的结构,为pod注入sidecar容器,istio就是这么干的。

validating webhook

用作校验的逻辑,虽然go是严格的强类型语言,结构体内的字段已经做了type校验,但字段的检验总是相对生硬死板的,validating webhook可以做很好的补充校验。

注意:按照执行顺序,validating webhook在mutating webhook之后执行。

Adminssion Webhook流程图

Kubebuilder使用webhook

回到项目根目录,执行:

# group version kind替换成自己的
mbp-16in:Unit ywq$ kubebuilder create webhook --group custom --version v1 --kind Unit --defaulting --programmatic-validationWriting scaffold for you to edit...
api/v1/unit_webhook.go

可以看到,api/v1/下多了一个unit_webhook.go文件,里面有4个方法以及列出来了

// Default implements webhook.Defaulter so a webhook will be registered for the type
func (r *Unit) Default() {unitlog.Info("default", "name", r.Name)// TODO(user): fill in your defaulting logic.}// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
// +kubebuilder:webhook:verbs=create;update,path=/validate-custom-my-crd-com-v1-unit,mutating=false,failurePolicy=fail,groups=custom.my.crd.com,resources=units,versions=v1,name=vunit.kb.iovar _ webhook.Validator = &Unit{}// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (r *Unit) ValidateCreate() error {unitlog.Info("validate create", "name", r.Name)// TODO(user): fill in your validation logic upon object creation.}// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (r *Unit) ValidateUpdate(old runtime.Object) error {unitlog.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 *Unit) ValidateDelete() error {unitlog.Info("validate delete", "name", r.Name)// TODO(user): fill in your validation logic upon object deletion.return nil
}

从命名和注释就可以看出来,4个方法分别用于:

  • Default() 用于修改,即对应mutating webhook
  • ValidateCreate()用于校验,对应validating webhook,仅在create操作使用
  • ValidateUpdate()用于校验,对应validating webhook,仅在create操作使用
  • ValidateDelete()用于校验,对应validating webhook,仅在create操作使用

Default()ValidateCreate()为例,来实现简单的Unit实例持久化之前的修改Unit默认字段、内容校验的逻辑

Default()

func (r *Unit) Default() {unitlog.Info("default", "name", r.Name)// TODO(user): fill in your defaulting logic.// 这里可以加入一些Unit 结构体对象初始化之前的一些默认的逻辑,比如给一些字段填充默认值// default replicas set to 1unitlog.Info("default", "name", r.Name)if r.Spec.Replicas == nil {defaultReplicas := int32(1)r.Spec.Replicas = &defaultReplicas}// add default selector labellabelMap := make(map[string]string, 1)labelMap["app"] = r.Namer.Spec.Selector = &metav1.LabelSelector{MatchLabels: labelMap,}// add default template labelr.Spec.Template.Labels = labelMapr.Status.LastUpdateTime = metav1.Now()// 当然,还可以根据需求加一些适合在初始化时做的逻辑,例如为pod注入sidecar// ...}

给Unit指定默认的副本数、添加默认的自定义标签,还可以添加一些其他的东西,例如sidecar、initContainer等等

###ValidateCreate()

// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
// +kubebuilder:webhook:verbs=create;update,path=/validate-custom-my-crd-com-v1-unit,mutating=false,failurePolicy=fail,groups=custom.my.crd.com,resources=units,versions=v1,name=vunit.kb.io// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (r *Unit) ValidateCreate() error {unitlog.Info("validate create", "name", r.Name)// TODO(user): fill in your validation logic upon object creation.// 检查Unit.Spec.Categoryswitch r.Spec.Category {case CategoryDeployment:return nilcase CategoryStatefulSet:return nildefault:err := errors.New("spec.category only support Deployment or StatefulSet")unitlog.Error(err, "creating validate failed", "name", r.Name)return err}
}

因Unit动态支持Sts和Deploy,但只能二取其一,默认Unit结构体内的字段校验显然不适合做这种类型的校验,所以把校验的操作放到这里来。

Kubebuilder marker

在validateCreate()方法上方,有两行特殊的注释不知有没有吸引到你的注意力:

// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
// +kubebuilder:webhook:verbs=create;update,path=/validate-custom-my-crd-com-v1-unit,mutating=false,failurePolicy=fail,groups=custom.my.crd.com,resources=units,versions=v1,name=vunit.kb.io

第一行注释说明,修改第二行中的verbs字段可以改变validateCreate()的工作插入时机。

看看第二行注释的抬头:+kubebuilder:,有没有突然想起项目中有多处这种抬头的注释。这种格式的注释对kubebuilder有着特殊的意义,被称为marker。在执行make指令的时候,kubebuilder会根据特定位置的marker,进行相应的转换逻辑。

主要在如下3个地方使用到了marker:

webhook

api/v1/unit_webhook.go:39


// +kubebuilder:webhook:path=/mutate-custom-my-crd-com-v1-unit,mutating=true,failurePolicy=fail,groups=custom.my.crd.com,resources=units,verbs=create;update,versions=v1,name=munit.kb.iovar _ webhook.Defaulter = &Unit{}// Default implements webhook.Defaulter so a webhook will be registered for the type
func (r *Unit) Default() {unitlog.Info("default", "name", r.Name)...}// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
// +kubebuilder:webhook:verbs=create;update,path=/validate-custom-my-crd-com-v1-unit,mutating=false,failurePolicy=fail,groups=custom.my.crd.com,resources=units,versions=v1,name=vunit.kb.io// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (r *Unit) ValidateCreate() error {unitlog.Info("validate create", "name", r.Name)...
}

这两个钩子函数的上方,都有marker的存在,这里的marker的内容,会影响最终生成的Webhook资源的配置。

CRD type

api/v1/unit_types.go:79

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas,selectorpath=.status.selector
// Unit is the Schema for the units API
type Unit struct {metav1.TypeMeta   `json:",inline"`metav1.ObjectMeta `json:"metadata,omitempty"`Spec   UnitSpec   `json:"spec,omitempty"`Status UnitStatus `json:"status,omitempty"`
}

这里有两个后加入的marker,分别讲一下:

+kubebuilder:subresource:status

上一篇文章中有提过,更新Unit.Status()时,尽量局部更新避免并发冲突。实现Status局部更新,需要指定此marker

+kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas,selectorpath=.status.selector

添加这个marker并正确指定replicas字段的specpath以及statuspath后,可以使用kubectl scale命令的形式来方便地修改CRD的replicas值,就像Deploy/Sts一样。

Reconcile

controllers/unit_controller.go:64

// +kubebuilder:rbac:groups=custom.my.crd.com,resources=units,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=custom.my.crd.com,resources=units/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=apps,resources=statefulSet,verbs=get;update;patch;delete
// +kubebuilder:rbac:groups=apps,resources=deployment,verbs=get;update;patch;delete
// +kubebuilder:rbac:groups=core,resources=service,verbs=get;update;patch;delete
// +kubebuilder:rbac:groups=core,resources=endpoint,verbs=get
// +kubebuilder:rbac:groups=core,resources=persistentVolumeClaimStatus,verbs=get;update;patch;delete
// +kubebuilder:rbac:groups=extensions,resources=ingress,verbs=get;update;patch;deletefunc (r *UnitReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {...
}

很容易理解,Reconcile控制逻辑运行过程中,难免要对多种资源进行增删改查操作,rbac授权必不可少,因此,每种需要关注的GVK资源的授权都在这里的以marker形式指定,在make之后,会生成相应的rbac yaml文件,体现在config/rbac目录下。

总结

准备工作已经完成了,但代码编写很难一蹴而就,总会遇到error需要反复调试,下一篇开始讲述如何使本地环境与K8s集群连接,在本地环境中进行代码调试。

《 Kubebuilder v2 使用指南 》-P6-CRD Admission Webhook相关推荐

  1. 《 Kubebuilder v2 使用指南 》-P1-总览篇

    < Kubebuilder v2 使用指南 > Gitbook < Kubebuilder v2 使用指南 >专栏已整理打包为gitbook电子书,阅读更紧凑和连贯,推荐点击直 ...

  2. kube-apiserver源码-动态准入控制 admission webhook

    动态配置admission webhook举例(详情见官方文档:https://kubernetes.io/zh/docs/reference/access-authn-authz/extensibl ...

  3. k8s admission webhook初探

    前言 之前一篇博客讨论的问题,就是如何杀掉container的主进程,并且让container不重启,最后有讲到说也许可以使用admission webhook,动态替换容器,做到给一个空容器,也就是 ...

  4. Kubernetes Admission Webhook Validating 与 mutating 实践

    Kubernetes Admission Webhook Validating 与 mutating 实践 文章目录 Kubernetes Admission Webhook Validating 与 ...

  5. helm v2 入门指南

    文章目录 1. 前提条件 2. 功能 3. 概念 4. Helm组件 5. 安装 5.1 安装客户端 5.2 安装服务端 6. helm init 6.1 --history-max 6.2 --no ...

  6. P6 EPPM 安装与配置指南 16 R1 2016.4

       关于安装和 配置P6 EPPM 本指南告诉你如何自动 安装和配置您的应用程序. 在您开始之前,阅读 先决条件 P6 EPPM配置 (7页). 安装P6 EPPM 您将使用 安装程序 (窗口) . ...

  7. 第八课 k8s源码学习和二次开发原理篇-KubeBuilder使用和Controller-runtime原理

    第八课 k8s源码学习和二次开发原理篇-KubeBuilder使用和Controller-runtime原理 tags: k8s 源码学习 categories: 源码学习 二次开发 文章目录 第八课 ...

  8. 云原生生态周报 Vol. 14 | K8s CVE 修复指南

    业界要闻 Mesosphere 公司正式更名为 D2IQ, 关注云原生. Mesosophere 公司日前发布官方声明正式更名为:D2iQ(Day-Two-I-Q),称关注点转向 Kubernetes ...

  9. kubebuilder实践笔记(4) - 编写简单的业务逻辑

    今天使用kubebuilder,在一个Controller中编写简单的业务逻辑. 需求: 1)实现自定义对象(ats/at-sample)的状态(Status.Phase字段)的转换:PENDING& ...

最新文章

  1. 中科院计算所实习-深度学习方向
  2. CSS基础篇--CSS/CSS3中的原生变量var详解
  3. CPaintDC和CClientDC的区别
  4. python行业中性_市场风险中性假设的r0只是等效r的其中之一
  5. 校内训练赛题解第三篇
  6. Rk3288运行linux,查看“Firefly-rk3288 build linux”的源代码
  7. Flask的session使用
  8. linux_adduser
  9. C++再议构造函数及复制构造函数深度复制
  10. 中文信息处理(四)—— 神经网络基础
  11. html语言字体为隶书,css如何设置隶书字体库
  12. python身份证号码校验第十七位系数_python实现身份证校验位计算
  13. 概念数据模型(CDM)、逻辑数据模型(LDM)、物理数据模型(PDM)区别以及哪些适合需求分析阶段的数据建模
  14. Unity实现遮挡人物的障碍物体设为透明,并在不遮挡时恢复的个人解决方法
  15. 计算机视觉论文-2021-07-26
  16. 北京大学计算机考研资料汇总
  17. 百度地图LBS应用开发代码
  18. UE4元数据关键字的应用与含义(一)
  19. 什么是浏览器隐私模式?浏览器隐私模式是否安全?
  20. 前端学习记录005_canvas绘制钟表

热门文章

  1. 完美用Nlite添加ACHI SATA驱动至XP镜像
  2. C语言 统计元音字母个数
  3. 计算机图形学直线线型实验报告,计算机图形学实验报告-直线中点bresenham算法的实现资料.doc...
  4. 阿里视频云web播放器常见问题汇总
  5. 再编写代码中报错:CS8107 C# 7.0 中不支持功能“xxxxxx”。请使用 7.1 或更高的语言版本。...
  6. OpenCV 实时对象跟踪(质心跟踪)
  7. 自学Java!三面蚂蚁核心金融部,Java岗
  8. 4、selenium3的安装
  9. 2018年我跑去做淘宝了(续篇)
  10. 开源的跨平台AI模型部署总有一款是你的菜