1

istio: 如何对istio数据平面进行benchmark

 1 year ago
source link: https://ieevee.com/tech/2022/06/27/11-benchmark.html
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.

istio: 如何对istio数据平面进行benchmark

by 伊布

istio在应用时,会遇到的2个典型质疑是:

  • istio增加了单独的数据平面,从传输的角度来说增加了2跳,势必会带来latency的增加。那么latency的增加到底是多少呢?
  • proxy容器需要实现数据面的报文劫持、转发,以及一些策略的实施,其需要的cpu、内存,是多少呢?

要回答这些问题,就要对istio的数据面进行量化。 istio社区提供了一个工具来进行具体的测试:istio tools perf benchmark

为什么不需要对控制面进行量化呢?主要原因是数据面是O(n)的空间复杂度,而控制面几乎是O(1)的空间复杂度。另外一个原因是目前istio的遥测、限流等策略,均为envoy实现,不再交由mixer组件处理,因此集群规模提升后对控制面来说变化不大。

istio tools perf benchmark需要读取Pod的监控信息,因此部署istio时,需要增加Prometheus组件。具体参考Prometheus安装

tools install

安装参考 readme即可。

  1. 资源需求比较多,要求至少32 cpu、4个node。建议使用完善的生产集群,确保硬件资源充裕。
  2. 测试套依赖python3/pip3/pipenv,所以最好是在有网环境进行安装,我这里选择的是本地PC;若离线安装,可能会遇到一些镜像源获取不到的问题。
  3. 不要在docker环境中安装,测试套运行过程中会使用docker执行一些命令,如果在docker中安装会执行失败。

安装后,将在namespace twopods-istio中部署2个Deployment:fortioclient/fortioserver。下面简要说明下。

fortioclient

Deployment的编排文件请见deployment fortioclient。Pod的编排文件请见pod fortioclient

来看 Pod fortioclient。其包括4个container和1个init container:

  • captured:运行nighthawk客户端,客户端发出的报文会被proxy劫持
  • uncaptured:运行fortio客户端,客户端发出的报文不会被proxy劫持;监听9076端口,用于托管测试生成的json文件
  • shell:用于执行curl、jq等命令行
  • istio-proxy:proxy,istio注入的sidecar
  • init container:istio注入的init container,用于初始化iptables规则进行流量劫持。

注意Deployment 中设置的 excludeInboundPorts/excludeOutboundPorts的端口范围,8076/8077/8078/8081/端口是不走proxy的(具体查看fortioclient iptables规则),这里代表测试的是原生(非mesh)的性能,用于作为baseline对比;而发往8079/8080端口的报文则会被iptables劫持给proxy。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: fortioclient
  namespace: twopods-istio
..
  template:
    metadata:
      annotations:
        linkerd.io/inject: disabled
        sidecar.istio.io/inject: "true"
        sidecar.istio.io/interceptionMode: REDIRECT
        traffic.sidecar.istio.io/excludeInboundPorts: 8076,8077,8078,8081,9999
        traffic.sidecar.istio.io/excludeOutboundPorts: 80,8076,8077,8078,8081
        traffic.sidecar.istio.io/includeOutboundIPRanges: 10.222.0.0/16

fortioserver

Deployment的编排文件请见deployment fortioserver。Pod的编排文件请见pod fortioserver

fortioserver包括4个container和1个init container。

  • captured:nighthawk-test-server服务端,发给该服务的报文会被proxy劫持。具体来说,监听8079/8080/9080端口,均被劫持。
  • uncaptured:运行nighthawk-test-server服务端,发给该服务的报文不会被劫持。具体来说,监听8076/8077/8078端口,均不会被劫持。
  • shell:用于执行curl、jq等命令行
  • istio-proxy:proxy,istio注入的sidecar
  • init container:istio注入的init container,用于初始化iptables规则进行流量劫持。

fortioserver的excludeInboundPorts/excludeOutboundPorts的配置与fortioclient是一致的。

运行测试用例

runner/runner.py 用来执行测试用例。具体参数参考run-performance-tests

如下,将采用fortio作为压力源,并发连接设置为16,基准测试的qps依次设置为100,500,1000,2000,4000,每个基准测试用例持续时间为120s,遥测模式为telemetry-v2,针对如下场景进行测试:

  • both: 默认值,收发两端均通过sidecar
  • baseline: 基线,收发两端直连,均不通过sidecar
  • serversidecar: 只有server端启用sidecar
