创建K8s pod Webhook

这篇具有很好参考价值的文章主要介绍了创建K8s pod Webhook。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1.前提条件

2.开始创建核心组件Pod的Webhook

2.1.什么是Webhook

 2.2.在本地k8s集群安装cert-manager

2.3.创建一个空的文件夹

2.4. 生成工程框架

2.5. 生成核心组件Pod的API

2.6.生成Webhook

2.7.开始实现Webhook相关代码

2.7.1.修改相关配置

2.7.2.修改代码

2.7.3.按照最新配置更新yaml

2.7.4.集群运行测试

2.7.4.1.修改Makefile文件

2.7.4.2.将应用部署到k8s集群上

2.7.5.测试

2.7.5.1.准备测试Deployment的yaml配置

2.7.5.2.部署这个Pod demo

 2.7.5.3.停止测试

参考文章


1.前提条件

可以按之前的文章配置,配置好之后,我们会准备好以下内容:

  • 本地多节点集群
  • kubectl 客户端命令工具
  • Lens k8s dashboard 可视化客户端工具
  • golang开发语言
  • VScode Linux 版
  • kubebuilder

2.开始创建核心组件Pod的Webhook

        K8s的核心组件就那些几个:Deployment、Pod、Service、Ingress、ConfigMap、Secret、……

        在Kubebuilder的官方文档中,也有提到webhook的内容,但是比较简单,而且有些参考文章是基于CRD做的Webhook示例,此处我将演示核心组件Pod的Webhook。

创建K8s pod Webhook,kubernetes,kubernetes,docker,容器
图1 K8s核心组件

2.1.什么是Webhook

         从我的角度看,Webhook就是一个回调动作,举个例子方便理解:例如,我们希望在pod创建的时候,在annotation中增加一个标签,如author:geoff之类的,就可以利用这个webhook实现,当创建调用链完成之后,利用“回调”在这个创建动作之后丝滑地加入“增加annotation的额外动作”。可以结合Js的回调、java的AOP切片来理解。我们看看其中的原理:

创建K8s pod Webhook,kubernetes,kubernetes,docker,容器
图2 webhook基于k8s资源调用链中的admission 

        从图中可以看到,Webhook是在Mutating Admission或者Vaildating Admission阶段往Webhook发送一个“请求”并接受来自Webhook的“响应”。我们此时不妨大胆推测一下,实现这两点,要做些什么呢?我可以不负责任推测一下步骤:

  1. 在XXX Admission Controller配置一个请求,请求会往Webhook接受、处理并返回
  2. Webhook开发一个接收这个请求的Handler(类似Java的controller)

        事实也正如我们瞎想的哪样,确实核心就是这两个动作。这里我们看到,一共有两种Admission Controller,有点点区别:

  1. Mutating Admission Controller       # 可以修改资源
  2. Vaildating Admission Controller     # 验证资源,可以通过或者不通过

2.2.在本地k8s集群安装cert-manager

        这个算是提前准备了,需要注意的是,k8s集群的版本和cert-manage需要注意下,不然版本差别过多,可能会有些意想不到的问题

# 查看本地集群的版本
kind version

# 在集群上安装cert-maneger,其中v1.7.1就是cert-manager版本。
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.7.1/cert-manager.yaml

# 验证对应的资源实例是否安装成功
kubectl get all -n cert-manager
# 看对应的Pod是否被成功创建,可能一开始pod的replicas=0,因为集群节点是image container,下载image可能比较慢
kubectl get pods -n cert-manager
创建K8s pod Webhook,kubernetes,kubernetes,docker,容器
图3 检查cert-manager安装状况

        事实上,有时候,get pods可能会发现无资源,这可能是local cluster有问题,建议先删除,后新建:

# 先删除本地的集群
kind delete cluster --name k8s-local-dev 
# 再新建
## 创建集群配置文件,1个master node,1个worker node。
cat << EOF > kind-clusters-mutil-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
EOF

