跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Go / Golang

Kubernetes Informer Indexer 索引机制深度解析

Kubernetes Informer 组件中的 Indexer 负责维护本地缓存并建立索引,旨在减少直接访问 APIServer 的压力。通过 ThreadSafeMap 实现线程安全的增删改查,利用 IndexFunc 计算对象键值,支持按命名空间等维度快速检索资源。核心流程涉及 DeltaFIFO 同步数据至 Indexer,并通过 ByIndex 方法高效获取特定索引下的对象列表。

灰度发布发布于 2025/1/19更新于 2026/7/2450 浏览
Kubernetes Informer Indexer 索引机制深度解析

Indexer 概述

在 Kubernetes client-go 中,Indexer 是一个关键的本地存储组件。它的主要职责是建立索引并缓存 Resource 对象。通过维护与 ETCD 一致的数据副本,当需要获取资源时,可以直接从本地缓存读取,无需每次都请求 APIServer,从而有效降低了对 APIServer 和 ETCD 的压力。

数据流通常是从 DeltaFIFO 中 Pop 出来的资源对象交给 HandlerDeltas 处理,随后同步到 Indexer 中。以下是 HandleDeltas 方法的核心逻辑:

// k8s.io/client-go/tools/cache/shared_informer.go
func (s *sharedIndexInformer) HandleDeltas(obj interface{}) error {
    s.blockDeltas.Lock()
    defer s.blockDeltas.Unlock()
    if deltas, ok := obj.(Deltas); ok {
        return processDeltas(s, s.indexer, s.transform, deltas)
    }
    return errors.New("object given as Process argument is not Deltas")
}

// k8s.io/client-go/tools/cache/controller.go
func processDeltas(
    handler ResourceEventHandler,
    clientState Store,
    transformer TransformFunc,
    deltas Deltas) error {
    // from oldest to newest
    for _, d := range deltas {
        obj := d.Object
        if transformer != nil {
            var err error
            obj, err = transformer(obj)
            if err != nil {
                return err
            }
        }
        switch d.Type {
        case Sync, Replaced, Added, Updated:
            if old, exists, err := clientState.Get(obj); err == nil && exists {
                if err := clientState.Update(obj); err != nil {
                    return err
                }
                handler.OnUpdate(old, obj)
            } else {
                if err := clientState.Add(obj); err != nil {
                    return err
                }
                handler.OnAdd(obj)
            }
        case Deleted:
            if err := clientState.Delete(obj); err != nil {
                return err
            }
            handler.OnDelete(obj)
        }
    }
    return nil
}

核心接口与结构

Indexer 接口继承自 Store 接口,Store 负责基础的本地缓存操作(增删改查),而 Indexer 在此基础上扩展了索引功能。

Store 接口定义

// staging/src/k8s.io/client-go/tools/cache/store.go
type Store interface {
    Add(obj interface{}) error
    Update(obj interface{}) error
    Delete(obj interface{}) error
    List() []interface{}
    ListKeys() []string
    Get(obj interface{}) (item interface{}, exists bool, err error)
    GetByKey(key string) (item interface{}, exists bool, err error)
    Replace([]interface{}, string) error
    Resync() error
}

Indexer 接口定义

type Indexer interface {
    Store
    // 通过计算 obj 在 indexName 索引类中的索引键,获取所有对象
    Index(indexName string, obj interface{}) ([]interface{}, error)
    // 返回 indexKey 指定的所有对象键
    IndexKeys(indexName, indexedValue string) ([]string, error)
    // 获取 indexName 索引类中的所有索引键
    ListIndexFuncValues(indexName string) []string
    // 根据索引键获取对象列表
    ByIndex(indexName, indexedValue string) ([]interface{}, error)
    // 获取所有索引器
    GetIndexers() Indexers
    // 增加更多索引分类
    AddIndexers(newIndexers Indexers) error
}

内部实现:threadSafeMap

实际的数据存储依赖于 cache 结构体,它包含一个 ThreadSafeStore 接口的实现以及用于生成唯一 Key 的 KeyFunc。

type cache struct {
    cacheStorage ThreadSafeStore
    keyFunc      KeyFunc
}

ThreadSafeStore 接口封装了具体的线程安全操作,其底层由 threadSafeMap 实现。这个结构体不仅管理资源对象本身,还维护了索引映射关系。

type threadSafeMap struct {
    lock      sync.RWMutex
    items     map[string]interface{} // 存放资源对象
    indexers  Indexers               // 索引函数映射
    indices   Indices                // 索引数据映射
}

