前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Kube-controller-manager同步数据慢

Kube-controller-manager同步数据慢

作者头像
李鹤
发布2023-03-06 11:20:52
1720
发布2023-03-06 11:20:52
举报
文章被收录于专栏:k-cloud-labs

背景

版本1.12.4

线上遇到kube-controller-manager重启慢的问题,具体表现为进程重启虽然速度快,但是重启完所有数据都同步完一遍耗时很长,集群中大约5000个statefulset,在还没同步完一遍数据之前如果有statefulset的创建、删除、修改等操作,可能(和具体statefulset的操作有关,新建的情况肯定是在最后,更新和删除的情况需要看同名的statefulset是否已经被处理过了,如果是的话也会在最后处理,如果没有的话,则不会排在最后)就需要等到所有数据都同步完之后才能继续处理。

问题原因

并发goroutine数

当前版本的statefulset controller只使用了一个goroutine来串行的处理所有的statefulset,在最新版的代码中已经支持了多个goroutine并行处理,且可配置

Informer List

经过添加trace信息打印每个阶段耗时,发现在根据statefulset获取其对应的controllerrevision时比较慢,如下代码段

1 2 3 4 5 6

// adoptOrphanRevisions adopts any orphaned ControllerRevisions matched by set's Selector. func (ssc *StatefulSetController) adoptOrphanRevisions(set *apps.StatefulSet) error { // 比较慢 revisions, err := ssc.control.ListRevisions(set) ... }

而且同样的逻辑会在这里在执行一次

1 2 3 4 5 6 7 8 9 10 11

// syncStatefulSet syncs a tuple of (statefulset, []*v1.Pod). func (ssc *StatefulSetController) syncStatefulSet(set *apps.StatefulSet, pods []*v1.Pod) error { ... // TODO: investigate where we mutate the set during the update as it is not obvious. // UpdateStatefulSet里面会再次调用ListRevisions函数 if err := ssc.control.UpdateStatefulSet(set.DeepCopy(), pods); err != nil { return err } ... }

最终就导致同步一个statefulset就需要100+ms,总的5000+ statefulset同步完一遍就需要将近20m。

ControllerRevision

每个statefulset都对应一些controllerrevision资源,从字面意思就可以看出来其作用就是记录此statefulset的历史信息,这也是为什么我们可以直接对statefulset做回滚之类的操作的原因,默认情况下会为每个statefulset保留10条历史记录,在每个statefulset上有属性可配置。

其实上面说到的耗时的逻辑就是针对每个statefulset去获取孤儿controllerrevision,如果有则会领养孤儿。所以一个优化项就是直接从孤儿中找,而不是从全量中找,且把所有的controllerrevision缓存到本地,不再使用ListInformer提供的那些方法,因为这些方法始终会在全量中寻找满足条件的,而且还会用到反射,虽然数据也都在本地,但性能还是比较差的。大体思路就是在创建statesetfulset controller时同时注册controllerrevision相关的事件,把所有的revision和孤儿revision缓存到自定义的数据结构中,后续直接从里面获取即可。

最终效果

优化完之后最终重启一次controller-manager知道全量数据同步完一遍的耗时由20m左右缩减到1m左右,可以看到效果还是很明显的,而且还是有优化空间的,比如继续以空间换时间,在备controller-manager启动时就先把所有的数据同步完,所有更新缓存的逻辑照样执行,只是不触发其他操作,这样在主备切换时就能省掉网络传输数据的耗时,当然得衡量数据量大小,随着集群规模越来越大,master上各组件占用的内存势必越来越多,将来可能就又会面临内存不够用的情况。

意外收获

测试的时候发现了一个bug,孤儿controllerrevision无法被领养,且会导致statefulset同步失败,这是statefulset controller的代码bug,pr已合入master,随着v1.18版本发布。具体可参考这里

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-04-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 问题原因
    • 并发goroutine数
      • Informer List
        • ControllerRevision
        • 最终效果
        • 意外收获
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档