首页 > 编程语言 >Kubernetes client-go源码走读

Kubernetes client-go源码走读

时间:2024-07-06 14:59:20浏览次数:21  
标签:DeltaFIFO 缓存 队列 走读 Watch 源码 事件 go Informer

Informer机制

informer整体架构

Kubernetes使用Informer代替Controller去访问API Server,Controller的所有操作都和Informer进行交互,而Informer并不会每次都去访问API Server。

  • Informer使用ListAndWatch的机制,在Informer首次启动时,会调用LIST API获取所有最新版本的资源对象,然后再通过WATCH API来监听这些对象的变化,
    并将事件信息维护在一个只读的缓存队列中提升查询的效率,同时降低API Server的负载。
  • 除了ListAndWatch,Informer还可以注册相应的事件,之后如果监听到的事件变化就会调用对应的EventHandler,实现回调。

Informer核心代码模块:

  1. Controller:Informer的实施载体,可以创建reflector及控制processLoop。processLoop将DeltaFIFO队列中的数据pop出,首先调用Indexer进行缓存并建立索引,然后分发给processor进行处理。
  2. Reflector:Informer并没有直接访问k8s-api-server,而是通过一个叫Reflector的对象进行api-server的访问。Reflector通过ListAndWatch监控指定的 kubernetes 资源,当资源发生变化的时候,
    例如发生了Added资源添加等事件,会将其资源对象存放在本地缓存DeltaFIFO中。
  3. DeltaFIFO:是一个先进先出的缓存队列,用来存储Watch API返回的各种事件,如Added、Updated、Deleted。
  4. Indexer:Indexer使用一个线程安全的数据存储来存储对象和它们的键值。需要注意的是,Indexer中的数据与etcd中的数据是完全一致的,这样client-go需要数据时,
    无须每次都从api-server获取,从而减少了请求过多造成对api-server的压力。一句话总结:Indexer是用于存储+快速查找资源。
  5. Processor:记录了所有的回调函数(即ResourceEventHandler)的实例,并负责触发回调函数。

Informer负责与k8s apiserver 进行watch操作,watch的资源,可以是k8s内置资源对象,也可以是CRD。

Informer 是一个带有本地缓存以及索引机制的核心工具包,当请求为查询操作的时候,会优先从本地缓存内去查找数据,而创建、更新、删除这类操作,则会根据事件通知写入到队列DeltaFIFO中,同时对应的事件处理后,更新本地缓存,使本地缓存与ETCD的数据保持一致。

从上图就能看出来,Informer是有多个组件构成的,咱们就先简单了解一下都是什么组件,减轻了APIServer的数据交互压力。

Reflector : 使用List-Watch来保证本地缓存数据的,准确性、顺序性和一致性的,List对应资源的全量列表数据,Watch负责变化部分的数据,
当watch的资源发生变化时,触发变更的事件,比如Added, updated, delete事件,并将资源对象的变化事件存放到本地队列DeltaFIFO中。

DeltaFIFO :是一个增量队列,记录了资源变化的过程,Reflector就相当于队列的生产者。这个组件可以拆分两部分来理解,FIFO是一个队列,
拥有基本方法,例如ADD,UPDATE,DELETE,LIST,POP,CLOSE等,delta是一个资源对象存储,保存存储对象的消费类型,比如 added, updated, deleted等

indexer Store

Indexer :用来存储资源对象并自带索引功能的本地存储,Reflector从deltaFIFO中将消费出来的资源对象存储到Indexer,indexer与etcd中的数据保持完全一致,
从而client-go可以本地读取,减少k8s apiserver的数据交互压力。

List-Watch机制

List-Watch机制是Kubernetes中的异步消息通知机制,通过它能有效的确保了消息的实时性、顺序性和可靠性。

ListAndWatch的主要逻辑分为三大块:

A. List操作(只执行一次):

