K8S百万资源预list加载数据方案

news/2025/11/11 22:57:23/文章来源:https://www.cnblogs.com/yennie/p/19211852

K8S百万资源预list加载数据方案

联邦控制器资源已经超过百万,每次重启时,需要一次性list所有资源,需要10分钟,给服务启动带来很多风险。

现通过主从预list加载数据,避免升级或者leader切换过程中长时间拉取数据。

// IndexField registers Indexer functions to controller manager.
func IndexField(mgr controllerruntime.Manager) error {
rbIndexerFunc := func(obj client.Object) []string {
rb, ok := obj.(*v1.RB)
if !ok {
return nil
}
return util.GetBindingClusterNames(&rb.Spec)
}
    return utilerrors.NewAggregate([]error{
mgr.GetFieldIndexer().IndexField(context.TODO(), &v1.RB{}, rbClusterKeyIndex, rbIndexerFunc),
})
}

这里面通过IndexFiled方法去构建v1.RB资源的Informer (会NewSharedIndexInformer),并加入到InformerCache全局缓存里面
// IndexField adds an indexer to the underlying cache, using extraction function to get
// value(s) from the given field. This index can then be used by passing a field selector
// to List. For one-to-one compatibility with "normal" field selectors, only return one value.
// The values may be anything. They will automatically be prefixed with the namespace of the
// given object, if present. The objects passed are guaranteed to be objects of the correct type.
func (ip *informerCache) IndexField(ctx context.Context, obj client.Object, field string, extractValue client.IndexerFunc) error {
informer, err := ip.GetInformer(ctx, obj)
if err != nil {
return err
}
return indexByField(informer, field, extractValue)
}

---构建Informer
func NewSharedIndexInformer(lw ListerWatcher, exampleObject runtime.Object, defaultEventHandlerResyncPeriod time.Duration, indexers Indexers) SharedIndexInformer {
realClock := &clock.RealClock{}
sharedIndexInformer := &sharedIndexInformer{
processor: &sharedProcessor{clock: realClock},
indexer: NewIndexer(DeletionHandlingMetaNamespaceKeyFunc, indexers),
listerWatcher: lw,
objectType: exampleObject,
resyncCheckPeriod: defaultEventHandlerResyncPeriod,
defaultEventHandlerResyncPeriod: defaultEventHandlerResyncPeriod,
cacheMutationDetector: NewCacheMutationDetector(fmt.Sprintf("%T", exampleObject)),
clock: realClock,
}
return sharedIndexInformer
}

---构建Indexer索引器
func NewIndexer(keyFunc KeyFunc, indexers Indexers) Indexer {
return &cache{
cacheStorage: NewThreadSafeStore(indexers, Indices{}),
keyFunc: keyFunc,
}
}

---构建数据Cache
func NewThreadSafeStore(indexers Indexers, indices Indices) ThreadSafeStore {
return &threadSafeMap{
items: map[string]interface{}{},
index: &storeIndex{
indexers: indexers,
indices: indices,
},
}
}

--- 加入informerCache的时候调用NewSharedInformer
func (ip *specificInformersMap) addInformerToMap(gvk schema.GroupVersionKind, obj runtime.Object) (*MapEntry, bool, error) {
ip.mu.Lock()
defer ip.mu.Unlock()

// Check the cache to see if we already have an Informer. If we do, return the Informer.
// This is for the case where 2 routines tried to get the informer when it wasn't in the map
// so neither returned early, but the first one created it.
if i, ok := ip.informersByGVK[gvk]; ok {
return i, ip.started, nil
}

// Create a NewSharedIndexInformer and add it to the map.
var lw *cache.ListWatch
lw, err := ip.createListWatcher(gvk, ip)
if err != nil {
return nil, false, err
}
ni := cache.NewSharedIndexInformer(lw, obj, resyncPeriod(ip.resync)(), cache.Indexers{
cache.NamespaceIndex: cache.MetaNamespaceIndexFunc,
})
...
// Start the Informer if need by
// TODO(seans): write thorough tests and document what happens here - can you add indexers?
// can you add eventhandlers?
if ip.started {
go i.Informer.Run(ip.stop) //Run informer时,创建FIFO和reflector
}
}

