Kubernetes Informer 详解

简介: 今天给到大家介绍一下 Client-go 中的一个非常关键的工具包 Informer。 Informer 内部实现极其复杂,详细介绍的文章也很少,很多人反馈比较难用。但不得不承认它也是一个设计精良、安全可靠的组件,值得我们去一探究竟。

今天给到大家介绍一下 Client-go 中的一个非常关键的工具包 Informer。 Informer 内部实现极其复杂,详细介绍的文章也很少,很多人反馈比较难用。但不得不承认它也是一个设计精良、安全可靠的组件,值得我们去一探究竟。


Informer 简介

Informer 基础功能

Informer 是 Client-go 中的一个核心工具包。在 Kubernetes 源码中,如果 Kubernetes 的某个组件,需要 List/Get Kubernetes 中的 Object,在绝大多 数情况下,会直接使用 Informer 实例中的 Lister()方法(该方法包含 了 Get 和 List 方法),而很少直接请求 Kubernetes API。Informer 最基本 的功能就是 List/Get Kubernetes 中的 Object。

如下图所示,仅需要十行左右的代码就能实现对 Pod 的 List 和 Get。

Informer 高级功能

Client-go 的首要目标是满足 Kubernetes 的自身需求。Informer 作为其中的核心工具包,面对 Kubernetes 极为复杂业务逻辑,如果仅实现 List/Get 功能,根本无法满足 Kubernetes 自身需求。因此,Informer 被设计为一个灵活而复杂的工具包,除 List/Get Object 外,Informer 还可以监听事件并触发回调函数等,以实现更加复杂的业务逻辑。

Informer 设计思路

Informer 设计中的关键点

为了让 Client-go 更快地返回 List/Get 请求的结果、减少对 Kubenetes API 的直接调用,Informer 被设计实现为一个依赖 Kubernetes List/Watch API 、可监听事件并触发回调函数的二级缓存工具包。

更快地返回 List/Get 请求,减少对 Kubenetes API 的直接调用

使用 Informer 实例的 Lister() 方法, List/Get Kubernetes 中的 Object 时,Informer 不会去请求 Kubernetes API,而是直接查找缓存在本地内存中的数据(这份数据由 Informer 自己维护)。通过这种方式,Informer 既可以更快地返回结果,又能减少对 Kubernetes API 的直接调用。

依赖 Kubernetes List/Watch API

Informer 只会调用 Kubernetes List 和 Watch 两种类型的 API。Informer 在初始化的时,先调用 Kubernetes List API 获得某种 resource 的全部 Object,缓存在内存中; 然后,调用 Watch API 去 watch 这种 resource,去维护这份缓存; 最后,Informer 就不再调用 Kubernetes 的任何 API。

用 List/Watch 去维护缓存、保持一致性是非常典型的做法,但令人费解的是,Informer 只在初始化时调用一次 List API,之后完全依赖 Watch API 去维护缓存,没有任何 resync 机制。

笔者在阅读 Informer 代码时候,对这种做法十分不解。按照多数人思路,通过 resync 机制,重新 List 一遍 resource 下的所有 Object,可以更好的保证 Informer 缓存和 Kubernetes 中数据的一致性。

咨询过 Google 内部 Kubernetes 开发人员之后,得到的回复是:
在 Informer 设计之初,确实存在一个 relist 无法去执 resync 操作, 但后来被取消了。原因是现有的这种 List/Watch 机制,完全能够保证永远不会漏掉任何事件,因此完全没有必要再添加 relist 方法去 resync informer 的缓存。这种做法也说明了 Kubernetes 完全信任 etcd。

可监听事件并触发回调函数

Informer 通过 Kubernetes Watch API 监听某种 resource 下的所有事件。而且,Informer 可以添加自定义的回调函数,这个回调函数实例(即 ResourceEventHandler 实例)只需实现 OnAdd(obj interface{}) OnUpdate(oldObj, newObj interface{}) 和 OnDelete(obj interface{}) 三个方法,这三个方法分别对应 informer 监听到创建、更新和删除这三种事件类型。

在 Controller 的设计实现中,会经常用到 informer 的这个功能。 Controller 相关文章请见此文《如何用 client-go 拓展 Kubernetes 的 API》。

二级缓存

二级缓存属于 Informer 的底层缓存机制,这两级缓存分别是 DeltaFIFO 和 LocalStore。

这两级缓存的用途各不相同。DeltaFIFO 用来存储 Watch API 返回的各种事件 ,LocalStore 只会被 Lister 的 List/Get 方法访问 。

虽然 Informer 和 Kubernetes 之间没有 resync 机制,但 Informer 内部的这两级缓存之间存在 resync 机制。

以上是 Informer 设计中的一些关键点,没有介绍一些太细节的东西,尤其对于 Informer 两级缓存还未做深入介绍。下一章节将对 Informer 详细的工作流程做一个详细介绍。

Informer 详细解析

Informer 内部主要组件

Informer 中主要包含 Controller、Reflector、DeltaFIFO、LocalStore、Lister 和 Processor 六个组件,其中 Controller 并不是 Kubernetes Controller,这两个 Controller 并没有任何联系;Reflector 的主要作用是通过 Kubernetes Watch API 监听某种 resource 下的所有事件;DeltaFIFO 和 LocalStore 是 Informer 的两级缓存;Lister 主要是被调用 List/Get 方法;Processor 中记录了所有的回调函数实例(即 ResourceEventHandler 实例),并负责触发这些函数。

