内容简介:借助 CSI(Container Storage Interface),加上对 Kubenetes 核心代码的少量修改,可以 out-tree 的方式高效且低耦合的方式扩展 Kubenetes 存储管理子模块。如《从可执行程序到可用编程产品,还需要设计结合业务需求的性能基准测试,并对发现的性能瓶颈进行优化。
借助 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-apiserver
- kube-controller-manager
- kubelet
- external-provisioner
- external-attacher
- csi-driver
- 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
我们可以立马进入调试环节:
- 阅读 external-provisioner 代码,加入调试日志,理解逻辑
- 不断缩小 code-path
步骤 1、2持续迭代,直到最终定位到问题函数,这是非常有效的办法。
或者采用 CPU profile:
- 采集堆栈样本
- 找到在采样手气内消耗 CPU 时间比率最高的函数,把该函数作为调试的起点
相比上一种,更高效的缩小问题的范围,节省更多的时间。
借助模块“net/http/pprof”,对 external-provisioner 进行 60 秒的 CPU 采样,可以获得如下信息:
- 生成堆栈使用百分比排序:
- 函数的调用关系以及采样周期内 CPU 耗时百分比:
针对“net/http/pprof”稍微啰嗦几句:
- 提供 CPU profile 和 Heap profile;
- 在采样时获得所有堆栈(几乎所有)信息,以此为依据估算整个采样周期内堆栈的CPU占用百分比,并不是100%准确;
- 采样成本并不低(几乎所有堆栈信息),100Hz 既可以采样够用的堆栈信息,又不会给应用程序本身带来过大的开销;
- 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,再加上对业务逻辑的理解找到解决方案。
所有的编程人员都是乐观主义者,无论是什么样的程序,结果是勿庸置疑的:"这次它肯定会运行。" 或者 "我刚刚找出了最后一个问题。"
-- 人月神话
以上所述就是小编给大家介绍的《容器化 RDS:借助火焰图定位Kubernetes性能问题》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Google's PageRank and Beyond
Amy N. Langville、Carl D. Meyer / Princeton University Press / 2006-7-23 / USD 57.50
Why doesn't your home page appear on the first page of search results, even when you query your own name? How do other web pages always appear at the top? What creates these powerful rankings? And how......一起来看看 《Google's PageRank and Beyond》 这本书的介绍吧!