python runner/runner.py --conn 16 --qps 100,500,1000,2000,4000 --duration 120 --serversidecar --baseline --load_gen_type=fortio --telemetry_mode=v2-nullvm

这样,就可以得到5 * 3 个测试数据,从而比对不同qps下,直连、全mesh、服务端mesh场景下,时延的变化情况。

测试完毕后,在fortioclient pod的shell container中的 /var/lib/fortio/下,会生成15个json文件,数据参考fortio_json_data,该文件描述了本次基准测试的数据,如基准测试起始时间,P50/P90/P99,基准测试报文特征等。

注意,由于每次测试生成的文件都放在 /var/lib/fortio/,多次测试的数据会有干扰,建议测试前先清理下该目录。

收集指标信息

runner/fortio.py 用来收集基准测试数据、监控指标数据。具体参数参考gather-result-metrics

fortio.py依赖 fortioclient uncaptured(9076端口)、Prometheus,需要确保本地能够访问这两个地址。

我这里使用了kubectl port-forward的方式。也可以直接访问url,注意FORTIO_CLIENT_URL、PROMETHEUS_URL设置为正确的值即可。

kubectl -n twopods-istio port-forward svc/fortioclient 9076:9076 &
kubectl -n istio-system port-forward svc/prometheus 9090:9090 &

export PROMETHEUS_URL=http://localhost:9090
export FORTIO_CLIENT_URL=http://localhost:9076

配置好后,执行下面的命令。

python ./runner/fortio.py $FORTIO_CLIENT_URL --prometheus=$PROMETHEUS_URL --csv StartTime,ActualDuration,Labels,NumThreads,ActualQPS,p50,p90,p99,p999,cpu_mili_avg_istio_proxy_fortioclient,cpu_mili_avg_istio_proxy_fortioserver,cpu_mili_avg_istio_proxy_istio-ingressgateway,mem_Mi_avg_istio_proxy_fortioclient,mem_Mi_avg_istio_proxy_fortioserver,mem_Mi_avg_istio_proxy_istio-ingressgateway

fortio.py 会调用kubectl将json文件拷贝到本地的tmp目录,并依次处理目录下的json文件。

注意,由于每次收集指标时,拷贝的文件都放在相同的tmp 目录(macos),多次测试的数据会有干扰,建议测试前先清理下该目录。

执行后,会生成一个json文件和一个csv文件。csv文件参考tmpld48kepv.csv

通过简单的数据分析,可以发现,both/serveronly模式下,相对baseline,其P50时延增加了基本不超过5ms,P99不超过8ms。

tmpld48kepv.png

在一些对时延要求相对宽松的场景下,增加8ms可能不是一个很致命的问题,但在一些严苛的场景(例如结算页),留给业务处理的时间可能就几十ms(包括业务逻辑、访问数据库、访问缓存),proxy增加的延迟还是比较严重的。

graph_plotter/graph_plotter.py 可以用来对数据进行可视化。具体参数参考usage-and-example-plot

接上面的示例,我们设置横轴(x_axis)为qps,横轴的点为qps列表(query_list) [100,500,1000,2000,4000] ,纵轴(graph_type)为P90的延迟数据,进行绘图。

python3 ./graph_plotter/graph_plotter.py --graph_type=latency-p90 --x_axis=qps --telemetry_modes=v2-nullvm_serveronly,v2-nullvm_baseline,v2-nullvm_both --query_list=100,500,1000,2000,4000 --query_str=NumThreads==16 --csv_filepath=/var/folders/sf/ndqwtn_105n5c4pfcg9kh1rc19706f/T/tmpld48kepv.csv --graph_title=./graph_plotter/example_plot/plotter_output4.png

绘制图形如下,可以直观的看到both和serveronly模式相对baseline的时延增加情况。

plotter_output-p90.png

将纵轴改为 服务端的cpu使用率 --graph_type=cpu-server,可以查看到随着qps的提高,pod的cpu使用率有着明显的提升。

plotter_output-cpu-server.png

istio tools perf benchmark 通过比较巧妙Deployment编排,设计了baseline/serveronly/both等测试场景,能够形象的对istio 数据面进行基准测试,并对延迟、cpu使用率、内存使用率进行度量。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK