介绍

Webhook就是一种HTTP回调,用于在某种情况下执行某些动作,Webhook不是K8S独有的,很多场景下都可以进行Webhook,比如在提交完代码后调用一个Webhook自动构建docker镜像

准入 Webhook 是一种用于接收准入请求并对其进行处理的 HTTP 回调机制。 可以定义两种类型的准入 Webhook, 即验证性质的准入 Webhook 和变更性质的准入 Webhook。 变更性质的准入 Webhook 会先被调用。它们可以修改发送到 API 服务器的对象以执行自定义的设置默认值操作。

在完成了所有对象修改并且 API 服务器也验证了所传入的对象之后, 验证性质的 Webhook 会被调用,并通过拒绝请求的方式来强制实施自定义的策略。

Admission Webhook使用较多的场景如下

  1. 在资源持久化到ETCD之前进行修改(Mutating Webhook),比如增加init Container或者sidecar Container
  2. 在资源持久化到ETCD之前进行校验(Validating Webhook),不满足条件的资源直接拒绝并给出相应信息

组成

  1. webhook 服务
  2. webhook 配置
  3. webhook 证书

创建核心组件Pod的Webhook

使用kubebuilder新建webhook项目

kubebuilder init --domain test.com --repo gitlab.qima-inc.com/test-operator
(base) (⎈ |kubernetes-admin@qa-u03:qa)➜  test-operator kubebuilder init --domain test.com --repo gitlab.qima-inc.com/test-operator
INFO Writing kustomize manifests for you to edit...
INFO Writing scaffold for you to edit...
INFO Get controller runtime:
$ go get sigs.k8s.io/controller-runtime@v0.17.2
INFO Update dependencies:
$ go mod tidy
go: go.mod file indicates go 1.21, but maximum version supported by tidy is 1.19
Error: failed to initialize project: unable to run post-scaffold tasks of "base.go.kubebuilder.io/v4": exit status 1

因为我默认是是go1.19所以版本达不到要求,这里两种处理方式

  1. 指定 --plugins go/v3 --project-version 3
  2. 切换高版本golang 这里我切换了go1.22
(base) (⎈ |kubernetes-admin@qa-u03:qa)➜  test-operator kubebuilder init --domain test.com --repo gitlab.qima-inc.com/test-operator
INFO Writing kustomize manifests for you to edit...
INFO Writing scaffold for you to edit...
INFO Get controller runtime:
$ go get sigs.k8s.io/controller-runtime@v0.17.2
INFO Update dependencies:
$ go mod tidy
Next: define a resource with:
$ kubebuilder create api

生成核心组件Pod的API

(base) (⎈ |kubernetes-admin@qa-u03:qa)➜  test-operator kubebuilder create api --group core --version v1 --kind Pod
INFO Create Resource [y/n]
n
INFO Create Controller [y/n]
n
INFO Writing kustomize manifests for you to edit...
INFO Writing scaffold for you to edit...
INFO Update dependencies:
$ go mod tidy

这里有两个选项,创建资源和创建控制器

因为是内置资源Pod所以不需要创建资源,也不需要控制器

假如是自定义资源,需要创建资源,创建控制器

创建webhook

(base) (⎈ |kubernetes-admin@qa-u03:qa)➜  test-operator kubebuilder create webhook --group core --version v1 --kind Pod --defaulting --programmatic-validation
INFO Writing kustomize manifests for you to edit...
ERRO Unable to find the target(s) #- path: patches/webhook/* to uncomment in the file config/crd/kustomization.yaml.
ERRO Unable to find the target(s) #configurations:
#- kustomizeconfig.yaml to uncomment in the file config/crd/kustomization.yaml.
INFO Writing scaffold for you to edit...
INFO api/v1/pod_webhook.go
INFO api/v1/pod_webhook_test.go
INFO api/v1/webhook_suite_test.go
INFO Update dependencies:
$ go mod tidy
INFO Running make:
$ make generate
mkdir -p /Users/xxxx/test-operator/bin
Downloading sigs.k8s.io/controller-tools/cmd/controller-gen@v0.14.0
/Users/xxxx/test-operator/bin/controller-gen-v0.14.0 object:headerFile="hack/boilerplate.go.txt" paths="./..."
Next: implement your new Webhook and generate the manifests with:
$ make manifests

