38

PaaS容器集群优化之路

 5 years ago
source link: http://dockone.io/article/8678?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

1. 性能优化面对的挑战

以下是整个PaaS平台的架构

其中主要包括这些子系统:

微服务治理框架:为应用提供自动注册、发现、治理、隔离、调用分析等一系列分布式/微服务治理能力,屏蔽分布式系统的复杂度。

应用调度与资源管理框架:打通从应用建模、编排部署到资源调度、弹性伸缩、监控自愈的生命周期管理自动化。

应用开发流水线框架:打通从编写代码提交到自动编译打包、持续集成、自动部署上线的一系列CI/CD全流程自动化。

云中间件服务:应用云化所需的数据库、大数据、通信和应用中间件服务;通过服务集成管控可集成传统非云化的中间件能力。

面对一个如此复杂的系统,性能优化工作是一个非常艰巨的挑战,这里有这么一些痛点:

源代码及开发组件多,100+ git repo,整体构建超过1天

运行架构复杂,全套安装完需要30+VM,200+进程

软件栈深,网络平面复杂

集群规模大,5k — 10k节点环境搭建非常困难

系统操作会经过分布式的多个组件,无法通过单一组件诊断发现系统瓶颈

无法追踪上千个处于不同层次的API的时延和吞吐

大部分开发人员专注于功能开发,无法意识到自己的代码可能造成性能问题

2. 优化分析

那么,对于这么一个大的、复杂的系统,从方法论的角度来讲,应该怎么去优化呢?基本思路就是做拆分,把一个大的问题分解为多个互相不耦合的维度,进行各个击破。从大的维度来讲,一个PaaS容器集群,可以分为3个大的子系统。

控制子系统:控制指令的下发和运行(k8s),例如创建pod

业务流量子系统:容器网络(flannel)、负载均衡(ELB/kube-proxy)

监控子系统:监控告警数据的采集(kafka, Hadoop)

这个看起来仅仅是一个架构上的划分,那么如何和具体的业务场景对应起来呢?我们可以考虑如下一个场景,在PaaS平台上大批量的部署应用。看看在部署应用的过程中,会对各个子系统产生什么压力。

应用软件包大小:400M

应用模板大小:10M

1000个节点,每个节点一个POD,一个实例

10种类型的软件包,依赖长度为3,10GB 网络

调度及资源管理 3VM

这是一个典型的部署应用的一些规格,那么对于这样的一个输入,我们可以按照架构把压力分解到每个子系统上,这样得出的子系统需要支撑的指标是:

控制子系统: kubernetes调度速度 > 50 pods/s,仓库支持300并发下载,>40M/s

数据子系统:overlay容器网络TCP收发性能损耗 <5%

监控子系统:在上面这个场景中不涉及,但可以从别的场景大致告警处理能力100条/秒

这里的业务场景:架构分析:子系统指标,这三者是m:1:n的,也就是说在不同场景下对不同的组件的性能要求不同,最后每个组件需要取自己指标的最大值。

指标决定了后续怎么进行实验测试,而测试是要花较大时间成本的,所以在指标的选取上要求少求精,尽量力图用2-3个指标衡量子系统。

3. 优化测试 & 工具

上面讲的还是偏纸上的推演和分析,接下来进入实战阶段

rUVvae7.png!web

对于服务器后端的程序来讲,推荐使用Promtheus这个工具来做指标的定义和采集。Promtheus的基本工作原理是:后端程序引入Promtheus的SDK,自定义所有需要的测量的指标,然后开启一个http的页面,定期刷新数据。Promtheus服务器会定期抓取这个页面上的数据,并存在内部的时间序列数据库内。这种抓而非推的方式减少了对被测试程序的压力,避免了被测程序要频繁往外发送大量数据,导致自身性能反而变差而导致测量不准确。Promtheus支持这几种数据类型:

