专栏首页沃趣科技容器化 RDS:借助火焰图定位Kubernetes性能问题
原创

容器化 RDS:借助火焰图定位Kubernetes性能问题

容器化RDS系列文章:

借助 CSI(Container Storage Interface),加上对 Kubenetes 核心代码的少量修改,可以 out-tree 的方式高效且低耦合的方式扩展 Kubenetes 存储管理子模块。

《容器化 RDS:借助 CSI 扩展 Kubernetes 存储能力》介绍,以 out-tree 方式添加 PVC 扩容(Resize)特性。

从可执行程序到可用编程产品,还需要设计结合业务需求的性能基准测试,并对发现的性能瓶颈进行优化。

经验数据表明,相同功能的编程产品的成本,至少是已经过测试的程序的三倍。

——人月神话

本文将分享性能基准测试的优化案例:

  • 发现性能瓶颈
  • 确定问题组件
  • 借助 CPU Profile 和 Flame Graph,快速缩小范围,定位到问题 code-path
  • 有针对的优化

| 发现性能瓶颈

测试用例:

批量创建100个读写模式为RWO,容量为1GiB 的 PVC

期望测试结果:

180秒内全部创建成功并无报错

所有的编程人员都是乐观主义者,毕竟在可能出现问题的地方,一定都会遇到问题,在耗时 3600 秒后,95% 的 PVC 处于 Pending 状态,严格的说,在批量创建的场景,该功能不可用。

大量 PVC 处于 Pending 状态

| 定位问题组件

由于涉及组件众多:

  • kube-apiserve
  • kube-controller-manage
  • kubelet
  • external-provisione
  • external-attache
  • csi-drive
  • qcfs-csi-plugin

组件之间调用复杂,再加上无处不在的协程(goroutine),如果直接查看日志或是 debug code 定位问题,犹如大海捞针,更不要说定位性能瓶颈。所以,首要工作是先定位到问题组件。

在测试过程中,我们记录了所有组件和系统的资源使用情况,运气不佳,从 CPU 使用情况,内存使用情况,网络 I/O 和磁盘 I/O 来看都没有异常数据。

通过梳理存储管理相关组件的架构图:

架构图

以及业务流程的梳理,kube-controller-manager、external-provisioner 和 csi-driver 嫌疑较大。

通过 kubelet logs 查看日志,可以在 external-provisioner 中发现可疑日志:

I0728 19:19:50.504069    1 request.go:480] Throttling request took 192.714335ms, request: POST:https://10.96.0.1:443/api/v1/namespaces/default/events
I0728 19:19:50.704033    1 request.go:480] Throttling request took 190.667675ms, request: POST:https://10.96.0.1:443/api/v1/namespaces/default/events

external-provisioner 访问 kube-apiserver 触发限流

external-provisioner 有重大嫌疑。

| 定位问题 code-path

我们可以立马进入调试环节:

1.阅读 external-provisioner 代码,加入调试日志,理解逻辑

2.不断缩小 code-path

步骤 1、2持续迭代,直到最终定位到问题函数,这是非常有效的办法。

或者采用 CPU profile:

1.采集堆栈样本

2.找到在采样手气内消耗 CPU 时间比率最高的函数,把该函数作为调试的起点

相比上一种,更高效的缩小问题的范围,节省更多的时间。

借助模块“net/http/pprof”,对 external-provisioner 进行 60 秒的 CPU 采样,可以获得如下信息:

生成堆栈使用百分比排序:

函数的调用关系以及采样周期内 CPU 耗时百分比:

针对“net/http/pprof”稍微啰嗦几句:

  • 提供 CPU profile 和 Heap profile;
  • 在采样时获得堆栈(几乎所有)信息, 以此为依据估算整个采样周期内堆栈的CPU占用百分比, 并不是 100% 准确;
  • 采样成本并不低,100赫兹既可以采样够用的堆栈信息,又不会给应用程序带来过大开销;
  • CPU 采样频率默认为 100 赫兹,并硬编码到模块中, 不建议调到 500 赫兹以上。

网上已经有大量的相关文章,这里不赘述。

配合获取的 CPU profile 信息生成火焰图(Flame Graph):

这里针对火焰图再啰嗦下:

  • 借助第三方工具 go-torch 绘制
  • 每个矩形代表一个堆栈,采样时间内,CPU 占用百分比越高 Y 轴越长,X 轴表明了堆栈之间的调用关系
  • 从左到右按照字母表排序
  • 颜色随机选择,无具体含义

网上已经有大量的相关文章,这里不赘述。

可以发现函数 addClaim 和 lockProvisionClaimOperation 的 CPU 占用比率达到 36.23%。

来自于 external-provisioner 调用的第三方模块 kubenetes-incubator/external-storage

所以,只要引用例如了模块 Kubenetes-incubator/external-storage 实现卷创建功能,都可以复现 api throttling。

再针对性的加入调试日志到 code-path 中,理解逻辑,很快可以确定问题:

在创建卷时,external-storage 需要访问 API 资源(譬如 configmap、pvc、pv、event、secrets、storageclass 等),为减少 kube-apiserver 工作负荷,不建议直接访问 kube-apiserver,而应该利用本地缓存(由 informer cache 构建)。但 external-storage 恰好直接访问 kube-apiserver。通过下图可以看到,有18.84%的采样时间在 list event,这是导致 api throttling 的原因。