--- Run informer时 构建DeltaFIFO
func (s *sharedIndexInformer) Run(stopCh <-chan struct{}) {
fifo := NewDeltaFIFOWithOptions(DeltaFIFOOptions{
KnownObjects: s.indexer,
EmitDeltaTypeReplaced: true,
})

cfg := &Config{
Queue: fifo,
ListerWatcher: s.listerWatcher,
ObjectType: s.objectType,
FullResyncPeriod: s.resyncCheckPeriod,
RetryOnError: false,
ShouldResync: s.processor.shouldResync,

Process: s.HandleDeltas,
WatchErrorHandler: s.watchErrorHandler,
}
。。。
s.controller.Run(stopCh)
}

--- Controller Run的时候构建v1.RB这个资源对应的Reflector(一种gvk,一个Reflector)
func (c *controller) Run(stopCh <-chan struct{}) {
defer utilruntime.HandleCrash()
go func() {
<-stopCh
c.config.Queue.Close()
}()
r := NewReflector(
c.config.ListerWatcher,
c.config.ObjectType,
c.config.Queue,
c.config.FullResyncPeriod,
)
...
}


获取Leader后,针对Controller watch的资源建立Informer时,会现从InformerCache里面根据gvk get一下,如果有,就不再New,同时把Informer里面的Indexer,Indexer里面的CacheStorage(里面有之前listAndWatch的数据,都存在这里)带过来。
然后将Informer跟Controller的EventHandler拼接在一起。
--- 切Leader Controller Start时,将Informer.AddEventHandler
_, err := i.AddEventHandler(internal.EventHandler{Queue: queue, EventHandler: handler, Predicates: prct})
if err != nil {
ks.started <- err
return
}
if !ks.cache.WaitForCacheSync(ctx) {
// Would be great to return something more informative here
ks.started <- errors.New("cache did not sync")
}

--- Reflector Run的时候 listAndWatch数据
func (r *Reflector) Run(stopCh <-chan struct{}) {
klog.V(3).Infof("Starting reflector %s (%s) from %s", r.expectedTypeName, r.resyncPeriod, r.name)
wait.BackoffUntil(func() {
if err := r.ListAndWatch(stopCh); err != nil {
r.watchErrorHandler(r, err)
}
}, r.backoffManager, true, stopCh)
klog.V(3).Infof("Stopping reflector %s (%s) from %s", r.expectedTypeName, r.resyncPeriod, r.name)
}
func (r *Reflector) ListAndWatch(stopCh <-chan struct{}) error {
klog.V(3).Infof("Listing and watching %v from %s", r.expectedTypeName, r.name)
if r.expectedTypeName == "*unstructured.Unstructured" {
return nil
}

err := r.list(stopCh) //LIST
if err != nil {
return err
}
...
    w, err := r.listerWatcher.Watch(options)
}

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

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

相关文章

102302105汪晓红数据采集作业2

第二次作业 作业①: 作业代码和图片: 核心代码:点击查看代码 # 主程序 url = "http://www.weather.com.cn/weather/101010100.shtml" city = "北京"# 初始化数据库 conn = setup_database()try:…

【数据结构】:链表的核心实现与运行解析

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

11.11每日总结

今天主要的课程有人机交互技术和软件构造。软考结束了 唉 已经做好下学期再努力试一次的准备了。今天还完善了心理健康平台的设计,继续加油

Meta AI 推出全语种语音识别系统,支持 1600+语言;谢赛宁、李飞飞、LeCun 联手发布「空间超感知」AI 框架丨日报

开发者朋友们大家好:这里是 「RTE 开发者日报」,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的技术」、「有亮点的产品」、「有思考的文章」、「有态度…

Python Socket网络编程

