5. informer源码分析-概要分析

news/发布时间2024/6/17 20:37:44

k8s client-go k8s informers 实现了持续获取集群的所有资源对象监听集群的资源对象变化功能,并在本地维护了全量资源对象的内存缓存,以减少对 apiserver、对 etcd 的请求压力。Informers 在启动的时候会首先在客户端调用 List 接口来获取全量的对象集合,然后通过 Watch 接口来获取增量的对象,然后更新本地缓存

1. k8s informer 概述

我们都知道可以使用 k8s 的 Clientset 来获取所有的原生资源对象,那么怎么能持续的获取集群的所有资源对象,或监听集群的资源对象数据的变化呢?这里不需要轮询去不断执行 List 操作,而是调用 Watch 接口,即可监听资源对象的变化,当资源对象发生变化,客户端即可通过 Watch 接口收到资源对象的变化。

Watch 接口虽然可以直接使用,但一般情况下很少直接使用,因为往往由于集群中的资源较多,我们需要自己在客户端去维护一套缓存,而这个维护成本比较大。

也是因为如此,client-go 提供了自己的实现机制,Informers 应运而生。informers 实现了持续获取集群的所有资源对象、监听集群的资源对象变化功能,并在本地维护了全量资源对象的内存缓存,以减少对 apiserver、对 etcd 的请求压力。Informers 在启动的时候会首先在客户端调用 List 接口来获取全量的对象集合,然后通过 Watch 接口来获取增量的对象,然后更新本地缓存

此外 informers 也有很强的健壮性,当长期运行的 watch 连接中断时,informers 会尝试拉起一个新的 watch 请求来恢复连接,在不丢失任何事件的情况下恢复事件流。另外,informers 还可以配置一个重新同步的周期参数,每间隔该周期,informers 就会重新 List 全量数据

在 informers 的使用上,通常每个 GroupVersionResource(GVR)只实例化一个 informers,但有时候我们在一个应用中往往会在多个地方对同一种资源对象都有 informer 的需求,所以就有了共享 informer,即 SharedInformerFactory。所以可以通过使用 SharedInformerFactory 来实例化 informers,这样本地内存缓存就只有一份,通知机制也只有一套,大大提高了效率,减少了资源浪费。

1.1 k8s informer 架构

在这里插入图片描述

1.2 k8s informer 包含部件

k8s client-go informer 主要包括以下部件:

  • Reflector:Reflector 从 kube-apiserver 中 list&watch 资源对象,然后调用 DeltaFIFO 的 Add/Update/Delete/Replace 方法将资源对象及其变化包装成 Delta 并将其丢到 DeltaFIFO 中;
  • DeltaFIFO:DeltaFIFO 中存储着一个 map 和一个 queue,即map[object key]Deltas 以及 object key 的 queue,Deltas 为 Delta 的切片类型,Delta 装有对象及对象的变化类型(Added/Updated/Deleted/Sync) ,Reflector 负责 DeltaFIFO 的输入,Controller 负责处理 DeltaFIFO 的输出;
  • Controller:Controller 从 DeltaFIFO 的 queue 中 pop 一个 object key 出来,并获取其关联的 Deltas 出来进行处理,遍历 Deltas,根据对象的变化更新 Indexer 中的本地内存缓存,并通知 Processor,相关对象有变化事件发生;
  • Processor:Processor 根据对象的变化事件类型,调用相应的 ResourceEventHandler 来处理对象的变化;
  • Indexer:Indexer 中有 informer 维护的指定资源对象的相对于 etcd 数据的一份本地内存缓存,可通过该缓存获取资源对象,以减少对 apiserver、对 etcd 的请求压力;
  • ResourceEventHandler:用户根据自身处理逻辑需要,注册自定义的的 ResourceEventHandler,当对象发生变化时,将触发调用对应类型的 ResourceEventHandler 来做处理。

根据 informer 架构,对 k8s informer 的分析将分为以下几部分进行,本篇为概要分析:
(1)informer概要分析;
(2)informer之初始化与启动分析;
(3)informer之Reflector分析;
(4)informer之DeltaFIFO分析;
(5)informer之Controller&Processor分析;
(6)informer之Indexer分析;


2. informer 使用示例代码