(1)设置ListOptions,将ResourceVersion设置为“0”;
(2)调用r.listerWatcher.List方法,执行list操作,即获取全量的资源对象;
(3)根据list回来的资源对象,获取最新的resourceVersion;
(4)资源转换,将list操作获取回来的结果转换为[]runtime.Object结构;
(5)调用r.syncWith,根据list回来转换后的结果去替换store里的items;
(6)调用r.setLastSyncResourceVersion,为Reflector更新已被处理的最新资源对象的resourceVersion值;

B. Resync操作(异步循环执行):

(1)判断是否需要执行Resync操作,即重新同步;
(2)需要则调用r.store.Resync操作后端store做处理;

C. Watch操作(循环执行):

(1)stopCh处理,判断是否需要退出循环;
(2)设置ListOptions,设置resourceVersion为最新的resourceVersion,即从list回来的最新resourceVersion开始执行watch操作;
(3)调用r.listerWatcher.Watch,开始监听操作;
(4)watch监听操作的错误返回处理;
(5)调用r.watchHandler,处理watch操作返回来的结果,操作后端store,新增、更新或删除items;

List-Watch,顾名思义,它是分为两部分的。

  • List负责调用资源对应的K8S APIServer的RestFul API获取全局数据列表,并同步到本地缓存中。
  • Watch负责监听资源的变化,并调用相应事件的处理函数进行处理,同时更新本地缓存,使本地缓存与Etcd中数据,保持一致。
  • List是基于HTTP中的短链接实现,Watch则是基于HTTP长链接实现,Watch使用长链接的方式,极大的减轻了Kubernetes APIServer的访问压力。

K8S util workQueue和一般的队列实现有什么区别?

功能更加丰富,支持有序、去重、并发安全等特性

  • 有序:按照添加顺序处理元素(item)
  • 去重:相同元素在同一时间不会被重复处理,例如一个元素在处理前被添加了多次,它只会被处理一次。
  • 并发性:多生产者和多消费者
  • 标记机制:支持标记功能,标记一个元素是否被处理,也允许元素在处理时重新排队。
  • 通知机制:ShutDown方法通过信号量通知队列不再接收新的元素,并通知metric goroutine退出。
  • 延迟:支持延迟队列,延迟一段时间后再将元素存入队列。
  • 限速:支持限速队列,元素存入队列时进行速率限制。限制一个元素被重新排队(Reenqueued)的次数。

为什么需要Resync机制?

  • Resync 机制的引入,定时将 Indexer 缓存事件重新同步到 Delta FIFO 队列中,在处理 SharedInformer 事件回调时,让处理失败的事件得到重新处理。
  • 并且通过入队前判断 FIFO 队列中是否已经有了更新版本的 event,来决定是否丢弃 Indexer 缓存不进行 Resync 入队。
  • 在处理 Delta FIFO 队列中的 Resync 的事件数据时,触发 onUpdate 回调来让事件重新处理。

为什么不从etcd重新拉取?

  • 问:因为watch是长连接,如果网络发生波动连接断了呢,本地缓存因为网络断了那段事件肯定就丢失了一部分事件导致etcd和本地数据不一致,这种情况下如果网络稳定下来或者在网络波动间隙,定时从etcd拉取的方案还能继续保持本地缓存和etcd一致,为什么不这样做呢?
  • 答:informer能保证通过list+watch不会丢失事件,如果网络抖动重新恢复后,watch会带着之前的resourceVersion号重连,resourceVersion是单调递增的,apiserver收到该请求后会将所有大于该resourceVersion的变更同步过来。
  • 另外好像网络长期中断的话会导致informer重新初始化也就会重新list。

总结:

  • Reflector的职责很清晰,要做的事情就是保持DeltaFIFO中的items持续更新,具体实现是通过ListerWatcher提供的list-watch能力来列选指定类型的资源,产生一系列Sync事件,通过ResourceVersion来开启监听过程,
  • 监听到新的事件后,会和前面提到的Sync事件一样,通过DeltaFIFO提供的方法构造相应的DeltaType到DeltaFIFO中,拿着对象的新ResourceVersion重新开始一轮新的监听过程。
  • 监听到更新事件时,也不是直接修改DeltaFIFO中已经存在的元素,而是添加一个新的DeltaType到队列。DeltaFIFO中添加到新的DeltaType时也会有一定的去重机制。