1. Socket参数介绍 服务器端server = socket.socket(AF.INET,sock.SOCK_STREAM)Socket Typessocket.SOCK_STREAM #for tcpsocket.SOCK_DGRAM #for udp socket.SOCK_RAW #原始套接字,普通的套接字无法处理ICMP、…

拥护向量机(SVM)(二)---优化算法

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

英语翻译题做法

🔹快速浏览全文和完形填空一样,做翻译题前,我先快速浏览一遍全文,大概知道文章讲什么、关于什么。如果时间充裕,可以这样做;但如果考试时间紧张,直接读划线句的翻译部分。重点看首尾两段,也能大致把握主旨。�…

Python show memory

py -m pip install psutil import os import psutil import asyncio import time from datetime import datetimeclass Book:def __init__(self,id,name,author,isbn,title,topic):self.id=idself.name=nameself.autho…

LeetCode - 1171. - 教程

LeetCode - 1171. - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", &q…

研发度量DORA+SPACE+OST 影响模型

目录总结DORA 指标Space指标传统指标参考资料 总结 作为研发总监,建议您建立一个三层指标仪表盘:顶层(DORA + 业务结果): 关注结果和对业务的贡献。这是您向 CEO 或董事会汇报的指标。核心 DORA 4 指标。 功能发布…

断句

文言文断句,传统上称为“句读”,明辨“句读”是阅读文言文最基本的方法;文言文断句,在通读全文、了解大意的基础上,可借助以下几种方法断句:一、借助虚词标志性词语断句 虚词是明辨句读的重要标志,尤其是代词、…

GBT - What is gradient-boosted tree regression?

GBT - What is gradient-boosted tree regression?Gradient-Boosted Tree Regression (GBT Regression) — also called Gradient Boosted Regression Trees (GBRT) or Gradient Boosting Regression — is a powerfu…

保姆级教程 十分钟带你配置好vscode xdebug

本文详细介绍了在VSCode中配置Xdebug进行PHP远程调试的完整流程。首先通过PHP版本确认和路径查找确定环境配置基础,然后通过手动或自动方法下载匹配的Xdebug扩展并进行正确安装。重点讲解了php.ini文件的关键配置项设…

比特币的简单技术原理

比特币技术核心详解:从密码学原理到区块链架构 比特币不仅仅是一种数字货币,更是一个建立在密码学和分布式网络之上的革命性系统。理解其技术内核,是理解其价值主张的关键。 一、 终极目标:数字黄金与无需信任的价…

详细介绍:HUD-汽车图标内容

详细介绍:HUD-汽车图标内容pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco",…

后端八股之mysql - 指南

后端八股之mysql - 指南2025-11-11 22:38 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; fon…

nginx拦截ip

nginx拦截iphttp中加# 提取客户端真实 IPmap $http_x_forwarded_for $client_ip { "~^(?P<ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})" "$ip"; default …

2025年包装机厂家推荐排行榜,全自动包装机,全自动包装机生产线,非标定制生产线,非标定制机器公司精选指南

2025年包装机厂家推荐排行榜:全自动包装机生产线与非标定制设备选购指南 行业背景与发展趋势 随着制造业智能化转型的深入推进,包装机械行业正迎来技术革新的关键时期。全自动包装机生产线作为现代工业生产的重要装备…

【CI130x 离在线】FIFO的学习及实例

FIFO(先进先出)命名管道,用于无关系进程间的通信,因为Linux中所有事物都是文件,它在文件系统中以文件名的形式存在。创建管道用函数mkfifo(const char * pathname,mode_t mode); 函数说明:pathname参数为创建实名…

2025年包装机厂家权威推荐榜:全自动包装机、半自动包装机,高效智能包装解决方案精选

2025年包装机厂家权威推荐榜:全自动包装机、半自动包装机,高效智能包装解决方案精选随着制造业智能化转型的深入推进,包装机械行业正迎来技术革新的关键时期。全自动包装机和半自动包装机作为生产线上的关键设备,其…