Kubernetes开发(6)-MutatingAdmissionWebhook练手
发布日期:2021-06-29 11:37:49 浏览次数:2 分类:技术文章

本文共 4357 字,大约阅读时间需要 14 分钟。

之前写了一个简单的webhook 的tls server,并且写了一个简单的validate的api 用于实现资源的拦截。之前有提到webhook有两类,第二类就是mutatingadmissionwebhook,即对资源进行修改,仔细想想不会太意外,比如istio本质上不就是mutatingadmissionwebhook么,在启动的时候直接sidecar方式插入一个container,然后通过该container进行各类服务收集/治理,那练手的话可以自己插入一个redis 容器,模拟istio的sidecar容器创建。

同样,代码更新在了里面

思路

同样整理一下思路先:

  • 和validateadmission 不一样,mutateadmission 需要的是对资源的修改,所以需要先定义一个修改操作的结构体,即所谓的patch:
  • 由于需要插入的是一个sidecar容器,所以需要先定义一个sidecar的容器资源
  • 然后webhook拦截api-server的请求,获取admissionreview,获取创建的资源信息
  • 然后对admissionreview 进行patch 操作,将sidecar的容器注入进去。
  • 然后回调api-server

理完思路写代码,先看下patch的结构体

// 定义patch对象type patchOperation struct {	Op    string      `json:"op"`	Path  string      `json:"path"`	Value interface{} `json:"value,omitempty"`}

op是操作的类型,比如add,del, path是修改的资源对象的路径,value是修改资源对象的值。

然后将需要插入的sidecar 容器解析出来

// 需要插入的sidecar 容器type sideConfig struct {	Containers []corev1.Container `yaml:"containers"`}func loadSideCarConfig() (*sideConfig, error) {	data, err := ioutil.ReadFile("/config/sidecar.yaml")	if err != nil {		return nil, err	}	var cfg sideConfig	if err := yaml.Unmarshal(data, &cfg); err != nil {		return nil, err	}	return &cfg, nil}

现在有了具体的sidecar后,就只需要将插入sidecar 容器这个动作封装成patch ,以json序列化一下然后返回给api-server。

// 返回具体的admissionresponse	return &admissionv1.AdmissionResponse{		Allowed: allowed,		Patch:   patchBytes,		PatchType: func() *admissionv1.PatchType {			pt := admissionv1.PatchTypeJSONPatch			return &pt		}(),	}

之后进行镜像的打包和上传

docker build -t registry.cn-shanghai.aliyuncs.com/zyxpaomian/webhook:v1.8 .docker push registry.cn-shanghai.aliyuncs.com/zyxpaomian/webhook:v1.8

定义一个admissionwebhook, 只正对deployment和service的创建做拦截