标签:DeltaFIFO,缓存,队列,走读,Watch,源码,事件,go,Informer
From: https://blog.csdn.net/edsion330700/article/details/140227032

相关文章

  • STM32:ADC采集光照(含完整源码)
    需求通过ADC转换实现光照亮度的数字化测量,最后将实时测量的结果打印在串口上。一、ADC概要  ADC全称是Analog-to-DigitalConverter模数转换器,一般我们把模拟信号(Analogsignal)用A来进行简写,数字信号(digitalsignal)用D来表示。  自然界中绝大部分都是模拟信......
  • 基于java+springboot+vue实现的图书商城管理系统(文末源码+Lw)283
     摘 要现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本图书商城管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理......
  • 基于java+springboot+vue实现的旅游推荐系统(文末源码+Lw)280
    摘 要传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装旅游推荐系统软件来发挥其高效地信息处理的作用,可以规范信息管理流程,让管理工作可以系统化和程序化,同时,旅游推荐系统的有效......
  • 基于java+springboot+vue实现的流浪动物管理系统(文末源码+Lw)277
     摘    要在如今社会上,关于信息上面的处理,没有任何一个企业或者个人会忽视,如何让信息急速传递,并且归档储存查询,采用之前的纸张记录模式已经不符合当前使用要求了。所以,对流浪动物信息管理的提升,也为了对流浪动物信息进行更好的维护,流浪动物管理系统的出现就变得水到渠成......
  • 基于java+springboot+vue实现的药店管理系统(文末源码+Lw)285
    摘   要传统信息的管理大部分依赖于管理人员的手工登记与管理,然而,随着近些年信息技术的迅猛发展,让许多比较老套的信息管理模式进行了更新迭代,药品信息因为其管理内容繁杂,管理数量繁多导致手工进行处理不能满足广大用户的需求,因此就应运而生出相应的药店管理系统。本药店......
  • 基于java+springboot+vue实现的药店管理系统(文末源码+Lw)285
    摘   要传统信息的管理大部分依赖于管理人员的手工登记与管理,然而,随着近些年信息技术的迅猛发展,让许多比较老套的信息管理模式进行了更新迭代,药品信息因为其管理内容繁杂,管理数量繁多导致手工进行处理不能满足广大用户的需求,因此就应运而生出相应的药店管理系统。本药店......
  • Java计算机毕业设计信阳市多目的地同步导航系统(开题+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着信阳市城市化进程的加快,交通网络日益复杂,市民出行需求日益多样化,对导航系统的要求也愈发提高。传统单一目的地的导航系统已难以满足市民在日常出......
  • 好久不见!写了一个自动截图神器~【附源码】
    文章目录前言新增功能介绍截图功能快捷键设置程序设计和使用介绍操作菜单栏选择点击坐标点选择图片选择截图区域快捷键设置表格循环次数状态栏使用案例源代码前言好久没更新文章了。上一次更新是在4月16日差不多,也只是写了一个错误集,没什么太多内容。这一次,算是复......
  • 毕业设计-基于Springboot+Vue的在线考试系统的设计与实现(源码+LW+包运行)
    源码获取:https://download.csdn.net/download/u011832806/89456184基于SpringBoot+Vue的在线考试系统开发语言:Java数据库:MySQL技术:SpringBoot+MyBatis+Vue.js工具:IDEA/Ecilpse、Navicat、Maven系统演示视频:链接:https://pan.baidu.com/s/1ylSj7umVPabcPHK9oO5psA?pwd=iw......
  • Dubbo 2.7 源码解析 - 之 远程调用
    Dubbo2.7中的远程调用是其核心功能之一,涉及从客户端发起请求到服务端处理并返回结果的整个过程。这个过程高度抽象且灵活,支持多种协议、序列化方式和负载均衡策略。以下是远程调用的关键流程和相关源码解析:远程调用流程概览构建请求:消费者通过代理对象(由ProxyFactory创......