代码结构

.
├── Dockerfile
├── Makefile
├── PROJECT
├── README.md
├── api
│   └── v1
│   ├── pod_webhook.go
│   ├── pod_webhook_test.go
│   └── webhook_suite_test.go
├── bin
│   └── controller-gen-v0.14.0
├── cmd
│   └── main.go
├── config
│   ├── certmanager
│   │   ├── certificate.yaml
│   │   ├── kustomization.yaml
│   │   └── kustomizeconfig.yaml
│   ├── crd
│   │   └── patches
│   │   ├── cainjection_in_pods.yaml
│   │   └── webhook_in_pods.yaml
│   ├── default
│   │   ├── kustomization.yaml
│   │   ├── manager_auth_proxy_patch.yaml
│   │   ├── manager_config_patch.yaml
│   │   ├── manager_webhook_patch.yaml
│   │   └── webhookcainjection_patch.yaml
│   ├── manager
│   │   ├── kustomization.yaml
│   │   └── manager.yaml
│   ├── prometheus
│   │   ├── kustomization.yaml
│   │   └── monitor.yaml
│   ├── rbac
│   │   ├── auth_proxy_client_clusterrole.yaml
│   │   ├── auth_proxy_role.yaml
│   │   ├── auth_proxy_role_binding.yaml
│   │   ├── auth_proxy_service.yaml
│   │   ├── kustomization.yaml
│   │   ├── leader_election_role.yaml
│   │   ├── leader_election_role_binding.yaml
│   │   ├── role.yaml
│   │   ├── role_binding.yaml
│   │   └── service_account.yaml
│   └── webhook
│   ├── kustomization.yaml
│   ├── kustomizeconfig.yaml
│   ├── manifests.yaml
│   └── service.yaml
├── go.mod
├── go.sum
├── hack
│   └── boilerplate.go.txt
└── test
├── e2e
│   ├── e2e_suite_test.go
│   └── e2e_test.go
└── utils
└── utils.go

实现Webhook相关代码

因为只有Webhook,没有Controller 所以只需要实现Webhook相关代码即可,同时需要注释掉一些代码如:

Dockerfile中的

# COPY internal/controller/ internal/controller/

修改api/v1/xxx_suite_test.go

因为核心组件Pod的Webhook和一般的CRD的webhook不一样,此处生成的pod_webhook.go只有Default()这个function,因此,我们需要直接重写整个代码,最重要的是Handle()方法。