apiVersion: admissionregistration.k8s.io/v1kind: MutatingWebhookConfigurationmetadata:  name: admission-registry-mutatewebhooks:- name: zyx.test.admission-registry-mutate  clientConfig:    service:      namespace: default      name: admission-registry      path: "/v1/api/mutate"    caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURuakNDQW9hZ0F3SUJBZ0lVT2RVeWVCenVVcFdIenFvMGczOE5XeE1SNm9jd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1p6RUxNQWtHQTFVRUJoTUNRMDR4RVRBUEJnTlZCQWdUQ0ZOb1lXNW5hR0ZwTVJFd0R3WURWUVFIRXdoVAphR0Z1WjJoaGFURU1NQW9HQTFVRUNoTURhemh6TVE4d0RRWURWUVFMRXdaVGVYTjBaVzB4RXpBUkJnTlZCQU1UCkNtdDFZbVZ5Ym1WMFpYTXdIaGNOTWpFd05USTBNRGMwT1RBd1doY05Nall3TlRJek1EYzBPVEF3V2pCbk1Rc3cKQ1FZRFZRUUdFd0pEVGpFUk1BOEdBMVVFQ0JNSVUyaGhibWRvWVdreEVUQVBCZ05WQkFjVENGTm9ZVzVuYUdGcApNUXd3Q2dZRFZRUUtFd05yT0hNeER6QU5CZ05WQkFzVEJsTjVjM1JsYlRFVE1CRUdBMVVFQXhNS2EzVmlaWEp1ClpYUmxjekNDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFLTWJLT0Q5WGMzMDhlWlQKK0J2MGYzR3QxTGtzWk1jUXNUUG5rQXpWeVRQSDdFSkpORkVoVzI0UE8yNzgvaTNWcEdPNU12MVZCcW1rcGwrSgorZ1dwZW5TSDNIbTdsOTZmckt4TmRGWG94Y3VLaWNPOHhvVUVxWCt0cVIvR0toUGYrcjBCWXFUR1o1aVVCZGdVCjU0STJIQjREc1Exc0lCY1JBUms5WVJ5ZjRLYXRZVVEzdGRuNFRyNmFhUXg5OE9Gd1hUNXpiNktINVQ2MTNKdk8KUExpV0JNWUxUZG5WZ256ZzVXeDUreDkvV0FtaTJSK0JjTllLUjY0RWgzeWJZam5NeGtGL1JEMTZPSTlFOTJNRApEaVB6U09oemplQ3RIY1NRcStpTllIQzhzSUJlRFlxL256bTFDR0hTL1NpMDdZVFBjZTBXeE5RelRpMlM2dlZXCkdrWGVPaWNDQXdFQUFhTkNNRUF3RGdZRFZSMFBBUUgvQkFRREFnRUdNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHcKSFFZRFZSME9CQllFRlB0S2U2TXFoTjlLaEJ5S3Ntdy9sR3pZd25iL01BMEdDU3FHU0liM0RRRUJDd1VBQTRJQgpBUUFqNnVyVTVhS0I5MWZuQTF2dE1DVjZRVHFmenMrd1dFcHZVbElXOHdZYXVydDZPWUc1YkxFSHoyRUJJRXplCjMvcGM4ZUkvamJSU0JNZDJGbk9Sa0pVTmh5MDBBZE05MTRFUFo5Y0FIOFpGUVI1UTZCUmw1Qnl6Mk5jOHN3dGMKMmtraW0vWUJ4TkFFYnFLQjBhTmw0TW5LbTc3TzgzSXpwREN2SzBWdlRCVXJVYnlzd1l6d0lCaEZxSTl5ZUo2Zgo1U1JpemdrUHVYRG1qSlZiN092dzNTNkxRT1o4VmdJRS9wZGJvRTBsTHpmZ2pROWVDVFM0ZmRXSE9oNGp1TXJMCklqeG1pMHhOVVVkTXdPeFNvQlJKa3J3eU1Fa1FoN2swYmZROFdsRkFNenVST29RVmVraU1BNkhLeDdQOFd1UmUKYzhKRkVOVmk5VEVMTXkwWHpJNWhoOVlwCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K  rules:    - operations: [ "CREATE" ]      apiGroups: ["apps", ""]      apiVersions: ["v1"]      resources: ["deployments","services"]  admissionReviewVersions: [ "v1" ]  sideEffects: None

进行测试, 和之前一样编写一个deployment,里面只有一个nginx的container:

apiVersion: apps/v1kind: Deploymentmetadata:  name: nginx-deployment  labels:    app: nginxspec:  replicas: 3  selector:    matchLabels:      app: nginx  template:    metadata:      labels:        app: nginx    spec:      containers:      - name: nginx        image: docker.io/nginx:latest        ports:        - containerPort: 80

然后进行apply:

结果
可以看到这个deployment 下面有2个container 在初始化,这第二个container 就是mutatingadmission 拦截后注入的sidecar 容器。

个人公众号, 分享一些日常开发,运维工作中的日常以及一些学习感悟,欢迎大家互相学习,交流

在这里插入图片描述

转载地址:https://blog.csdn.net/zyxpaomian/article/details/117443980 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:微信小程序 - Unhandled promise rejection TypeError: r.Canvas is not a constructor
下一篇:Kubernetes开发(5)-validateadmission练手

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2024年04月20日 22时06分35秒