4.3 注入sidecar的mutatePod注入函数编写

本节重点总结 :

  • serveMutate编写
    • 准入控制请求参数校验
    • 根据annotation标签判断是否需要注入sidecar
    • mutatePod 注入函数编写
    • 生成注入容器和volume的patch函数

serveMutate编写

普通校验请求

  • serveMutate方法
  • body是否为空
  • req header的Content-Type 是否为application/json
	var body []byteif r.Body != nil {if data, err := ioutil.ReadAll(r.Body); err == nil {body = data}}if len(body) == 0 {glog.Error("empty body")http.Error(w, "empty body", http.StatusBadRequest)return}// verify the content type is accuratecontentType := r.Header.Get("Content-Type")if contentType != "application/json" {glog.Errorf("Content-Type=%s, expect application/json", contentType)http.Error(w, "invalid Content-Type, expect `application/json`", http.StatusUnsupportedMediaType)return}

准入控制请求参数校验

  • 构造准入控制的审查对象 包括请求和响应
  • 然后使用UniversalDeserializer解析传入的申请
  • 如果出错就设置响应为报错的信息
  • 没出错就调用mutatePod生成响应
	// 构造准入控制器的响应var admissionResponse *v1beta1.AdmissionResponse// 构造准入控制的审查对象 包括请求和响应// 然后使用UniversalDeserializer解析传入的申请// 如果出错就设置响应为报错的信息// 没出错就调用mutatePod生成响应ar := v1beta1.AdmissionReview{}if _, _, err := deserializer.Decode(body, nil, &ar); err != nil {glog.Errorf("Can't decode body: %v", err)admissionResponse = &v1beta1.AdmissionResponse{Result: &metav1.Status{Message: err.Error(),},}} else {admissionResponse = ws.mutatePod(&ar)}
  • 解析器使用UniversalDeserializer D:\go_path\pkg\mod\k8s.io\apimachinery@v0.22.1\pkg\runtime\serializer\codec_factory.go
package mainimport ("encoding/json""fmt""github.com/golang/glog""gopkg.in/yaml.v2""io/ioutil""k8s.io/api/admission/v1beta1"corev1 "k8s.io/api/core/v1"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/apimachinery/pkg/runtime""k8s.io/apimachinery/pkg/runtime/serializer""net/http"
)var (runtimeScheme = runtime.NewScheme()codecs        = serializer.NewCodecFactory(runtimeScheme)deserializer  = codecs.UniversalDeserializer()// (https://github.com/kubernetes/kubernetes/issues/57982)defaulter = runtime.ObjectDefaulter(runtimeScheme)
)

写入响应

  • 构造最终响应对象 admissionReview
  • 给response赋值
  • json解析后用 w.write写入
	// 构造最终响应对象 admissionReview// 给response赋值// json解析后用 w.write写入admissionReview := v1beta1.AdmissionReview{}if admissionResponse != nil {admissionReview.Response = admissionResponseif ar.Request != nil {admissionReview.Response.UID = ar.Request.UID}}resp, err := json.Marshal(admissionReview)if err != nil {glog.Errorf("Can't encode response: %v", err)http.Error(w, fmt.Sprintf("could not encode response: %v", err), http.StatusInternalServerError)}glog.Infof("Ready to write reponse ...")if _, err := w.Write(resp); err != nil {glog.Errorf("Can't write response: %v", err)http.Error(w, fmt.Sprintf("could not write response: %v", err), http.StatusInternalServerError)}

mutatePod 注入函数编写

  • 将请求中的对象解析为pod,如果出错就返回
	// 将请求中的对象解析为pod,如果出错就返回req := ar.Requestvar pod corev1.Podif err := json.Unmarshal(req.Object.Raw, &pod); err != nil {glog.Errorf("Could not unmarshal raw object: %v", err)return &v1beta1.AdmissionResponse{Result: &metav1.Status{Message: err.Error(),},}}

