过滤项存储在Kubernetes共享信息缓存中



我有一个使用client-go informers包编写的Kubernetes控制器。它对集群中的所有pod进行监视,这些对象大约有15k个,它们的YAML表示需要大约600mb的打印(我假设它们在内存中的表示没有那么大的不同)。

因此,这个(否则真的很小)控制器观看pod最终会占用巨大的内存(超过1gib)。即使您认为提供了一种过滤方式的方法,例如命名为NewFilteredSharedInformerFactory的方法,也没有真正给您一种方法来指定一个谓词函数,该函数选择哪些对象存储在内存中的cache中。

相反,该方法在client-go中提供了TweakListOptionsFunc。它可以帮助您控制ListOptions,但不幸的是,我的谓词不能满足于labelSelectorfieldSelector。当对象通过谓词函数到达控制器时,我需要删除它们。

注意:我的谓词是类似于" pod有一个DaemonSet">(这是不可能的fieldSelectors-也是我的另一个问题),没有labelSelector可以在我的场景中工作。

我如何在只有守护进程所有者引用的pod上配置一个通知器来减少我的控制器的内存占用?

这是一个想法,您可以获得集群中所有DaemonSets的列表。读取spec.selector.matchLabels字段以检索DaemonSetpod必须具有的标签。使用这些标签作为TweakListOptionsFunc与逻辑的一部分:

Pods with label1 OR label2 OR label3 ...

我知道这有点辛苦,但似乎是一种有效的方法。我相信没有办法在client-go中指定字段。

今天如果你使用SharedInformers,似乎没有办法过滤哪些对象要保留在共享缓存中,哪些对象要丢弃。

我在kube-state-metrics项目中发现了一个有趣的代码片段,它选择直接启动Watch调用(通常被认为是反模式),并使用watch.Filter,它决定是否从Watch()调用返回一个对象(对缓存/反射器)。

也就是说,许多控制器作者可能选择不走这条路,因为它要求您在Watch()调用周围指定自己的缓存/反射器/索引器。此外,据我所知,像controller-runtime这样的项目甚至不允许您访问这些低级机器。


减少控制器内存占用的另一个方面可以通过结构体上的字段/数据擦除来完成(而不是完全丢弃对象)。这在client-gocache.TransformFunc的新版本中是可能的,它可以让您删除不相关对象的字段(尽管这些对象仍然会消耗一些内存)。这句话更像是权宜之计,可以让你的情况好转。


在我的例子中,我主要需要监视某些名称空间中的DaemonSet Pods,因此我将代码从使用1个通知器(监视所有名称空间)重构为并发运行的N个名称空间范围的通知器。

最新更新