IMLC.ME

Kubernetes 网络性能压测工具 - fortio

fortio 是 Istio 推出的一款网络压测工具。 非常方便地,fortio 自带了 HTTP 服务,对于单独测试 Kubernetes 的网络性能或者 Istio(Service Mesh) 的网络性能非常有帮助。

下文叙述了如何部署 fortio 的客户端和服务端,并且运行性能测试。

如果你人在中国,由于网络原因你可能无法直接拉去镜像。 你可以使用 docker.mirrors.ustc.edu.cn 等国内 Docker 镜像服务 拉取镜像

1. 安装 fortio 服务

通过命令应用如下的yaml文件
kubectl apply -f fortio-server.yaml

这份 yaml 部署了 fortio-server ,http 服务暴露在了容器内的8080端口。
同时也创建了同名的 fortio-server Kubernetes 服务。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: fortio-server
  labels:
    app: fortio-server
spec:
  replicas: 1
  selector:
    matchLabels:
      app: fortio-server
  template:
    metadata:
      labels:
        app: fortio-server
    spec:
      containers:
        - name: fortio-server
          # 在中国,你可以使用 docker.mirrors.ustc.edu.cn/fortio/fortio:latest
          image: fortio/fortio:latest
          ports:
            - containerPort: 8080
              name: http-port
            - containerPort: 8078
              name: udp-port
            - containerPort: 8079
              name: grpc-port
            - containerPort: 8081
              name: https-port
          command:
            - fortio
            - server
---
apiVersion: v1
kind: Service
metadata:
  name: fortio-server
spec:
  ports:
    - name: http-port
      port: 8080
      protocol: TCP
      targetPort: 8080
    - name: https-port
      port: 8081
      protocol: TCP
      targetPort: 8081
    - name: http2-grpc
      port: 8079
      protocol: TCP
      targetPort: 8079
    - name: udp-grpc
      port: 8078
      protocol: UDP
      targetPort: 8078
  selector:
    app: fortio-server
  type: NodePort

fortio server 启动后,你可以看到类似如下的输出:

[email protected]:~$ kubectl logs fortio-server-55cdbd8b6b-rddq7
Fortio 1.20.0 tcp-echo TCP server listening on [::]:8078
Fortio 1.20.0 udp-echo UDP server listening on [::]:8078
Fortio 1.20.0 grpc 'ping' TCP server listening on [::]:8079
15:54:13 I fortio_main.go:272> Note: not using dynamic flag watching (use -config to set watch directory)
15:54:13 I fortio_main.go:280> All fortio 1.20.0 2021-12-24 21:20 4a325b93146c7faf5d7ff5a327d3c86abceb141f go1.17.3 servers started!
Fortio 1.20.0 https redirector TCP server listening on [::]:8081
Fortio 1.20.0 echo TCP server listening on [::]:8080
Data directory is /var/lib/fortio
UI started - visit:
http://localhost:8080/fortio/
(or any host/ip reachable on this server)

2. 安装并执行 fortio 客户端

应用下面的yaml文件启动 fortio 客户端。

注意 annotations 中的 proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'
这个配置用于确保 fortio client 在 istio sidecar启动之后,再执行。 否则,fortio client 会无法连接网络直接报错。

如果你没有安装 service mesh,就不需要添加这个 annotation。
如果你想在无客户端 sidecar 的情况下压测,可以使用 sidecar.istio.io/inject: "false" 关闭 sidecar 注入。
如果你安装的是其他 service mesh,就需要自己找相关的配置了。

注意这里的命令行参数 -t 1m表示测试1分钟,由于 Kubernetes Job 的限制,我们只能使用定时长的方式执行测试。

apiVersion: batch/v1
kind: Job
metadata:
  name: fortio-client
spec:
  template:
    metadata:
      annotations:
        # Or sidecar.istio.io/inject: "false"
        proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'
    spec:
      containers:
        - name: fortio
          # 在中国,你可以使用 docker.mirrors.ustc.edu.cn/fortio/fortio:latest
          image: fortio/fortio:latest
          command: ["fortio",  "load", "-t", "1m", "http://fortio-server:8080"]
      restartPolicy: Never

测试完成后的输出如下:

[email protected]:~$ kubectl logs  -f fortio-client-mdmwv
Fortio 1.20.0 running at 8 queries per second, 8->8 procs, for 1m0s: http://fortio-server:8080
16:58:59 I httprunner.go:81> Starting http test for http://fortio-server:8080 with 4 threads at 8.0 qps
Starting at 8 qps with 4 thread(s) [gomax 8] for 1m0s : 120 calls each (total 480)
16:59:59 I periodic.go:564> T000 ended after 1m0.002138897s : 120 calls. qps=1.999928705974843
16:59:59 I periodic.go:564> T002 ended after 1m0.002301506s : 120 calls. qps=1.9999232860759593
16:59:59 I periodic.go:564> T003 ended after 1m0.002326776s : 120 calls. qps=1.9999224438075982
16:59:59 I periodic.go:564> T001 ended after 1m0.002334446s : 120 calls. qps=1.9999221881607923
Ended after 1m0.002352026s : 480 calls. qps=7.9997
Sleep times : count 476 avg 0.50166692 +/- 0.0007058 min 0.497964387 max 0.502901729 sum 238.793456
Aggregated Function Time : count 480 avg 0.0017757797 +/- 0.0004973 min 0.001110734 max 0.006039904 sum 0.852374263
# range, mid point, percentile, count
>= 0.00111073 <= 0.002 , 0.00155537 , 80.42, 386
> 0.002 <= 0.003 , 0.0025 , 97.08, 80
> 0.003 <= 0.004 , 0.0035 , 99.17, 10
> 0.004 <= 0.005 , 0.0045 , 99.79, 3
> 0.006 <= 0.0060399 , 0.00601995 , 100.00, 1
# target 50% 0.00166277
# target 75% 0.00193995
# target 90% 0.002575
# target 99% 0.00392
# target 99.9% 0.00602075
Sockets used: 4 (for perfect keepalive, would be 4)
Jitter: false
Code 200 : 480 (100.0 %)
Response Header Sizes : count 480 avg 124 +/- 0 min 124 max 124 sum 59520
Response Body/Total Sizes : count 480 avg 124 +/- 0 min 124 max 124 sum 59520
All done 480 calls (plus 4 warmup) 1.776 ms avg, 8.0 qps

3. 在容器内手工执行 fortio 测试

从第二点可以看出,通过 Kubernetes Job 跑测试其实非常不方便。个人主要在自动化压测的场景下,才会通过创建 Job 的方式执行测试。

其他情况,通常是手工执行命令更加方便。

下方的yaml文件是创建一个ubuntu的辅助容器。之后,kubectl exec -it ubuntu-xxx-xxx -- bash,就是我们熟悉的 Linux 环境了。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ubuntu
  labels:
    app: ubuntu
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ubuntu
  template:
    metadata:
      labels:
        app: ubuntu
    spec:
      containers:
        - name: ubuntu
          # 在中国,你可以使用 docker.mirrors.ustc.edu.cn/ubuntu/ubuntu:latest
          image: ubuntu:22.04
          command:
            - sleep
            - 365d

然后安装 fortio

apt get install curl -y
curl -L https://github.com/fortio/fortio/releases/download/v1.20.0/fortio-linux_x64-1.20.0.tgz \
 | tar -C / -xvzpf -