## start to create cluster
kind create cluster --name k8s-local-dev --config ./kind-clusters-mutil-config.yaml

## copy kubeconfig to Lens kubecofig
## 不然Lens在Kind集群更新后,配置文件没更新,会打不开
cp ~/.kube/config /mnt/c/Users/${current_user}/.kube/config

2.3.创建一个空的文件夹

# 创建一个空的文件节夹
mkdir create-pod-webhook-demo
# 进入空文件夹
cd create-pod-webhook-demo

2.4. 生成工程框架

# 生成工程框架
kubebuilder init --domain geoff.wh.demo --repo k8s-operator/kubebuilder-webhook-demo

         生成文件目录如下, 此处,我不赘述了,上一篇文章已经有比较清晰的介绍了。

➜  create-pod-webhook-demo tree
.
├── Dockerfile
├── Makefile
├── PROJECT
├── README.md
├── config
│   ├── default
│   │   ├── kustomization.yaml
│   │   ├── manager_auth_proxy_patch.yaml
│   │   └── manager_config_patch.yaml
│   ├── manager
│   │   ├── controller_manager_config.yaml
│   │   ├── 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_binding.yaml
│       └── service_account.yaml
├── go.mod
├── go.sum
├── hack
│   └── boilerplate.go.txt
└── main.go

6 directories, 25 files

2.5. 生成核心组件Pod的API

        从这里之前,和创建Operator的步骤基本是一致的,从这里开始,要开始有点不一样了

# 定义API,此处要实现Pod的Webhook,因此直接按Pod的Api创建
kubebuilder create api --group core --version v1 --kind Pod
# 之后的option我们不创建Resource和Controller,因此都选择n

        之后的option我们不创建Resource和Controller,因此都选择n

创建K8s pod Webhook,kubernetes,kubernetes,docker,容器
图3 不创建Resource和Controller,选n

2.6.生成Webhook

# --Kind这里,可以指定现存的PAAS组件,也可以
kubebuilder create webhook --group core --version v1 --kind Pod --defaulting --webhook-version v1

        生成webhook的代码结构如下: 

➜  create-pod-webhook-demo tree
.
├── Dockerfile
├── Makefile
├── PROJECT
├── README.md
├── api
│   └── v1
│       ├── pod_webhook.go
│       └── webhook_suite_test.go
├── bin
│   └── controller-gen
├── config
│   ├── certmanager
│   │   ├── certificate.yaml
│   │   ├── kustomization.yaml
│   │   └── kustomizeconfig.yaml
│   ├── default
│   │   ├── kustomization.yaml
│   │   ├── manager_auth_proxy_patch.yaml
│   │   ├── manager_config_patch.yaml
│   │   ├── manager_webhook_patch.yaml
│   │   └── webhookcainjection_patch.yaml
│   ├── manager
│   │   ├── controller_manager_config.yaml
│   │   ├── 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_binding.yaml
│   │   └── service_account.yaml
│   └── webhook
│       ├── kustomization.yaml
│       ├── kustomizeconfig.yaml
│       └── service.yaml
├── go.mod
├── go.sum
├── hack
│   └── boilerplate.go.txt
└── main.go

11 directories, 36 files

到这一步之后,我们直接转转入VScode开发

# 当前工程目录打开VScode
code .
创建K8s pod Webhook,kubernetes,kubernetes,docker,容器
图3 转入Vscode进行开发

2.7.开始实现Webhook相关代码

2.7.1.修改相关配置

        修改config/default/kustomize.yaml:

  1. 注释-crd 相关内容,因为我们没有CRD,只是实现Pod webhook
  2. 打开webhook、cert-manager相关配置,如下图所示
  3. 但是要注意属性缩进对齐,不然会报错
创建K8s pod Webhook,kubernetes,kubernetes,docker,容器
图4 修改config/default/kustomize.yaml的配置

        修改config/rdbc/kustomize.yaml:

