Kubernetes上的MySQL性能测验


以前,我曾经发过题为《Kubernetes上运行自定义配置的MySQL/Percona服务器》的文章。目的是让Kubernetes平台上的MySQL可以使用全部的系统资源。 今天,我将在Kubernetes上,测验一下MySQL运行时,是否存在某些性能问题,以及展示一下尝试测验过程中所遇到的挑战。如果你想和者更多Kubernetes技术专家交流,可以加我微信liyingjiese,备注『加群』。群里每周都有全球各大公司的最佳实践以及行业最新动态

我将采用一个非常简单的CPU计算密集型基准来测验MySQL数据库在OLTP只读工作负载下的性能情况,命令和参数如下:
sysbench oltp_read_only --report-interval=1 --time=1800 --threads=56 --tables=10 --table-size=10000000 --mysql-user=sbtest --mysql-password=sbtest --mysql-socket=/var/lib/mysql/mysql.sock run

参考硬件环境配置如下:

超微服务器
  • Intel(R) Xeon(R) CPU E5-2683 v3 @ 2.00GHz
  • 2 CPU/28核/56线程
  • 256GB 内存


请注意:CPU是28核/56线程,稍后的测试会关系到这个数字。

先来看看MySQL在裸金属机环境的性能情况:
[ 607s ] thds: 56 tps: 22154.20 qps: 354451.12 (r/w/o: 310143.73/0.00/44307.39) lat (ms,95%): 2.61 err/s: 0.00 reconn/s: 0.00
[ 608s ] thds: 56 tps: 22247.80 qps: 355955.88 (r/w/o: 311461.27/0.00/44494.61) lat (ms,95%): 2.61 err/s: 0.00 reconn/s: 0.00
[ 609s ] thds: 56 tps: 21984.01 qps: 351641.13 (r/w/o: 307672.12/0.00/43969.02) lat (ms,95%): 2.66 err/s: 0.00 reconn/s: 0.00

这个硬件环境下测试结果,可以取近似值为22000 tps。

接下来,我们在同样的服务器环境下,依次部署Kubernetes节点,Percona服务器系统镜像。所采用的镜像为修改过的Percona Server 8,镜像已经包含了sysbech测验软件。镜像下载链接在:https://hub.docker.com/r/vadimtk/ps-8-vadim

对应的deployment的yaml配置如下:
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
selector:
app: mysql
ports:
- name: mysql
  port: 3306
  protocol: TCP
  targetPort: 3306

apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
name: mysql
spec:
selector:
matchLabels:
  app: mysql
strategy:
type: Recreate
template:
metadata:
  labels:
    app: mysql
spec:
  nodeSelector:
    kubernetes.io/hostname: smblade01
  volumes:
    - name: mysql-persistent-storage
      hostPath:
        path: /mnt/data/mysql
        type: Directory
    - name: config-volume
      configMap:
        name: mysql-config
        optional: true
  containers:
  - image: vadimtk/ps-8-vadim
    imagePullPolicy: Always
    name: mysql
    env:
      # Use secret in real usage
    - name: MYSQL_ROOT_PASSWORD
      value: password
    ports:
    - containerPort: 3306
      name: mysql
    volumeMounts:
    - name: mysql-persistent-storage
      mountPath: /var/lib/mysql
    - name: config-volume
      mountPath: /etc/my.cnf.d

较为重要的一点是:测试中的镜像部署,都是部署在smblade01节点上,和前面的测试部署是相同的。

然后再看看部署后的性能测试情况。数据如下:
[ 605s ] thds: 56 tps: 10561.88 qps: 169045.04 (r/w/o: 147921.29/0.00/21123.76) lat (ms,95%): 12.98 err/s: 0.00 reconn/s: 0.00
[ 606s ] thds: 56 tps: 10552.00 qps: 168790.98 (r/w/o: 147685.98/0.00/21105.00) lat (ms,95%): 15.83 err/s: 0.00 reconn/s: 0.00
[ 607s ] thds: 56 tps: 10566.00 qps: 169073.97 (r/w/o: 147942.97/0.00/21131.00) lat (ms,95%): 5.77 err/s: 0.00 reconn/s: 0.00
[ 608s ] thds: 56 tps: 10581.08 qps: 169359.21 (r/w/o: 148195.06/0.00/21164.15) lat (ms,95%): 5.47 err/s: 0.00 reconn/s: 0.00
[ 609s ] thds: 56 tps: 12873.80 qps: 205861.77 (r/w/o: 180116.17/0.00/25745.60) lat (ms,95%): 5.37 err/s: 0.00 reconn/s: 0.00
[ 610s ] thds: 56 tps: 20196.89 qps: 323184.24 (r/w/o: 282789.46/0.00/40394.78) lat (ms,95%): 3.02 err/s: 0.00 reconn/s: 0.00
[ 611s ] thds: 56 tps: 18033.21 qps: 288487.30 (r/w/o: 252421.88/0.00/36065.41) lat (ms,95%): 5.28 err/s: 0.00 reconn/s: 0.00
[ 612s ] thds: 56 tps: 11444.08 qps: 183129.22 (r/w/o: 160241.06/0.00/22888.15) lat (ms,95%): 5.37 err/s: 0.00 reconn/s: 0.00
[ 613s ] thds: 56 tps: 10597.96 qps: 169511.35 (r/w/o: 148316.43/0.00/21194.92) lat (ms,95%): 5.57 err/s: 0.00 reconn/s: 0.00
[ 614s ] thds: 56 tps: 10566.00 qps: 169103.93 (r/w/o: 147969.94/0.00/21133.99) lat (ms,95%): 5.67 err/s: 0.00 reconn/s: 0.00
[ 615s ] thds: 56 tps: 10640.07 qps: 170227.13 (r/w/o: 148948.99/0.00/21278.14) lat (ms,95%): 5.47 err/s: 0.00 reconn/s: 0.00
[ 616s ] thds: 56 tps: 10579.04 qps: 169264.66 (r/w/o: 148106.58/0.00/21158.08) lat (ms,95%): 5.47 err/s: 0.00 reconn/s: 0.00