是否需要注入判断

	// 是否需要注入判断if !mutationRequired(ignoredNamespaces, &pod.ObjectMeta) {glog.Infof("Skipping mutation for %s/%s due to policy check", pod.Namespace, pod.Name)return &v1beta1.AdmissionResponse{Allowed: true,}}
  • mutationRequired判断函数,判断这个pod资源要不要注入
    1. 如果pod在高权限的ns中,不注入
    1. 如果pod annotations中 标记为已注入就不再注入了
    1. 如果pod annotations中 配置不愿意注入就不注入
// 判断这个pod资源要不要注入
// 1. 如果pod在高权限的ns中,不注入
// 2. 如果pod annotations中 标记为已注入就不再注入了
// 3. 如果pod annotations中 配置不愿意注入就不注入
func mutationRequired(ignoredList []string, metadata *metav1.ObjectMeta) bool {// skip special kubernete system namespacesfor _, namespace := range ignoredList {if metadata.Namespace == namespace {glog.Infof("Skip mutation for %v for it's in special namespace:%v", metadata.Name, metadata.Namespace)return false}}annotations := metadata.GetAnnotations()if annotations == nil {annotations = map[string]string{}}// 如果 annotation中 标记为已注入就不再注入了status := annotations[admissionWebhookAnnotationStatusKey]if strings.ToLower(status) == "injected" {return false}// 如果pod中配置不愿意注入就不注入switch strings.ToLower(annotations[admissionWebhookAnnotationInjectKey]) {default:return falsecase "true":return false}
}
  • 相关的常量定义
const (// 代表这个pod是否要注入  = ture代表要注入admissionWebhookAnnotationInjectKey = "sidecar-injector-webhook.xiaoyi/need_inject"// 代表判断pod已经注入过的标志 = injected代表已经注入了,就不再注入admissionWebhookAnnotationStatusKey = "sidecar-injector-webhook.xiaoyi/status"
)// 为了安全,不给这两个ns中的pod注入 sidecar
var ignoredNamespaces = []string{metav1.NamespaceSystem,metav1.NamespacePublic,
}

添加默认的配置

  • https://github.com/kubernetes/kubernetes/pull/58025
defaulter = runtime.ObjectDefaulter(runtimeScheme)
func applyDefaultsWorkaround(containers []corev1.Container, volumes []corev1.Volume) {defaulter.Default(&corev1.Pod{Spec: corev1.PodSpec{Containers: containers,Volumes:    volumes,},})
}

定义pathoption

type patchOperation struct {Op    string      `json:"op"`              // 动作Path  string      `json:"path"`            // 操作的pathValue interface{} `json:"value,omitempty"` // 值
}

生成容器端的patch函数

// 添加容器的patch
// 如果是第一个patch 需要在path末尾添加 /-
func addContainer(target, added []corev1.Container, basePath string) (patch []patchOperation) {first := len(target) == 0var value interface{}for _, add := range added {value = addpath := basePathif first {first = falsevalue = []corev1.Container{add}} else {path = path + "/-"}patch = append(patch, patchOperation{Op:    "add",Path:  path,Value: value,})}return patch
}

生成添加volume的patch函数

func addVolume(target, added []corev1.Volume, basePath string) (patch []patchOperation) {first := len(target) == 0var value interface{}for _, add := range added {value = addpath := basePathif first {first = falsevalue = []corev1.Volume{add}} else {path = path + "/-"}patch = append(patch, patchOperation{Op:    "add",Path:  path,Value: value,})}return patch
}

更新annotation 的patch

func updateAnnotation(target map[string]string, added map[string]string) (patch []patchOperation) {for key, value := range added {if target == nil || target[key] == "" {target = map[string]string{}patch = append(patch, patchOperation{Op:   "add",Path: "/metadata/annotations",Value: map[string]string{key: value,},})} else {patch = append(patch, patchOperation{Op:    "replace",Path:  "/metadata/annotations/" + key,Value: value,})}}return patch
}
  • 最终的patch调用
func createPatch(pod *corev1.Pod, sidecarConfig *Config, annotations map[string]string) ([]byte, error) {var patch []patchOperationpatch = append(patch, addContainer(pod.Spec.Containers, sidecarConfig.Containers, "/spec/containers")...)patch = append(patch, addVolume(pod.Spec.Volumes, sidecarConfig.Volumes, "/spec/volumes")...)patch = append(patch, updateAnnotation(pod.Annotations, annotations)...)return json.Marshal(patch)
}