这里有两个关键类型:

  • IndexFunc: 用于从对象中提取索引键的函数。
  • Index: 存储索引键到对象键集合的映射。

索引功能实现

索引功能的灵活性依赖于 IndexFunc。Kubernetes 提供了一个常用的默认索引函数 MetaNamespaceIndexFunc,它基于对象的命名空间进行索引。

func MetaNamespaceIndexFunc(obj interface{}) ([]string, error) {
    meta, err := meta.Accessor(obj)
    if err != nil {
        return []string{""}, fmt.Errorf("object has no meta: %v", err)
    }
    return []string{meta.GetNamespace()}, nil
}

ByIndex 查询逻辑

当我们使用 ByIndex 方法时,实际上是在利用预先构建好的索引快速定位对象。大致流程如下:

  1. 查找索引函数:根据索引器名称找到对应的 IndexFunc。
  2. 查找索引数据:根据索引器名称获取对应的索引映射表。
  3. 获取对象列表:根据传入的索引值(如 namespace)从索引表中拿到对象键集合,再反查 items 获取具体对象。
func (c *threadSafeMap) ByIndex(indexName, indexedValue string) ([]interface{}, error) {
    c.lock.RLock()
    defer c.lock.RUnlock()

    // 1、查找索引器函数
    indexFunc := c.indexers[indexName]
    if indexFunc == nil {
        return nil, fmt.Errorf("Index with name %s does not exist", indexName)
    }

    // 2、查找相应的缓存器函数
    index := c.indices[indexName]

    // 3、根据索引 Key 查询并返回结果
    set := index[indexedValue]
    list := make([]interface{}, 0, set.Len())
    for key := range set {
        list = append(list, c.items[key])
    }
    return list, nil
}

使用示例

在实际开发中,我们常利用索引来过滤特定命名空间或节点下的 Pod。

// 查询 default 命名空间下的所有 Pod
pods, err := index.ByIndex("namespace", "default")
if err != nil {
    panic(err)
}
for _, pod := range pods {
    fmt.Println(pod.(*v1.Pod).Name)
}
fmt.Println("------")

// 查询 node1 节点上的所有 Pod
pods, err = index.ByIndex("nodename", "node1")
if err != nil {
    panic(err)
}
for _, pod := range pods {
    fmt.Println(pod.(*v1.Pod).Name)
}

输出示例:

pod-1
pod-2
------
pod-1

总结

Indexer 不仅具备维护本地缓存的能力,更核心的价值在于其索引功能。通过 threadSafeMap 中的 indexers 和 indices 属性,我们可以实现高效的反向查找。例如,要查询某个 Node 下的所有 Pod,或者某个命名空间下的所有 Pod,直接利用索引都能秒级完成,避免了遍历整个缓存带来的性能损耗。

目录

  1. Indexer 概述
  2. 核心接口与结构
  3. Store 接口定义
  4. Indexer 接口定义
  5. 内部实现:threadSafeMap
  6. 索引功能实现
  7. ByIndex 查询逻辑
  8. 使用示例
  9. 总结
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • OpenClaw.ai:Agentic AI 时代的 Spring Framework 时刻
  • Python 搭建 GEO 多平台监控系统:支持 ChatGPT 豆包 Kimi 等
  • 特斯联获 20 亿融资,聚焦 AI+IoT 与模型系统落地路径
  • Android ApplicationInfo 元数据读取 getString 返回 null 问题排查
  • Java 线程与锁:JLS 第 17 章核心机制解析
  • Win11 + IDEA 集成 Codex 大模型开发环境搭建指南
  • 基于 Nexent 平台搭建育儿问答智能体实战
  • 基于 Docker 部署的 AI 量化分析平台搭建与波浪理论实战
  • C++ STL 详解:手写 String 类实现
  • Coze + Bot API:实现带自我反思的高质量长文翻译 Agent
  • AG-UI:构建 AI 前端交互的统一协议
  • C++ 类和对象:默认成员函数详解
  • OpenCV 并行处理与构建配置指南
  • PADS 2005 SP2 安装常见问题排查与解决
  • OpenClaw 跨平台 AI 助手完全使用指南:从入门到精通
  • C++ 仿 Muduo 库:高并发服务器架构初探
  • 大语言模型(LLM)初学者学习路径指南
  • 循环神经网络(RNN)与序列数据处理实战
  • Java 并发核心:单例模式、生产者消费者、定时器及线程池实现
  • WebStorm 安装与首次启动指南

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online