结果的差异性很大。数值分布在10550 tps到20196 tps之间,但绝大多数都是10000 tps上下。我们基本上可以理解为:MySQL迁移到Kubernetes上后,损失了将近一半的吞吐量。这个结论有点悲观,但也别先急于悲伤,应该是有办法优化的。我们首先需要搞清楚这个结果的产生原因。问题的答案在于Kubernetes如何应用Pod 的QoS

默认情况下(假定不考虑CPU或内存限制),QoS后的结果会是最佳的效果,如果我们要确保QoS是有保证,应该给它分配所有CPU资源。为此,我们镜像的配置定义中,添加如下内容:
resources:
      requests:
        cpu: "55500m"
        memory: "150Gi"
      limits:
        cpu: "55500m"
        memory: "150Gi"

在定义CPU限制时,遇到一个有意思的问题。正如前面提到的56个CPU线程,所以最初时,我尝试将这个数值设定为“56”开头的值,结果发现Kubernetes无法启动Pod,错误提示为CPU不足。我猜应该是Kubernetes不能给内部应用分配100%的CPU资源导致的,于是就设定为cpu: "55500m",这也表示只给Percona服务器分配了55.5个CPU线程。

Guaranteed QoS的测验结果如下:
[ 883s ] thds: 56 tps: 20320.06 qps: 325145.96 (r/w/o: 284504.84/0.00/40641.12) lat (ms,95%): 2.81 err/s: 0.00 reconn/s: 0.00
[ 884s ] thds: 56 tps: 20908.89 qps: 334587.21 (r/w/o: 292769.43/0.00/41817.78) lat (ms,95%): 2.81 err/s: 0.00 reconn/s: 0.00
[ 885s ] thds: 56 tps: 20529.03 qps: 328459.46 (r/w/o: 287402.40/0.00/41057.06) lat (ms,95%): 2.81 err/s: 0.00 reconn/s: 0.00
[ 886s ] thds: 56 tps: 17567.75 qps: 281051.03 (r/w/o: 245914.53/0.00/35136.50) lat (ms,95%): 5.47 err/s: 0.00 reconn/s: 0.00
[ 887s ] thds: 56 tps: 18036.82 qps: 288509.07 (r/w/o: 252437.44/0.00/36071.63) lat (ms,95%): 5.47 err/s: 0.00 reconn/s: 0.00
[ 888s ] thds: 56 tps: 18398.23 qps: 294399.67 (r/w/o: 257603.21/0.00/36796.46) lat (ms,95%): 5.47 err/s: 0.00 reconn/s: 0.00
[ 889s ] thds: 56 tps: 18402.90 qps: 294484.45 (r/w/o: 257677.65/0.00/36806.81) lat (ms,95%): 5.47 err/s: 0.00 reconn/s: 0.00
[ 890s ] thds: 56 tps: 19428.12 qps: 310787.86 (r/w/o: 271934.63/0.00/38853.23) lat (ms,95%): 5.37 err/s: 0.00 reconn/s: 0.00
[ 891s ] thds: 56 tps: 19848.69 qps: 317646.11 (r/w/o: 277947.73/0.00/39698.39) lat (ms,95%): 5.28 err/s: 0.00 reconn/s: 0.00
[ 892s ] thds: 56 tps: 20457.28 qps: 327333.49 (r/w/o: 286417.93/0.00/40915.56) lat (ms,95%): 2.86 err/s: 0.00 reconn/s: 0.00

结果表示有了很大的改善,大多数值都接近20000 tps。但依然没有达到22000 tps的级别。我不确定为什么仍然有10%的性能损失的原因,但它可能与GitHub上提到的一个Pod Guaranteed的CPU配置问题有关。同时,我还发现有一项优化Guaranteed QoS性能的工作正在进行中,目前还没有被合并到主版本中,希望它能在下一个版本中出现吧。

结论:
  • 在Kubernetes Pod上,采用开箱即用的方式部署应用时,所看到的性能可能会非常差。
  • 为了改善用户体验,我们建议使用Guaranteed QoS,但Kubernetes上配置这个却不太友好。需要手动设置CPU线程的数量,如果使用动态性的云实例时,也不是那么清晰易见。
  • 采用Guaranteed QoS方式,目前仍然有10%左右的性能开销,我认为这个代价应该是当下必须接受的。


原文链接:Measuring MySQL Performance in Kubernetes(翻译:易理林)

0 个评论

要回复文章请先登录注册