调用patch 生成patch option

  • mutatePod方法中
	annotations := map[string]string{admissionWebhookAnnotationStatusKey: "injected"}patchBytes, err := createPatch(&pod, ws.sidecarConfig, annotations)if err != nil {return &v1beta1.AdmissionResponse{Result: &metav1.Status{Message: err.Error(),},}}glog.Infof("AdmissionResponse: patch=%v\n", string(patchBytes))return &v1beta1.AdmissionResponse{Allowed: true,Patch:   patchBytes,PatchType: func() *v1beta1.PatchType {pt := v1beta1.PatchTypeJSONPatchreturn &pt}(),}return nil

本节重点总结 :

  • serveMutate编写
    • 准入控制请求参数校验
    • 根据annotation标签判断是否需要注入sidecar
    • mutatePod 注入函数编写
    • 生成注入容器和volume的patch函数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/69493.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

win10向windows server服务器传输文件

win10向windows server服务器传输文件 遇到无法直接拖动文件进行传输时 解决方案: 1.点击显示选项 2.点击本地资源-详细信息 3.在窗口中选择你需要共享的磁盘 4.然后远程连接到Windows server服务器 5.登录Windows server服务器后,在此电脑下就能看…

为AI聊天工具添加一个知识系统 之93 详细设计之34 Derivation 之 8 实现和平台

本文要点 要点 插入话题:实现 “实现”作为一个普通名词(一般术语)应该遵循第一性第二性第三性原则。其 第一性第二性第三性 分别是:完整性/鲁棒性/健壮性 ,三者 分别注重 性能/功能/能力。即 首先是 实现完整性的性…

ASP.NET Core SignalR的协议协商

SignalR支持多种服务器推送方式:Websocket、Server-Sent Events、长轮询。默认按顺序尝试。F12查看协商过程。websocket和HTTP是不同的协议,为什么能用同一个端口。在【开发人员工具】的【网络】页签中看WebSocket通信过程。 协议协商问题 集群中协议协…

Sinusoidal(正弦曲线)位置编码公式详细推导过程