Informer 关键逻辑解析

我们以 Pod 为例,详细说明一下 Informer 的关键逻辑:

  1. Informer 在初始化时,Reflector 会先 List API 获得所有的 Pod
  2. Reflect 拿到全部 Pod 后,会将全部 Pod 放到 Store 中
  3. 如果有人调用 Lister 的 List/Get 方法获取 Pod, 那么 Lister 会直接从 Store 中拿数据
  4. Informer 初始化完成之后,Reflector 开始 Watch Pod,监听 Pod 相关 的所有事件;如果此时 pod_1 被删除,那么 Reflector 会监听到这个事件
  5. Reflector 将 pod_1 被删除 的这个事件发送到 DeltaFIFO
  6. DeltaFIFO 首先会将这个事件存储在自己的数据结构中(实际上是一个 queue),然后会直接操作 Store 中的数据,删除 Store 中的 pod_1
  7. DeltaFIFO 再 Pop 这个事件到 Controller 中
  8. Controller 收到这个事件,会触发 Processor 的回调函数

LocalStore 会周期性地把所有的 Pod 信息重新放到 DeltaFIFO 中

Informer 总结

Informer 的内部原理比较复杂、不太容易上手,但 Informer 却是一个非常稳定可靠的 package,已被 Kubernetes 广泛使用。但是,目前关于 Informer 的文章不是很多,如果文章中有表述不正确的地方,希望各位读者悉心指正。

本文转自中文社区-Kubernetes Informer 详解

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
存储 Kubernetes 安全
【K8s源码品读】010:Phase 1 - kube-scheduler - Informer是如何保存数据的
了解Informer在发现资源变化后,是怎么处理的
167 0
|
Kubernetes 容器
【K8s源码品读】009:Phase 1 - kube-scheduler - Informer监听资源变化
了解Informer是如何从kube-apiserver监听资源变化的情况
273 0
|
存储 传感器 Kubernetes
图解 K8S 源码 - Informer 篇
图解 K8S 源码中的 Informer 机制及 Reflector 实现。
4300 0
|
Kubernetes 容器
Kubernetes Client-go Informer 源码分析
几乎所有的Controller manager 和CRD Controller 都会使用Client-go 的Informer 函数,这样通过Watch 或者Get List 可以获取对应的Object,下面我们从源码分析角度来看一下Client go Informer 的机制。
4793 0
|
2月前
|
人工智能 算法 调度
阿里云ACK托管集群Pro版共享GPU调度操作指南
本文介绍在阿里云ACK托管集群Pro版中,如何通过共享GPU调度实现显存与算力的精细化分配,涵盖前提条件、使用限制、节点池配置及任务部署全流程,提升GPU资源利用率,适用于AI训练与推理场景。
298 1
|
2月前
|
弹性计算 监控 调度
ACK One 注册集群云端节点池升级:IDC 集群一键接入云端 GPU 算力,接入效率提升 80%
ACK One注册集群节点池实现“一键接入”,免去手动编写脚本与GPU驱动安装,支持自动扩缩容与多场景调度,大幅提升K8s集群管理效率。
262 89
|
7月前
|
资源调度 Kubernetes 调度
从单集群到多集群的快速无损转型:ACK One 多集群应用分发
ACK One 的多集群应用分发,可以最小成本地结合您已有的单集群 CD 系统,无需对原先应用资源 YAML 进行修改,即可快速构建成多集群的 CD 系统,并同时获得强大的多集群资源调度和分发的能力。
301 9
|
7月前
|
资源调度 Kubernetes 调度
从单集群到多集群的快速无损转型:ACK One 多集群应用分发
本文介绍如何利用阿里云的分布式云容器平台ACK One的多集群应用分发功能,结合云效CD能力,快速将单集群CD系统升级为多集群CD系统。通过增加分发策略(PropagationPolicy)和差异化策略(OverridePolicy),并修改单集群kubeconfig为舰队kubeconfig,可实现无损改造。该方案具备多地域多集群智能资源调度、重调度及故障迁移等能力,帮助用户提升业务效率与可靠性。
|
9月前
|
存储 Kubernetes 监控
K8s集群实战:使用kubeadm和kuboard部署Kubernetes集群
总之,使用kubeadm和kuboard部署K8s集群就像回归童年一样,简单又有趣。不要忘记,技术是为人服务的,用K8s集群操控云端资源,我们不过是想在复杂的世界找寻简单。尽管部署过程可能遇到困难,但朝着简化复杂的目标,我们就能找到意义和乐趣。希望你也能利用这些工具,找到你的乐趣,满足你的需求。
893 33
|
9月前
|
Kubernetes 开发者 Docker
集群部署:使用Rancher部署Kubernetes集群。
以上就是使用 Rancher 部署 Kubernetes 集群的流程。使用 Rancher 和 Kubernetes,开发者可以受益于灵活性和可扩展性,允许他们在多种环境中运行多种应用,同时利用自动化工具使工作负载更加高效。
521 19