1.注释 -role,这个也是和CRD相关,因为我们没有,所以注释掉

创建K8s pod Webhook,kubernetes,kubernetes,docker,容器
图4 注释config/rdbc/kustomize.yaml的role配置

        修改config/default/webhookcainjection_patch.yaml:

1.我们为了不搞这么复杂,我们只关心MutatingAdmision,因此可以直接注释掉ValidateAdmission

创建K8s pod Webhook,kubernetes,kubernetes,docker,容器
图5 注释config/default/webhookcainjection_patch.yaml中ValidateAdmission配置

2.7.2.修改代码

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

        修改api/v1/pod_webhook.go文件:

/*
Copyright 2023.

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 (
	"context"
	"encoding/json"
	"fmt"
	"net/http"

	corev1 "k8s.io/api/core/v1"
	"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
}


// 注释掉一开始生成的内容
// func (r *Pod) SetupWebhookWithManager(mgr ctrl.Manager) error {
// 	return ctrl.NewWebhookManagedBy(mgr).
// 		For(r).
// 		Complete()
// }

// // TODO(user): EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!

// var _ webhook.Defaulter = &Pod{}

// // Default implements webhook.Defaulter so a webhook will be registered for the type
// func (r *Pod) Default() {
// 	podlog.Info("default", "name", r.Name)

// 	// TODO(user): fill in your defaulting logic.
// }

        修改api/v1/xxx_suite_test.go

        全部注释掉,替换一个简单的测试Function。这个测试也是有讲究的,有兴趣可以研究一下。

/*
Copyright 2023.

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"
	"testing"
)

func TestFunc(t *testing.T) {
	// 打印
	fmt.Println("this is test function......")
}

        修改main.go文件:

import (
	......
    # 增加一个依赖包 
	v1 "k8s-operator/kubebuilder-webhook-demo/api/v1"
	......
)
......

// 注释掉
// if err = (&corev1.Pod{}).SetupWebhookWithManager(mgr); err != nil {
// 	setupLog.Error(err, "unable to create webhook", "webhook", "Pod")
// 	os.Exit(1)
// }

// 增加webhook注册
mgr.GetWebhookServer().Register("/mutate-core-v1-pod", &webhook.Admission{Handler: &v1.PodWebhookMutate{Client: mgr.GetClient()}})

......
创建K8s pod Webhook,kubernetes,kubernetes,docker,容器
图6 在main.go注册webhook endpoint

        修改Dockerfile

1.和上面一样,因为我们是创建Pod的Webhook,不需要自定义Controller,注释掉。

创建K8s pod Webhook,kubernetes,kubernetes,docker,容器
图7 注释Dockerfile中关于controller的内容

         修改Makefile文件

增加一个kind-load,方便将image上传到本地集群中

......
# local k8s cluster name
KUBE_CLUSTER = k8s-local-dev 
......
.PHONY: kind-load
kind-load: ## load the local image to the kind cluster
	kind load docker-image ${IMG} --name ${KUBE_CLUSTER}
......
创建K8s pod Webhook,kubernetes,kubernetes,docker,容器
图8 在Makefile增加kind-load命令

2.7.3.按照最新配置更新yaml

# 更新yaml,这里和之前main.go和xxx_webhook.go的注释有点关,生成的代码是依据注释实现的
make mainfests generate

        这一步比较重要,执行后会生成config/webhook/mainfests.yaml文件,切记执行

2.7.4.集群运行测试

2.7.4.1.修改Makefile文件

# 增加一个kind-load,方便将本地image上传到本地k8s集群中

......
# local k8s cluster name
KUBE_CLUSTER = k8s-local-dev 
......
.PHONY: kind-load
kind-load: ## load the local image to the kind cluster
    kind load docker-image ${IMG} --name ${KUBE_CLUSTER}
......

创建K8s pod Webhook,kubernetes,kubernetes,docker,容器
图9 增加kind-load,可以将image上传到kind创建的集群容器中
2.7.4.2.将应用部署到k8s集群上

以下是部署到集群的步骤:构建镜像、上传到集群容器中、部署

其中IMG是一个可以自行设置镜像名的变量,此处为:k8s-podwebhook-demo:1.0。

按如下命令执行后,即可在k8s集群中看到部署的CRD controller应用。

# 构建镜像(有时候会失败,可能是网络问题,多试几遍),IMG需要指定,不然后面部署还是有问题
make docker-build IMG=k8s-podwebhook-demo:1.0
# local镜像上传到Kind创建的k8s集群所在的所有node中(如果本地是)
make kind-load IMG=k8s-podwebhook-demo:1.0
# 部署controller
make deploy IMG=k8s-podwebhook-demo:1.0

        在这个过程中,bin/目录存在一些二进制的工具包,可以先删除,是之前make deploy时下载的,如果已存在,有可能会报错。

创建K8s pod Webhook,kubernetes,kubernetes,docker,容器
图10 bin目录应该要提前删除kustomize工具
创建K8s pod Webhook,kubernetes,kubernetes,docker,容器
图11 将webhook项目工程直接部署到本地k8s集群中
创建K8s pod Webhook,kubernetes,kubernetes,docker,容器
图12 在Lens上查看被部署到本地k8s集群的webhook应用
创建K8s pod Webhook,kubernetes,kubernetes,docker,容器
图13 在Lens上查看注册的MutatingAdmission实例

         这个MutatingAdmission的作用是注册一个endpoint,使得Pod在被创建后,往这个endpoint发送一个https请求(这也是为什么需要证书的原因)。事实上main.go中

// 增加webhook注册
mgr.GetWebhookServer().Register("/mutate-core-v1-pod", &webhook.Admission{Handler: &v1.PodWebhookMutate{Client: mgr.GetClient()}})

 这句就类似java controller,接受这个https的请求。

2.7.5.测试

2.7.5.1.准备测试Deployment的yaml配置

        这里需要说明,因为我们这里创建的是Pod Webhook,但是一般而言,我们不直接创建Pod,而是创建一个deployment,因为deployment最后也是会创建pod的。当然直接创建Pod也是可以的,这里创建一个pod-demo-ngnix.yaml文件去创建一个简单的pod,这个Pod只是一个基本的Ngnix镜像。

cat <<EOF >pod-demo-ngnix.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-demo-ngnix
  labels:
    role: myrole
spec:
  containers:
    - name: web
      image: nginx
      ports:
        - name: web
          containerPort: 80
          protocol: TCP
EOF
2.7.5.2.部署这个Pod demo
# 部署这个pod demo实例
kubectl apply -f ./pod-demo-ngnix.yaml
创建K8s pod Webhook,kubernetes,kubernetes,docker,容器
图14 在创建pod的时候,webhook接受到了请求并在日志中体现

 2.7.5.3.停止测试

# 删除测试Pod
kubectl delete -f ./pod-demo-ngnix.yaml
# undeploy这个webhook
make undeploy

参考文章

8. kubebuilder 进阶: webhook - Mohuishou

使用kubebuilder开发kubernetes核心资源的webhook | 老 宋

调试运行中的 Pod | Kubernetes文章来源地址https://www.toymoban.com/news/detail-672652.html

到了这里,关于创建K8s pod Webhook的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【云原生 | Kubernetes 系列】K8s 实战 如何给应用注入数据 II 将pod数据传递给容器

    在上一篇文章中,我们学习了针对容器设置启动时要执行的命令和参数、定义相互依赖的环境变量、为容器设置环境变量,三种设置方式,本篇文章,我们将继续学习数据的传递。 有两种方式可以将 Pod 和 Container 字段传递给运行中的容器: 环境变量 卷文件 这两种呈现 Pod

    2024年01月25日
    浏览(124)
  • 容器技术,1. Docker,2. Kubernetes(K8s):

    目录 容器技术 1. Docker: 2. Kubernetes(K8s): Docker和Kubernetes 容器的主要应用场景有哪些? 有效的将单个操作系统的资源划分到孤立的组中,以便更好的在孤立的组之间平衡有冲突的资源使用需求,这种技术就是容器技术。 容器技术指通过在物理主机操作系统上创建一个一个

    2024年02月11日
    浏览(66)
  • kubernetes(k8s)大白学习02:容器和docker基础、使用、架构学习

    简单说:容器(container)就是计算机上的一个沙盒进程,它与计算机上的所有其它进程相隔离。 这种隔离是怎么做到的呢?它利用了内核提供的 namespace 和 cgroup 这 2 种技术。这些技术能力在 Linux 中已经存在了很长时间。而 Docker 或容器技术致力于将这些功能更易于使用和更

    2024年02月07日
    浏览(66)
  • Kubernetes(K8s 1.28.x)部署---创建方式Docker(超详细)

    目录 一、基础环境配置(所有主机均要配置) 1、配置IP地址和主机名、hosts解析 2、关闭防火墙、禁用SELinux 3、安装常用软件 4、配置时间同步 5、禁用Swap分区 6、修改linux的内核参数 7、配置ipvs功能 二、容器环境操作 1、定制软件源 2、安装最新版docker 3、配置docker加速器 4、

    2024年02月09日
    浏览(43)
  • k8s 多容器pod进入指定容器

    kubectl exec -it prometheus-prometheus-server-697cccff9c-qtrf7 -c prometheus-server sh

    2024年02月14日
    浏览(57)
  • 【Kubernetes】K8s 查看 Pod 的状态

    NAME :Pod 的名称。 READY :代表 Pod 里面有几个容器,前面是启动的,后面是总数, 1 / 1 1/1 1/1 。 STATUS :就是当前 Pod 状态,最常见的就是 Running 正在运行,最期望的状态,只要不是 Running 的就说明有问题,就算是 Running 的就不一定没有问题。 状态 说明 Pending 挂起 在执行创建

    2024年01月15日
    浏览(92)
  • K8S | 容器和Pod组件

    对比软件安装和运行; 作为研发人员,通常自己电脑的系统环境都是非常复杂,在个人的习惯上,是按照下图的模块管理电脑的系统环境; 对于「基础设施」、「主机操作系统」、「系统软件」来说,通常只做配置修改; 对于自行安装的软件环境来说,个人通常这样分类:

    2024年02月11日
    浏览(53)
  • kubernetes(k8s) pod(资源限制、基础概念)

    目录  一、资源限制 1、概念 1.2、Pod和容器的资源请求和限制 1.3、CPU资源单位 1.4、内存资源单位 1.5、CPU和内存的Requests和Limits的特点 1.6、案例 二、pod 的两种使用方式 三、pod 资源共享 四、底层容器Pause 1、pause 共享资源 1.1、网络 1.2、存储 1.3、小结 2、Pause主要功能 3、Pod

    2024年02月05日
    浏览(71)
  • Kubernetes(k8s)核心资源解析:Pod详解

    💖The Begin💖点点关注,收藏不迷路💖 Pod是Kubernetes中最小的调度单元,它可以包含一个或多个容器。Pod中的所有容器共享网络和存储卷,它们一起运行在同一个节点上。Pod提供了一种抽象层,使得容器可以作为一个逻辑单元来管理。 Pod中的容器共享IP地址、端口空间和存储

    2024年04月11日
    浏览(70)
  • K8s Pod状态与容器探针

    Pod创建过程如上图所示,首先用户向apiserver发送创建pod的请求,apiserver收到用于创建pod请求后,对应会对该用户身份信息进行验证,该用户是否是合法的用户,是否具有创建pod的权限,如果能够通过apiserver的验证,则进行下一步,对用户提交的资源进行准入控制,所谓准入控

    2024年02月07日
    浏览(90)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包