进一步分析,之所以有大量的 list event 是因为 Leader Election 的 Lock 实现粒度太细导致锁抢占严重。生产环境中,一个组件会启动多个实例,抢占到 Leader Lock 的实例即为 Leader 并对外提供服务,其他实例以 Slave 模式运行,一旦 Leader 出现问题,Slave 发现 Leader Lock 在租期内没有更新即可发起抢占成为新的 Leader 并接管服务。这样不仅提升了组件的可用性也避免了可能带来的 data race 问题。所以可以理解成是一个组件实例一把锁,并且只在 Leader 和 Slave 角色切换时才会重新选主,但 external-storage 原意为了提升并发度,运行多个实例同时为 Leader 提供服务,可以简单理解成一个 PVC 一把锁,100 PVC 就意味着多个实例要最少发生100次的 Lock 抢占。

最终定位到问题原因:

Lock 的抢占导致 api throttling,引发 Lock 抢占 timeout,timeout 后抢占重试,进一步恶化 api throttling。

从下图可以进一步得到验证,有 8.7% 的采样时间在进行 Leader Election。

| 解决问题

一旦发现问题的根源,解决它反而是件不难的事情。后面针对该问题做了修复:

  • 采用 sharedinformer cache
  • 修改 Leader Lock 粒度

再次生成运行,可以发现函数 addClaim 和 lockProvisionClaimOperation 的 CPU 占用百分比下降到 13.95%。

external-provisioner 日志中的 throttling 关键字消失

100 PVC 的时间缩短到60秒以内全部创建成功,无任何报错。

| 结语

对于终端用户而言,交互的界面越来越简单,但对于开发者而言,组件越来越多,编译一次的时间越来越久,加上无处不在的并发,导致定位问题的难度越来越大,尤其是性能问题。所以,对体系架构的理解能帮我们快速锁定问题组件,配合 Profile 工具和 Flame Graph 快速定位 code-path,再加上对业务逻辑的理解找到解决方案。

所有的编程人员都是乐观主义者,无论是什么样的程序,结果是勿庸置疑的:"这次它肯定会运行。" 或者 "我刚刚找出了最后一个问题。"

——人月神话

| 作者简介

熊中哲·沃趣科技联合创始人

曾就职于阿里巴巴和百度,超过10年关系型数据库工作经验,目前致力于将云原生技术引入到关系型数据库服务中。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 或许,9月12日的苹果新品发布会依然会让人失望!

    正如每一次的苹果邀请函都带给我们不一样的感受一样,今年9月12日的苹果发布会的邀请函依然让我们浮想联翩。这或许是苹果以往营销套路的延续——通过给人一个极具想象力...

    孟永辉
  • 恒大入主法拉第,FF91真的要来了吗?

    自恒大入主法拉第之后,FF91落地的步伐似乎开始逐步加快。在许家印到法拉第公司考察之后,FF91在落地到中国的步伐更加快速。就在上周,恒大法拉第未来智能汽车集团...

    孟永辉
  • 1万步21天钉钉运动大神赛

      目前所在的企业,从入职开始到现在,内部沟通协作的主要软件也就是钉钉。三月初的时候,偶然在钉钉运动一栏中发现了这个活动,当时也没怎么犹豫,果断支付了2元契约金...

    happyJared
  • 任性的苹果,任性的库克

    或许在人类历史上还没有哪一个科技公司会像苹果般任性,任性到可以不顾及用户的感受。随着苹果发布会的新鲜“上线”,我们再次见识到了苹果的任性。价格再度刷新史上最高、...

    孟永辉
  • 锤子手机推“无限屏”新机:让我们为老罗的创新点赞

    人们对于锤子手机的发布会的期待其实更多的是在看罗永浩的“单口相声”。无论锤子手机如何,观众依然能够在锤子手机发布会上过一回嘴瘾。罗永浩对于自己,对于友商,对于行...

    孟永辉
  • 共享单车落幕:上海凤凰诉ofo或在情理之中

    共享单车浩浩荡荡的发展历程伴随着资本的退却而最终落幕。尽管共享单车市场上摩拜投身美团总算是有了一个好归宿,哈罗单车对于三四线的深度布局实现了逆袭,ofo依然在仗...

    孟永辉
  • BAT、TMD加持新技术背景下,互联网家装如何蝶变新生?

    几乎所有的“互联网+”模式都存在同样的问题,那就是对于行业内在运行逻辑改造的无力与浅层。互联网家装同样如此。我们看到,尽管互联网家装改变了人们获取用户的方式和手...

    孟永辉
  • 饿了么并入口碑,一场“非典型”新零售大战的开始

    如果你了解互联网巨头的套路,你就会发现他们会不断用资本的力量去拓展自己的势力范围,并且建构一个能够将人们所有的生活场景全部都囊括其中的生态体系。饿了么并入口碑仅...

    孟永辉
  • 拼多多、趣头条上市,反驳消费升级的无效样本

    最近,有关消费升级与消费降级的讨论一直都没有停止过。作为一个新的风口和方向,人们对于消费升级和消费降级的谈论无可厚非,因为只有深入讨论才能找到合适的发展方向。但...

    孟永辉
  • 马云退休,一个全新的互联网时代或将开始

    今天,马云退休的消息无疑是一个焦点。对于马云退休的原因,外界依然有很多的猜测。几乎可以确定的是,未来马云将会从事自己心仪的教育事业,并将会持续发挥自己在教育事业...

    孟永辉

扫码关注云+社区

领取腾讯云代金券