Kubenetes client-go informers添加转换函数,apiserver 内存优化"
背景
client-go 函数转换机制 - transform functions
在 Client-go
中,对象放入缓存之前对其进行转换。Client-go
允许使用转换功能配置核心信息者。在将对象放入缓存之前,将使用该对象作为参数调用这些函数。如果转换器想要检索其字段,则需要将对象转换为具体或元数据类型。与仅元数据缓存相比,这是一个较少使用的功能。几个用法示例:
- 在controller-runtime中添加了对转换函数的支持,目的是允许用户删除托管字段和注释
- Istio 的试点控制器使用此机制来配置其 client-go informer,以在将对象放入缓存之前删除托管字段。 我还没有看到任何使用此机制修改非元数据字段的使用示例。我看不出为什么无法添加新字段(即表明已应用转换的标签)以及删除字段的原因。
使用场景
在 Secret 和 ConfigMap 大量(200+)使用的集群中,Client-go 通过watch informer
方式, watch 全部资源很耗内存。
本地KinD
实验: 在200个Secret下,通过Client-go的demo 去watch数据性能
func (f *filteredSecretInformer) Informer() Informer {
typedInformer := f.typedInformerFactory.InformerFor(&corev1.Secret{}, f.newTyped)
// TODO: 将在这边设置transform
metadataInformer := f.metadataInformerFactory.ForResource(secretsGVR).Informer()
// TODO: 设置transform 来删除应用不用到注释、label和ManagedFields等
return &informer{
typedInformer: typedInformer,
metadataInformer: metadataInformer,
}
}
func (f *filteredSecretInformer) Lister() SecretLister {
typedLister := corev1listers.NewSecretLister(f.typedInformerFactory.InformerFor(&corev1.Secret{}, f.newTyped).GetIndexer())
metadataLister := metadatalister.New(f.metadataInformerFactory.ForResource(secretsGVR).Informer().GetIndexer(), secretsGVR)
return &secretLister{
typedClient: f.typedClient,
namespace: f.namespace,
typedLister: typedLister,
partialMetadataLister: metadataLister,
ctx: f.ctx,
}
}
结果:
apiserver metrics:
- 峰值内存使用:~80MiB,约 5 分钟后降至约 70MiB。
- 峰值CPU使用:0.06% core
添加清理函数
var_cache.TransformFunc=partialMetadataRemoveAll
// partialMetadataRemoveAll 实现了一个删除的cache.TransformFunc标签、注释和托管 PartialObjectMetadata 中的字段。
func partialMetadataRemoveAll(obj interface{}) (interface{}, error) {
partialMeta, ok := obj.(*metav1.PartialObjectMetadata)
if !ok {
return nil, fmt.Errorf("internal error: cannot cast object %v to PartialObjectMetadata", obj)
}
partialMeta.Annotations = nil
partialMeta.ManagedFields = nil
partialMeta.Labels = nil
return partialMeta, nil
}
func (f *filteredSecretInformer) Informer() Informer {
typedInformer := f.typedInformerFactory.InformerFor(&corev1.Secret{}, f.newTyped)
metadataInformer := f.metadataInformerFactory.ForResource(secretsGVR).Informer()
// 设置transform 来删除应用不用到注释、label和ManagedFields等
+ if err := metadataInformer.SetTransform(partialMetadataRemoveAll); err != nil {
+ panic(fmt.Sprintf("internal error: error setting transfomer on the metadata informer: %v", err))
+ }
return &informer{
typedInformer: typedInformer,
metadataInformer: metadataInformer,
}
}
apiserver metrics:
- 峰值内存使用:~37MiB, 约 5 分钟后降至约 20MiB.
- 峰值CPU使用:0.15% core, 约 5 分钟后降至约 0.05% core.
结果
对于大量读写 Secret
和 ConfigMap
场景下, 使用自定义的transform
, 可将少 60% api-server内存使用;
「如果这篇文章对你有用,请随意打赏」
如果这篇文章对你有用,请随意打赏
使用微信扫描二维码完成支付
