Kubernetes测试系列 - 性能测试

序言

对软件系统而言,性能测试通常包括两部分,一是制造合适的负载,二是在负载条件下进行合理的观测。

定义观测对象

任何系统都是有性能边界的,保证性能需要成本、人力、时间,不可能无休止地亦或是全方位地要求性能指标。
开发软件系统的目的是为了更好的服务用户,用户对系统有品质要求。影响到用户品质要求的性能指标是主要的、核心的指标,其它的是次要的指标(比如程序员拍脑袋想的指标)。因此,在进行性能测试之前,定义哪些指标会影响到用户品质要求是必须的工作,哪怕定义的指标不全面。盲目进行性能测试得到的通常是毫无意义的结果。

通常云厂商使用SLA(服务等级协议)来概括用户对系统的品质要求。遗憾的是,由于Kubernetes的复杂性,截止至2019.5.18,各大云厂商都没有提供可以最终公布的SLA。
Kubernetes社区提供了一些SLI(服务等级指标)和SLO(服务等级目标)指导系统性能测试、分析,详见跳转地址。这些指标间接地描述了Kubernetes系统服务品质,是性能测试重点关注的指标。
除此之外,Master机器的CPU、Memory等指标,以及ETCD的ioutil等指标也会对Kubernetes服务造成明显影响,因此同样应当纳入性能测试的观测范围。

制造集群负载

  • 便宜的负载
    社区资料表明Kubernetes可以支持5000台Node、15万Pod的集群良好运行。这意味着,验证这一说法至少应该制造5000台Node、15万Pod的负载。然而获得5000台真实机器的使用权很贵,长期占用这么多机器用于Kubernetes的开发测试是不科学的。因此,社区开发了kubemarkVirtual Kubelet等工具用于模拟真实Node,使用少量机器也可以制造出足够大的负载。在小米的测试过程中,20台真实机器可以模拟3000台Node、10万个Pod的负载情况。
  • 多样的负载
    在实际运行环境中,真实负载情况是多种多样的,不同的负载可能对系统的性能指标有不同的影响,在测试过程中模拟多种负载情况是必要的。为了方便模拟多样的负载情况,性能测试提供负载的程序可配置性应当尽可能强。在早期的Kubernetes代码中,性能测试程序的各项参数写死在代码中,要修改Kubernetes源码重新编译后,拷贝到测试环境,才能修改一次测试参数。测试过程十分痛苦。
    因此社区开发了perf-test/clusterloader2,可配置性极强,并且配备了相应的性能指标观测代码,十分推荐。

工具使用说明

Kubernetes性能测试的前置要求:

  • 准备运行良好的Kubernetes集群

本文接下来介绍性能测试工具kubemarkperf-test/clusterloader2

kubemark

kubemark是阉割版的kubelet,除了不调用CRI接口之外(即不调用Docker,直接返回),其它行为和kubelet基本一致。

编译
  • 编译二进制
    下载kubernetes源码,执行make WHAT='cmd/kubemark'
  • 编译镜像
    编译docker镜像的脚本在test/kubemark/start-kubemark.sh中,因为要涉及到一些代码改造,在此不作说明。
使用步骤
  • 标记真实Node
    1.设置Taint
    假设Node名字是mytestnode,执行以下命令设置Taint。
    kubectl taint nodes mytestnode role=real:NoSchedule
    设置Taint的目的在于,避免压力测试的Pod调度至真实Node上。
    2.设置Label
    假设Node名字是mytestnode,执行以下命令设置Label。
    kubectl label nodes mytestnode role=real
  • 配置kubeconfig
apiVersion: v1
kind: Config
users:
- name: kubelet
  user: {}
clusters:
- name: kubemark
  cluster:
    server: http://10.114.25.172:8083 #替换成你自己的APIServer地址
contexts:
- context:
    cluster: kubemark
    user: kubelet
  name: kubemark-context
current-context: kubemark-context

假如上述kubeconfig保存在/home/mi/.kube/config,执行以下命令创建secret

kubectl create secret generic kubeconfig --from-file=kubelet.kubeconfig=/home/mi/.kube/config
  • 创建kubemark Pod
    执行以下脚本运行kubemark:
curl -L https://gist.githubusercontent.com/Betula-L/fef068ef7e914aa4a52113ac81fc6517/raw/77abf3f9b234274e33435597dec079ef46300324/kubemark.yaml | kubectl apply -f -
注意事项
  • kubemark版本尽量和master版本一致
  • 上述说明只适用没有开启认证授权的master

clusterloader2

运行要求
  • master节点开放ssh服务
  • 测试启动时刻所有Node处于Ready状态(包括hollow node)
编译

下载pert-tests项目,运行${perf-tests}/clusterloader2/run-e2e.sh或者如下脚本编译二进制文件。

CLUSTERLOADER_ROOT=${perf-tests}
cd ${CLUSTERLOADER_ROOT}/ && go build -o clusterloader './cmd/'
使用步骤
  • 设置环境变量
# kube config for kubernetes api
KUBE_CONFIG=${HOME}/.kube/config