使用大致过程如下:
(1)构建与 kube-apiserver 通信的 config 配置;
(2)初始化与 apiserver 通信的 clientset;
(3)利用 clientset 初始化 shared informer factory 以及 pod informer;
(4)注册 informer 的自定义 ResourceEventHandler;
(5)启动 shared informer factory,开始 informer 的 list & watch 操作;
(6)等待 informer 从 kube-apiserver 同步资源完成,即 informer 的 list 操作获取的对象都存入到 informer 中的 indexer 本地缓存中;
(7)创建 lister,可以从 informer 中的 indexer 本地缓存中获取对象;

func main() {// 自定义与kube-apiserver通信的config配置master := "192.168.1.10" // apiserver urlkubeconfig := "/.kube/config"config, err = clientcmd.BuildConfigFromFlags(master, kubeconfig)if err != nil {klog.Fatalf("Failed to create config: %v", err)}// 或使用k8s serviceAccount机制与kube-apiserver通信// config, err = rest.InClusterConfig()// 初始化与apiserver通信的clientsetclientset, err := kubernetes.NewForConfig(config)if err != nil {klog.Fatalf("Failed to create client: %v", err)}// 初始化shared informer factory以及pod informerfactory := informers.NewSharedInformerFactory(clientset, 30*time.Second)podInformer := factory.Core().V1().Pods()informer := podInformer.Informer()// 注册informer的自定义ResourceEventHandlerinformer.AddEventHandler(cache.ResourceEventHandlerFuncs{AddFunc:    xxx,UpdateFunc: xxx,DeleteFunc: xxx,})// 启动shared informer factory,开始informer的list & watch操作stopper := make(chan struct{})go factory.Start(stopper)// 等待informer从kube-apiserver同步资源完成,即informer的list操作获取的对象都存入到informer中的indexer本地缓存中 // 或者调用factory.WaitForCacheSync(stopper)if !cache.WaitForCacheSync(stopper, informer.HasSynced) {runtime.HandleError(fmt.Errorf("Timed out waiting for caches to sync"))return}// 创建listerpodLister := podInformer.Lister()// 从informer中的indexer本地缓存中获取对象podList, err := podLister.List(labels.Everything())if err != nil {fmt.Println(err)}}

以上只是对 K8s informer 做了简单的介绍,以及简单的写了一下如何使用 informer 的示例代码,后面将开始对 informer 的各个部件做进一步的源码分析。

从图中可以看出,k8s informer主要包括以下几个部分:

2.1.Reflector

(1)Reflector 从 kube-apiserver 中 list 资源对象列表,然后调用 DeltaFIFO 的 Replace 方法将 object 包装成 Sync/Deleted 类型的 Delta 丢进 DeltaFIFO 中;

(2)Reflector 从 kube-apiserver 中 watch 资源对象的变化,然后调用 DeltaFIFO 的 Add/Update/Delete 方法将 object 包装成 Added/Updated/Deleted 类型的 Delta 丢到 DeltaFIFO 中;

2.2.DeltaFIFO

DeltaFIFO 中存储着一个 map 和一个 queue;

(1)其中 queue 可以看成是一个先进先出队列,一个 object 进入 DeltaFIFO 中,会判断 queue 中是否已经存在该 object key,不存在则添加到队尾;

(2)map 即 map[object key]Deltas,是 object key 和 Deltas 的映射,Deltas 是 Delta 的切片类型,Delta 中存储着 DeltaType 和 object;另外,Deltas 最末尾的两个 Deleted 类型的 Delta 会被去重;

DeltaType 有4种,分别是 Added、Updated、Deleted、Sync

2.3.Controller

Controller 从 DeltaFIFO 的 queue 中 pop 一个 object key 出来,并从 DeltaFIFO 的 map 中获取其对应的 Deltas 出来进行处理,遍历 Deltas,根据 object 的变化类型更新 Indexer 本地缓存,并通知 Processor 相关对象有变化事件发生:

(1)如果 DeltaType 是 Deleted,则调用 Indexer 的 Delete 方法,将 Indexer 本地缓存中的 object 删除,并构造 deleteNotification struct,通知 Processor 做处理;

(2)如果 DeltaType 是 Added/Updated/Sync,调用 Indexer 的 Get 方法从 Indexer 本地缓存中获取该对象,存在则调用 Indexer 的 Update 方法来更新 Indexer 缓存中的该对象,随后构造 updateNotification struct,通知 Processor 做处理;如果 Indexer 中不存在该对象,则调用 Indexer 的 Add 方法将该对象存入本地缓存中,并构造 addNotification struct,通知 Processor 做处理;

2.4.Processor

Processor 根据 Controller 的通知,即根据对象的变化事件类型(addNotification、updateNotification、deleteNotification),调用相应的 ResourceEventHandler(addFunc、updateFunc、deleteFunc)来处理对象的变化。

2.5.Indexer

Indexer 中有 informer 维护的指定资源对象的相对于 etcd 数据的一份本地内存缓存,可通过该缓存获取资源对象,以减少对 apiserver、对etcd 的请求压力。

informer 所维护的缓存依赖于 threadSafeMap 结构体中的 items 属性,其本质上是一个用 map 构建的键值对,资源对象都存在 items 这个 map 中,key 为资源对象的 namespace/name 组成,value 为资源对象本身,这些构成了 informer 的本地缓存。

Indexer 除了维护了一份本地内存缓存外,还有一个很重要的功能,便是索引功能了。索引的目的就是为了快速查找,比如我们需要查找某个 node 节点上的所有 pod、查找某个命名空间下的所有 pod 等,利用到索引,可以实现快速查找。关于索引功能,则依赖于 threadSafeMap 结构体中的 indexers 与 indices 属性。

2.6.ResourceEventHandler

用户根据自身处理逻辑需要,注册自定义的的 ResourceEventHandler,当对象发生变化时,将触发调用对应类型的 ResourceEventHandler 来做处理。

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

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

相关文章

idea如何建立一个springboot项目

1.打开File -New-Project 2.填写相关信息,Name:### Type:Maven Croup、Artifact、java 版本 注:此时,第一次打开可能会报错,说版本不匹配。注意下方的两个红框,将Server URL的地址改为“https://start.aliyun.com ”…

【蓝桥杯单片机入门记录】动态数码管

目录 一、数码管动态显示概述 二、动态数码管原理图 (1)原理图 (2)动态数码管如何与芯片相连 (3)“此器件” ——>锁存器74HC573 三、动态数码管显示例程 (1)例程1&#xf…

【架构】GPU架构总结

文章目录 GPU架构GPU渲染内存架构Streaming Multiprocessor(SM)CUDA CoreTensor CoreRT CoreCPU-GPU异构系统GPU资源管理模型 GPU架构演进G80 架构Fermi 架构Maxwell架构Tesla架构Pascal架构Volta 架构Turing架构Ampere 架构Hopper架构 参考文献 GPU架构 主要组成包括&#xf…

订单视角看支付

支付是指为清偿商品交换和劳务活动所引起的债权债务,货币债权从付款人向收付人的转移的过程。支付能力是电商产品的核心能力之一,作为订单同学,有必要了解关联域支付的流程以及基本概念,同时支付领域的很多设计思路与资损防控经验…

Aethir推出其首次去中心化AI节点售卖

Aethir,去中心化GPU云基础设施领导者,宣布其备受期待的节点销售。Aethir是一家企业级的以AI和游戏为重点的GPU即服务提供商。Aethir的去中心化云计算基础设施使GPU提供商能够与需要NVIDIA的H100芯片提供强大AI/ML任务支持的企业客户相连接。 此外&#x…

蓝桥杯Learning

Part 1 递归和递推 1. 简单斐波那契数列 n int(input())st [0]*(47) # 注意这个地方,需要将数组空间设置的大一些,否则会数组越界 st[1] 0 st[2] 1 # 这个方法相当于是递推,即先求解一个大问题的若干个小问题 def dfs(u):if u 1:print(…

「优选算法刷题」:矩阵区域和

一、题目 给你一个 m x n 的矩阵 mat 和一个整数 k &#xff0c;请你返回一个矩阵 answer &#xff0c;其中每个 answer[i][j] 是所有满足下述条件的元素 mat[r][c] 的和&#xff1a; i - k < r < i k, j - k < c < j k 且(r, c) 在矩阵内。 示例 1&#xff1…

卷积神经网络介绍

卷积神经网络(Convolutional Neural Networks&#xff0c;CNN) 网络的组件&#xff1a;卷积层&#xff0c;池化层&#xff0c;激活层和全连接层。 CNN主要由以下层构造而成&#xff1a; 卷积层&#xff1a;Convolutional layer&#xff08;CONV&#xff09;池化层&#xff1a…

颠覆传统,企业邮件营销如何一键实现个性化、自动化

市场营销大环境&#xff1a;在当今竞争激烈的市场中&#xff0c;邮件营销成为吸引潜在客户和联系人的关键战略。而个性化则是提高电子邮件营销效果的不二选择。在谈论成功的电子邮件营销技巧之前&#xff0c;数据的充足性显得至关重要。如果您的数据不够充足&#xff0c;别担心…

C/C++暴力/枚举/穷举题目持续更新(刷蓝桥杯基础题的进!)

目录 前言 一、百钱买百鸡 二、百元兑钞 三、门牌号码&#xff08;蓝桥杯真题&#xff09; 四、相乘&#xff08;蓝桥杯真题&#xff09; 五、卡片拼数字&#xff08;蓝桥杯真题&#xff09; 六、货物摆放&#xff08;蓝桥杯真题&#xff09; 七、最短路径&#xff08;蓝…

Spring篇----第十篇

系列文章目录 文章目录 系列文章目录前言一、spring JDBC API 中存在哪些类?二、使用 Spring 访问 Hibernate 的方法有哪些?三、列举 spring 支持的事务管理类型四、spring 支持哪些 ORM 框架五、什么是 AOP?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽…

Apache Paimon 主键表解析

Primary Key Table-主键表 1.概述 主键表是创建表时的默认表类型&#xff0c;用户可以插入、更新或删除表中的记录&#xff1b; 主键由一组列组成&#xff0c;这些列包含每条记录的唯一值&#xff1b; Paimon通过对每个桶中的主键排序来强制数据有序&#xff0c;允许用户在…

Qt QWidget 简约美观的加载动画 第五季 - 小方块风格

给大家分享两个小方块风格的加载动画 &#x1f60a; 第五季来啦 &#x1f60a; 效果如下: 一个三个文件,可以直接编译运行 //main.cpp #include "LoadingAnimWidget.h" #include <QApplication> #include <QGridLayout> int main(int argc, char *arg…

Ubuntu服务器fail2ban的使用

作用&#xff1a;限制ssh远程登录&#xff0c;防止被人爆破服务器&#xff0c;封禁登录ip 使用lastb命令可查看到登录失败的用户及ip&#xff0c;无时无刻的不在爆破服务器 目录 一、安装fail2ban 二&#xff0c;配置fail2ban封禁ip的规则 1&#xff0c;进入目录并创建ssh…

Java集合基础梳理(集合体系+ArrayList)

目录 Java集合体系 为什么要使用集合类 ? 如何选用集合? 哪些集合类是线程安全的&#xff1f;哪些不安全&#xff1f; 快速失败(fail-fast)和安全失败(fail-safe)的区别是什么&#xff1f; 遍历的同时修改一个List有几种方式 ArrayList 如何进行元素的遍历操作&#x…

高数考研 -- 公式总结(更新中)

1. 两个重要极限 (1) lim ⁡ x → 0 sin ⁡ x x 1 \lim _{x \rightarrow 0} \frac{\sin x}{x}1 limx→0​xsinx​1, 推广形式 lim ⁡ f ( x ) → 0 sin ⁡ f ( x ) f ( x ) 1 \lim _{f(x) \rightarrow 0} \frac{\sin f(x)}{f(x)}1 limf(x)→0​f(x)sinf(x)​1. (2) lim ⁡…

使用 React 和 ECharts 创建地球模拟扩散和飞线效果

在本博客中&#xff0c;我们将学习如何使用 React 和 ECharts 创建一个酷炫的地球模拟扩散效果。我们将使用 ECharts 作为可视化库&#xff0c;以及 React 来构建我们的应用。地球贴图在文章的结尾。 最终效果 准备工作 首先&#xff0c;确保你已经安装了 React&#xff0c;并…

信息安全计划

任何管理人员或人力资源专业人士都知道&#xff0c;除非彻底记录标准和实践&#xff0c;否则永远无法真正实施和执行标准和实践。正如您可能想象的那样&#xff0c;在保护您的网络、技术和数据系统免受网络威胁以及在发生这些事件时规划最及时、高效和有效的响应时&#xff0c;…

OpenAI划时代大模型——文本生成视频模型Sora作品欣赏(八)

Sora介绍 Sora是一个能以文本描述生成视频的人工智能模型&#xff0c;由美国人工智能研究机构OpenAI开发。 Sora这一名称源于日文“空”&#xff08;そら sora&#xff09;&#xff0c;即天空之意&#xff0c;以示其无限的创造潜力。其背后的技术是在OpenAI的文本到图像生成模…

猜测了一个sora模型结构

如果是上述的这种结构&#xff0c;可以确定的是patch 的size &#xff08;一个图像的小片&#xff09;是固定大小的 那么调节一个视觉分辨率大小通过patchs的大小决定。 如图所示可以证明输入的时候图片没有本物理人为的分割为小片&#xff0c;是通过一个模型进行分割为 小片。…
推荐文章