Sinusoidal(正弦曲线)位置编码公式推导 参考链接 Transformer升级之路:1、Sinusoidal位置编码追根溯源 1. 前置数学的基本概念 1.1 内积 定义: 内积是两个向量之间的一种运算,其结果为一个标量。公式: 对于向量 a [ a 1 , …

仿 RabbitMQ 实现的简易消息队列

文章目录 项目介绍开放环境第三⽅库介绍ProtobufMuduo库 需求分析核⼼概念实现内容 消息队列系统整体框架服务端模块数据管理模块虚拟机数据管理模块交换路由模块消费者管理模块信道(通信通道)管理模块连接管理模块 客户端模块 公共模块日志类其他工具类…

GOland的context的使用

超时控制 在 HTTP 请求、数据库查询或 RPC 调用等操作中,防止请求长时间阻塞。 package mainimport ("context""fmt""time" )func main() {// 设置 2 秒超时ctx, cancel : context.WithTimeout(context.Background(), 2*time.Secon…

openssl使用

openssl使用 提取密钥对 数字证书pfx包含公钥和私钥,而cer证书只包含公钥。提取需输入证书保护密码 openssl pkcs12 -in xxx.pfx -nocerts -nodes -out pare.key提取私钥 openssl rsa -in pare.key -out pri.key提取公钥 openssl rsa -in pare.key -pubout -ou…

CANoe查看CAN报文发送周期

在CANoe软件中,Analysis -> Select other options 下的 Toggle Grid 和 Toggle Samples 选项确实用于控制分析窗口中的显示方式和采样行为,从而更清晰地查看CAN报文周期。 Toggle Grid(切换网格) 功能:启用网格线…

【Pytorch函数】PyTorch随机数生成全解析 | torch.rand()家族函数使用指南

🌟 PyTorch随机数生成全解析 | torch.rand()家族函数使用指南 🌟 📌 一、核心函数参数详解 PyTorch提供多种随机数生成函数(注意:无直接torch.random()函数),以下是常用函数及参数:…

【Go语言圣经】第八节:Goroutines和Channels

DeepSeek 说 Goroutines 和 Channels 最近非常流行询问DeepSeek某些相关概念或热点的解释,因此在开始系统性地学习《Go语言圣经》之前,我首先向DeepSeek进行了提问。具体的Prompt如下: 有关Golang当中的Goroutines和Channels,我现…

从零开始掌握Python人工智能:实战案例、学习路径与职业建议

想必大家最近也都关注了实时,最近AI及deep seek可谓是火遍全球啊!小米总裁还说:大学生应该赶紧学会使用人工智能,你越早学会,你就比其他人更有优势。我也这样的感觉,deep seek现在可以和很多软件运用,完成绝…

Java 魔法:精准掌控 PDF 合同模板,指定页码与关键字替换签章日期

朋友们!在实际业务场景中,经常会碰到处理 PDF 合同模板的需求,要在几十页的合同里对指定页面替换公章、签名和日期,还涉及多人签名以及多个公司盖公章。下面就给大家分享两种用 Java 处理这类问题的方法,一种是通过指定…

e2studio开发RA4M2(10)----定时器AGT输出PWM

e2studio开发RA4M2.10--定时器AGT输出PWM 概述视频教学样品申请硬件准备参考程序源码下载选择计时器新建工程工程模板保存工程路径芯片配置工程模板选择时钟设置SWD调试口设置GPIO口配置AGT定时器AGT定时器属性配置初始化AGT启动AGT PWM模块AGTIO 和 AGTO演示 概述 AGT模块是R…

使用PyCharm进行Django项目开发环境搭建

如果在PyCharm中创建Django项目 1. 打开PyCharm,选择新建项目 2.左侧选择Django,并设置项目名称 3.查看项目解释器初始配置 4.新建应用程序 执行以下操作之一: 转到工具| 运行manage.py任务或按CtrlAltR 在打开的manage.pystartapp控制台…

【Java基础】为什么不支持多重继承?方法重载和方法重写之间区别、Exception 和 Error 区别?

Hi~!这里是奋斗的明志,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~ 🌱🌱个人主页:奋斗的明志 🌱🌱所属专栏:Java基础面经 📚本系列文章为个…

【Jetson Nano安装gpu版pytroch1.7torchvision0.8.1 in python3.8 跑 Ultralytics YOLO】

文章目录 1. 系统环境2. 安装torch1.7.03. 安装torchvision0.8.14. 参考文献 1. 系统环境 笔者的jetson nano b01的系统版本如下: 环境版本JetPack4.4Ubuntu18.04python(Miniforge3环境)3.8python3(系统自带环境)3.6.9python2(系统自带环境)2.7 由于Ultralytics …

bladeX微服务框架如何修改nacos分组

nacos中注册的服务他的分组(分组名称)怎么修改 在org.springblade.common.launch // 指定注册IP PropsUtil.setProperty(props, "spring.cloud.nacos.discovery.ip", "127.0.0.1"); // 指定注册端口 PropsUtil.setProperty(props, &…

大数据项目2a:基于spark的电影推荐和分析系统设计与实现

1、项目目的 本项目的目的是设计并实现一个基于Spark的电影推荐系统,以应对大数据环境下电影推荐服务的挑战。通过整合电影、评分和用户数据集,并利用SparkSql框架进行高效处理,系统能够为用户提供个性化的电影推荐。项目采用多种先进技术&…

机器学习常用包matplotlib篇(四)绘图规范

前言 为了让 Matplotlib 绘图代码更规范、易读,且为后期图形完善预留空间,建议遵循一些规范绘图方法。😉 1.管理图形对象 建议使用 plt.figure() 或者 plt.subplots() 管理完整的图形对象,而非直接用 plt.plot(...) 绘图。这样能…

LVGL4种输入设备详解(触摸、键盘、实体按键、编码器)

lvgl有触摸、键盘、实体按键、编码器四种输入设备 先来分析一下这四种输入设备有什么区别 (1)LV_INDEV_TYPE_POINTER 主要用于触摸屏 用到哪个输入设备保留哪个其他的也是,保留触摸屏输入的任务注册,其它几种种输入任务的注册&…