# Provider setting
# Supported provider for xiaomi: local, kubemark, lvm-local, lvm-kubemark
PROVIDER='kubemark'

# SSH config for metrics' collection
KUBE_SSH_KEY_PATH=$HOME/.ssh/id_rsa
MASTER_SSH_IP=10.142.43.51
MASTER_SSH_USER_NAME=root

# Clusterloader2 testing strategy config paths
# It supports setting up multiple test strategy. Each testing strategy is individual and serial.
TEST_CONFIG='configs/examples/density/config.yaml'

# Clusterloader2 testing override config paths
# It supports setting up multiple override config files. All of override config files will be applied to each testing strategy.
# OVERRIDE_CONFIG='testing/density/override/200-nodes.yaml'

# Log config
REPORT_DIR='./reports'
LOG_FILE='logs/tmp.log'

填充上述脚本内容,并使用source命令设置好Linux环境变量

  • 运行clusterloader2
$CLUSTERLOADER_BIN --kubeconfig=$KUBE_CONFIG \
    --provider=$PROVIDER \
    --masterip=$MASTER_SSH_IP --mastername=$MASTER_SSH_USER_NAME \
    --testconfig=$TEST_CONFIG \
    --report-dir=$REPORT_DIR \
    --alsologtostderr 2>&1 | tee $LOG_FILE
#   --testoverrides="${OVERRIDE_CONFIG:-}" \

按上述命令运行clusterloader2,其中CLUSTERLOADER_BIN是编译好的clusterloader2二进制文件位置,其它参数是设置好的环境变量。

测试说明

pert-tests只是性能测试框架,具体的性能测试策略需要用户自己通过配置文件定义。
kubernetes density测试为例,解释clusterloader2的测试过程及其结果。
density测试策略

  1. 启动若干个观测程序
    测试策略配置文件中,所有的Measurement都是用于采集数据的观测程序。perf-tests提供了十几个Measurement,density测试使用了其中5个,包括APIResponsivenessSaturationPodStartupLatencyWaitForRunningSaturationRCsSchedulingThroughputPodStartupLatency
  2. 系统调度吞吐测试
    kubernetes认为每个Node运行30个Pod是机器正常负载情况。一次性发布#node*30个Pod用于测试集群的调度吞吐性能,可以说明“系统发生大规模故障后,从零到正常负载所需恢复时间”,调度吞吐量定义如下:
              调度吞吐量=一段较长时间内最大可以发布的Pod数量/总发布时间
    值得注意的是,clusterloader2不是简单地使用一个rc创建#node*30个Pod,因为kubernetes对系统的使用有一些基本假设,包括“每个namespace的Pod数量不超过3000”,“每个node的Pod数量不能超过110”等。为了满足这些基本假设,clusterloader2在创建rc时,做了不少的特殊处理。
  3. Pod启动e2e耗时测试
    为了说明Pod启动e2e耗时,在不删除“调度吞吐测试”负载的基础上,进行latency测试。
    latency测试策略是每隔0.2秒创建一个pod,根据pod创建过程中产生的timestamp和event,计算出Pod启动过程中,每个阶段的耗时和总e2e耗时。如果调度吞吐量<5pods/s,则创建Pod的时间间隔应当设置大于0.2s。
    目前latency测试存在精度问题,因为kubernetes event存储的时间是RFC3339,导致部分阶段的耗时精度只到秒,对性能分析价值不大。
    density测试策略

测试结果

  • stdout/stderr
    整个性能测试过程以及部分测试结果会打印到stdout中,如果按本文所述方法运行clusterloader2,打印结果会保存一份至${LOG_FILE}
调度吞吐量结果:
Jan  9 13:55:47.876: INFO: E2E startup time for 10500 pods: 28m40.333662404s
Jan  9 13:55:47.876: INFO: Throughput (pods/s) during cluster saturation phase: 6.1034675
^[[1mSTEP^[[0m: Printing Pod to Node allocation data
Jan  9 13:55:47.884: INFO: Density Pods: 10500 out of 10500 created, 10500 running, 0 pending, 0 waiting, 0 inactive, 0 terminating, 0 unknown, 0 runningButNotReady
Pod启动e2e耗时结果:
Jan  9 14:09:31.598: INFO: perc50: 1614, perc90: 2241, perc99: 2541
Jan  9 14:09:31.598: INFO: Approx throughput: 7486.052881923156 pods/min
  • report文件夹
    详细的性能测试结果clusterloader2收集在report文件夹下,如果按本文方法运行,则结果存放在{$REPORT_DIR}中。因为涉及到的性能测试结果非常多,本文不在此一一列举。目前Kubernetes性能分析最主要的性能指标如下:
    • APIServer Restful API响应时间 - APIResponsiveness
    • Pod 启动总耗时 - PodStartupLatency
    • Scheduler调度性能 - SchedulingThroughput, SchedulingMetrics
    • ETCD指标 - EtcdMetrics
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,427评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,551评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,747评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,939评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,955评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,737评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,448评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,352评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,834评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,992评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,133评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,815评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,477评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,022评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,147评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,398评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,077评论 2 355

推荐阅读更多精彩内容