/*
Copyright 2024. Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/ package v1 import (
"fmt"
"net/http"
"sigs.k8s.io/controller-runtime/pkg/client"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
) // log is for logging in this package.
var podlog = logf.Log.WithName("pod-resource") // 定义核心组件pod的webhook的主struct,类似于java的Class
type PodWebhookMutate struct {
Client client.Client
decoder *admission.Decoder
} // +kubebuilder:webhook:path=/mutate-core-v1-pod,mutating=true,failurePolicy=fail,sideEffects=None,groups=core,resources=pods,verbs=create;update,versions=v1,name=mpod.kb.io,admissionReviewVersions=v1
func (a *PodWebhookMutate) Handle(ctx context.Context, req admission.Request) admission.Response {
pod := &corev1.Pod{}
err := a.decoder.Decode(req, pod)
if err != nil {
return admission.Errored(http.StatusBadRequest, err)
} // TODO: 变量marshaledPod是一个Map,可以直接修改pod的一些属性
marshaledPod, err := json.Marshal(pod)
if err != nil {
return admission.Errored(http.StatusInternalServerError, err)
}
// 打印
fmt.Println("======================================================")
fmt.Println(string(marshaledPod))
return admission.PatchResponseFromRaw(req.Object.Raw, marshaledPod)
} func (a *PodWebhookMutate) InjectDecoder(d *admission.Decoder) error {
a.decoder = d
return nil
}

修改main.go文件:

if os.Getenv("ENABLE_WEBHOOKS") != "false" {
//if err = (&corev1.Pod{}).SetupWebhookWithManager(mgr); err != nil {
// setupLog.Error(err, "unable to create webhook", "webhook", "Pod")
// os.Exit(1)
//}
mgr.GetWebhookServer().Register("/mutate-core-v1-pod", &webhook.Admission{Handler: &v1.PodWebhookMutate{Client: mgr.GetClient()}})
}

生成mainfests

make manifests generate

证书

手动签发证书

https://cuisongliu.github.io/2020/07/kubernetes/admission-webhook/

自动签发证书

webhook 服务启动时自动生成证书,授权证书

  1. 创建CA根证书以及服务的证书
  2. 将服务端、CA证书写入 k8s Secret,并且支持find or create
  3. 本地写入证书
  4. 获取MutatingWebhookConfiguration和ValidatingWebhookConfiguration将caCert写入webhook config中的ClientConfig.CABundle(这里有个问题是webhook需要提前创建,CABundle可以写个临时值,等webhook server 启动覆盖)

自动签发证书参考项目: https://github.com/koordinator-sh/koordinator/blob/main/pkg/webhook/util/controller/webhook_controller.go#L187

开发一个MutatingWebhook的更多相关文章

  1. 拥抱.NET Core,如何开发一个跨平台类库 (1)

    在此前的文章中详细介绍了使用.NET Core的基本知识,如果还没有看,可以先去了解“拥抱.NET Core,学习.NET Core的基础知识补遗”,以便接下来的阅读. 在本文将介绍如何配置类库项目支 ...

  2. 如何开发一个简单的HTML5 Canvas 小游戏

    原文:How to make a simple HTML5 Canvas game 想要快速上手HTML5 Canvas小游戏开发?下面通过一个例子来进行手把手教学.(如果你怀疑我的资历, A Wiz ...

  3. [MEF插件式开发] 一个简单的例子

    偶然在博客园中了解到这种技术,顺便学习了几天. 以下是搜索到一些比较好的博文供参考: MEF核心笔记 <MEF程序设计指南>博文汇总 先上效果图 一.新建解决方案 开始新建一个解决方案Me ...

  4. bootstrap开发一个简单网页。

    CSS代码: body{        padding-top: 50px;        padding-bottom: 50px;        overflow: auto!important; ...

  5. 后移动互联网时代:到底还要不要开发一个App?

    后移动互联网时代,到底是什么样的一个时代? 首先,后移动互联网时代中,产生头部应用的几率变小了,像微信这样巨头式的App很难在产生第二个.其次,后移动互联网时代,物联网发展迅速,所有的智能硬件都需要一 ...

  6. iOS开发一个用户登录注册模块需要解决的坑

    最近和另外一位同事负责公司登录和用户中心模块的开发工作,开发周期计划两周,减去和产品和接口的协调时间,再减去由于原型图和接口的问题,导致强迫症纠结症状高发,情绪不稳定耗费的时间,能在两周基本完成也算是 ...

  7. 【如何快速的开发一个完整的iOS直播app】(美颜篇)

    原文转自:袁峥Seemygo    感谢分享.自我学习 前言 在看这篇之前,如果您还不了解直播原理,请查看这篇文章如何快速的开发一个完整的iOS直播app(原理篇) 开发一款直播app,美颜功能是很重 ...

  8. 【如何快速的开发一个完整的iOS直播app】(采集篇)

    原文转自:袁峥Seemygo    感谢分享.自我学习 前言 在看这篇之前,如果您还不了解直播原理,请查看这篇文章如何快速的开发一个完整的iOS直播app(原理篇) 开发一款直播app,首先需要采集主 ...

  9. 【如何快速的开发一个完整的iOS直播app】(播放篇)

    原文转自:袁峥Seemygo    感谢分享.自我学习 前言 在看这篇之前,如果您还不了解直播原理,请查看上篇文章如何快速的开发一个完整的iOS直播app(原理篇) 开发一款直播app,集成ijkpl ...

  10. 【如何快速的开发一个完整的iOS直播app】(原理篇)

    原文转自:袁峥Seemygo    感谢分享.自我学习 目录 [如何快速的开发一个完整的iOS直播app](原理篇) [如何快速的开发一个完整的iOS直播app](播放篇) [如何快速的开发一个完整的 ...

随机推荐

  1. Numpy技巧: 由label获得相等矩阵

    Numpy技巧: 由label获得相等矩阵     假设Label为:  [ABAC] , 如何方便的得到一个矩阵, 其元素i,j表示第i位和第j位相等呢?   先把Label复制扩展成: m,m 的 ...

  2. android 8.1 安全机制 — SEAndroid & SELinux

    android 8.1 安全机制 - SEAndroid & SELinux 原文链接:https://blog.csdn.net/qq_19923217/article/details/81 ...

  3. PHP 真的不行了?透过 PHP 的前世今生看真相

    大家好,我是码农先森. 1994年我出生在湖南的农村,就在同年加拿大的拉斯姆斯·勒多夫创造了 PHP,这时的 PHP 还只是用 Perl 编写的 CGI 脚本.或许是时间的巧合 PHP 变成了我后半生 ...

  4. 【Mysql】 MysqlDump导表结构或数据

    mysqldump只导出表结构或只导出数据的实现方法 语法: 默认不带参数的导出,导出文本内容大概如下:创建数据库判断语句-删除表-创建表-锁表-禁用索引-插入数据-启用索引-解锁表. Usage: ...

  5. Qt--共享内存监听工具

    共享内存概述 共享内存的特点: 1)共享内存是进程共享数据的一种最快的方法. 一个进程向共享内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容. 2)使用共享内存要注意的是多个进程 ...

  6. VulnHub_DC-1渗透流程

    DC-1 DC-1 是一个专门建造的易受攻击的实验室,目的是在渗透测试领域获得经验. 它旨在为初学者提供挑战,但它的难易程度取决于您的技能和知识,以及您的学习能力. 要成功完成此挑战,您将需要 Lin ...

  7. Spring定时任务和@Async注解异步调用

    Spring定时任务 1.@Scheduled注解方式 使用方式 @Scheduled的使用方式十分简单,首先在项目启动类添加注解@EnableScheduled. 编写定时任务方法,方法上添加注解@ ...

  8. 谈谈你对 keep-alive 的了解?

    在做电商有关的项目中,当我们第一次进入列表页需要请求一下数据,当我从列表页进入详情页,详情页不缓存也需要请求下数据,然后返回列表页,这时候我们使用keep-alive来缓存组件,防止二次渲染,这样会大 ...

  9. Solo 开发者周刊 (第 1 期):开源产品的探索之路

    产品推荐 如何着手将一个简单的想法转变为一个成熟的开源项目,以及如何在此过程中利用和贡献于开源社区.同时使其达到商业化的同时,保持原有的开源精神.这些是我们需要探索的. Spug 开源运维平台 Spu ...

  10. AI驱动音乐创新,网易数帆X云音乐刷新MIREX世界纪录 网易数帆 网易数帆

    在近期揭榜的2021国际音频检索评测大赛(MIREX)上,网易数帆易智语音团队携手网易云音乐音视频实验室,凭借生产级AI技术创新能力,在歌词识别和歌单识别两个赛道大幅打破世界纪录夺得冠军. MIREX ...