计数(对应收集器初始化方法NewCounter、NewCounterFunc、NewCounterVec,单一数值,数值一直递增,适合请求数量统计等)

测量(对应收集器初始化方法NewGauge、NewGaugeFunc、NewGaugeVec,单一数值,数值增减变动,适合CPU、Mem等的统计)

直方图测量(对应收集器初始化方法NewHistogram、NewHistogramVec,比较适合时长等的统计)

概要测量(对应收集器初始化方法NewSummary、NewSummaryVec,比较适合请求时延等的统计)

我们可以看看在kubernetes项目里面是怎么用的:

var ( // TODO(a-robinson): Add unit tests for the handling of these metrics once // the upstream library supports it. requestCounter = prometheus.NewCounterVec( prometheus.CounterOpts{ Name: "apiserver_request_count", Help: "Counter of apiserver requests broken out for each verb, API resource, client, and HTTP response contentType and code.", }, []string{"verb", "resource", "client", "contentType", "code"}, ) requestLatencies = prometheus.NewHistogramVec( prometheus.HistogramOpts{ Name: "apiserver_request_latencies", Help: "Response latency distribution in microseconds for each verb, resource and client.", // Use buckets ranging from 125 ms to 8 seconds. Buckets: prometheus.ExponentialBuckets(125000, 2.0, 7), }, []string{"verb", "resource"}, ) requestLatenciesSummary = prometheus.NewSummaryVec( prometheus.SummaryOpts{ Name: "apiserver_request_latencies_summary", Help: "Response latency summary in microseconds for each verb and resource.",// Make the sliding window of 1h. MaxAge: time.Hour, }, []string{"verb", "resource"}, ) )

在这里,一个http请求被分为verb, resource, client, contentType, code这五个维度,那么后面在PromDash上就能图形化的画出这些请求的数量。 从而分析哪种类型的请求是最多,对系统造成最大压力的,如图

yyEJf2y.png!web

除了Promtheus,还可以引入其他的测量手段,对系统进行分析。

Ev6vaiU.png!web

在kubernetes调度过程中,各个状态Pod的数量,看哪一步是最卡的

2iM322U.png!web

go pprof分析,哪些函数是最耗CPU的

4. 优化开发

发现了瓶颈之后,下一步就是解决瓶颈,和具体业务逻辑有关,本文在这里就不做过多的阐释。需要对相关代码非常熟悉,在不改变功能的情况下增强性能,基本思路为并发/缓存/去除无用步骤等。

5. 优化的优化

在上面的优化过程当中,基本上工程师要做几百次优化的测试和开发。这里会产生一个循环:

测试寻找瓶颈点

修改代码突破这个瓶颈点

重新测试验证这段代码是否有效,是否需要改优化思路

这就是一个完整的优化的迭代过程,在这个过程当中,大部分时间被浪费在构建代码、搭建环境、输出报告上。开发人员真正思考和写代码的时间比较短。为了解决这个问题,就需要做很多自动化的工作。在kubernetes优化的过程中,有这么几项方法可以节省时间:

qIfiUni.png!web

kubemark模拟器 :社区项目,使用容器模拟虚拟机,在测试中模拟比达到1:20,也就是一台虚拟机可以模拟20台虚拟机对apiserver产生的压力。在测试过程当中,我们使用了500台虚拟机,模拟了10000节点的控制面行为。

CI集成:提交PR后自动拉性能优化分支并开始快速构建

CD集成:使用I层的快照机制,快速搭建集群并执行测试案例输出测试报告

以上都是在实践过程中总结的一些点,对于不同的项目工程应该有很多点可以做进一步的优化,提升迭代效率。

在搭建完这套系统后,我们发现这个系统可以从源头上预防降低系统性能的代码合入主线。如果一项特性代码造成了性能下降,在CI的过程当中,功能开发者就能收到性能报告,这样开发者就能自助式的去查找自己代码的性能问题所在,减少性能工程师的介入。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK