一、需求与目标
在实际生产环境中,无论是新业务上线,还是新功能的发布,我们都需要做整体的性能压测,以便我们能够清楚的知道系统的性能上限,而然搭建压测环境往往比较耗时,本文主要介绍怎么使用K8S快速创建locust压测服务。
二、容器和K8S基本使用介绍
1.构建docker镜像
1.1 自动构建
容器镜像自动构建基于github或者gitlab代码仓库,要求代码仓库里面必须包含Dockerfile文件。用户需要先注册github或者gitlab服务器的token,如果代码仓库使用的是gitlab,gitlab服务器要求必须能够公网访问。用户可以针对代码仓库设置自动构建规则,当用户往代码仓库发起push操作时,如果符合自动构建规则,那么就会在腾讯云容器平台上进行容器镜像的自动构建,并将构建出来的容器镜像自动推送到腾讯云容器镜像仓库中。
1.2 手动构建
1.2.1 通过 Dockerfile 手动构建镜像
1.构建镜像
代码语言:txt复制(1)docker build ./ -t 指定镜像名
(2)docker images
2.登录腾讯云docker registry
代码语言:txt复制sudo docker login --username=23966523 ccr.ccs.tencentyun.com
3.从 registry 拉取镜像
代码语言:txt复制sudo docker pull hub.tencentyun.com/3321337994/fox_test_flows:[tag]
4.将镜像推送到腾讯云registry(工蜂)
代码语言:txt复制sudo docker login --username=23966523 ccr.ccs.tencentyun.com #登录到腾讯云docker registry
sudo docker tag [ImageId] ccr.ccs.tencentyun.com/vicwan/vicwan:[tag] #给镜像打name[:tag]
sudo docker push ccr.ccs.tencentyun.com/vicwan/vicwan:[tag] #将镜像name[:tag]推送到腾讯云docker registry
其中 ImageId 请根据您的实际镜像 ID 信息进行填写, tag 请根据您的镜像版本信息进行填写。
1.2.2执行 Commit 实现打包生成镜像
1.运行centos基础镜像容器,并进入console
代码语言:txt复制docker run -i -t centos
2.安装需要的软件,并添加配置
代码语言:txt复制yum update && yum install openssh-server
3.配置完成后打开另外一个终端,保存镜像
代码语言:txt复制shell
[root@VM_88_88_centos ~]# docker ps #查看正在运行的容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f5f1beda4075 centos "/bin/bash" 8 minutes ago Up 8 minutes hungry_kare
[root@VM_88_88_centos ~]# docker commit f5f1beda4075 test:v1.0
sha256:65325ffd2af9d574afca917a8ce81cf8a710e6d1067ee611a87087e1aa88e4a4
[root@VM_88_88_centos ~]#
[root@VM_88_88_centos ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test v1.0 65325ffd2af9 11 seconds ago 307.8 MB
4.运行Docker镜像
代码语言:txt复制docker run -d --name name[:tag] #-d:让容器在后台运行
5.Docker 清理命令
杀死所有正在运行的容器
代码语言:txt复制docker kill $(docker ps -a -q)
删除所有已经停止的容器
代码语言:txt复制docker rm $(docker ps -a -q)
通过镜像的id来删除指定镜像
代码语言:txt复制docker rmi <image id>
删除所有镜像
代码语言:txt复制docker rmi $(docker images -q)
2.通过Kubectl操作集群
2.1 安装 kubectl 工具
2.1.1下载 kubectl 工具
mac os系统:
代码语言:txt复制curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.8.13/bin/darwin/amd64/kubectl
Linux系统:
代码语言:txt复制curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.8.13/bin/linux/amd64/kubectl
2.1.2赋予执行权限
代码语言:txt复制chmod x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl
2.1.3测试安装结果
代码语言:txt复制kubectl version
2.2 获取集群账号密码以及证书信息
在集群信息页,单击【显示凭证】,查看用户名、密码和证书信息,复制或下载证书文件到本地,并开启外网访问地址获。
2.3 通过证书信息使用 kubectl 操作集群
2.3.1 修改 kubectl 配置文件,长期有效
该方法适用于长期通过 kubectl 操作集群, 一次配置,只要文件不修改就长期有效。
设置 kubectl 配置,修改以下命令中的密码、证书信息。
代码语言:txt复制kubectl config set-credentials default-admin --username=admin --password=6666o9oIB2gHD88882quIfLMy6666
kubectl config set-cluster default-cluster --server=https://cls-66668888.ccs.tencent-cloud.com --certificate-authority=/etc/kubernetes/cluster-ca.crt
kubectl config set-context default-system --cluster=default-cluster --user=default-admin
kubectl config use-context default-system
2.3.2 配置完成,直接使用 kubectl 命令:
代码语言:txt复制kubectl get nodes
NAME STATUS AGE
10.0.0.61 Ready 10h
2.4 用kubectl create创建nginx服务示例
kubectl create命令
代码语言:txt复制kubectl create -f nginx-test.yaml # nginx-test.yaml文件见下
nginx-test.yaml 文件如下:
代码语言:txt复制apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-test
labels:
qcloud-app: nginx-test
spec:
replicas: 1
revisionHistoryLimit: 5
selector:
matchLabels:
qcloud-app: nginx-test
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
qcloud-app: nginx-test
spec:
containers:
- image: nginx:latest
imagePullPolicy: Always
name: nginx-test
resources:
limits:
cpu: 200m
memory: 128Mi
requests:
cpu: 200m
memory: 128Mi
securityContext:
privileged: false
serviceAccountName: ""
volumes: null
imagePullSecrets:
- name: qcloudregistrykey
status: {}
---
apiVersion: v1
kind: Service
metadata:
name: nginx-test
labels:
qcloud-app: nginx-test
spec:
ports:
- name: tcp-80-80-ogxxh
nodePort: 0
port: 80
protocol: TCP
targetPort: 80
selector:
qcloud-app: nginx-test
type: LoadBalancer
status:
loadBalancer: {}
通过以下命令获取外网访问地址:
代码语言:txt复制kubectl get services
kubectl logs在容器中打印容器的日志
代码语言:txt复制kubectl get pod
kubectl logs <pod-name>
三、Locust简介
1.基本介绍
Locust是使用Python语言编写实现的开源性能测试工具,简洁、轻量、高效,并发机制基于gevent协程,可以实现单机模拟生成较高的并发压力。
官网:https://locust.io/
主要特点如下:
1) 使用普通的Python脚本用户测试场景
2) 分布式和可扩展,支持成千上万的用户
3) 基于Web的用户界面,用户可以实时监控脚本运行状态
4) 几乎可以测试任何系统,除了web http接口外,还可自定义clients测试其他类型系统
在模拟有效并发方面,相对于Apache JMeter,Locust的优势在于其摒弃了进程和线程,完全基于事件驱动,使用gevent提供的非阻塞IO和coroutine来实现网络层的并发请求,因此即使是单台压力机也能产生数千并发请求数;再加上对分布式运行的支持,理论上来说,Locust能在使用较少压力机的前提下支持极高并发数的测试。
2.安装
Locust可以通过pip或者easy_install安装:
代码语言:txt复制pip install locustio
或者
代码语言:txt复制easy_install locustio
安装完Locust后,shell命令locust就可以使用了,可以查看locust命令有哪些选项:
代码语言:txt复制locust --help
如果打算以分布式模式运行Locust,建议同时安装pyzmq(一种通信队列):
代码语言:txt复制pip install pyzmq
或者
代码语言:txt复制easy_install pyzmq
注意:增加打开文件限制的最大数量:
在每一个HTTP连接的机器上打开一个新文件(技术文件描述符)。操作系统可以设置一个可以打开的文件的最大数量的下限。如果限制小于模拟用户的数量,在测试时,会发生故障。增加操作系统的默认最大数量的文件限制到一个数字高于模拟用户数的数量,才能达到你想要的测试,在centos中在命令行中执行:
代码语言:txt复制ulimit 655336
更改文件描述符最大就行不会报open too many file 的错误。
3.编写Locust file
下面是一个简单的列子
代码语言:txt复制vim locustfile.py
代码语言:txt复制 1. from locust import HttpLocust, TaskSet, task
2.
3. class WebsiteTasks(TaskSet):
4. def on_start(self):
5. self.client.post("/login", {
6. "username": "test",
7. "password": "123456"
8. })
9.
10. @task(2)
11. def index(self):
12. self.client.get("/")
13.
14. @task(1)
15. def about(self):
16. self.client.get("/about/")
17.
18. class WebsiteUser(HttpLocust):
19. task_set = WebsiteTasks
21. min_wait = 1000
22. max_wait = 5000
主要包含两个类,一个是WebsiteUser(继承自HttpLocust),另一个是WebsiteTasks(继承自TaskSet),HttpLocust类就好比是一群蝗虫,而每一只蝗虫就是一个类的实例,TaskSet类就好比是蝗虫的大脑,控制着蝗虫的具体行为,即实际业务场景测试对应的任务集。
在这个示例中,先模拟用户登录系统,然后随机地访问首页(/)和关于页面(/about/),请求比例为2:1;并且,在测试过程中,两次请求的间隔时间为1~5秒间的随机值。
4.运行Locust
4.1单实例运行locust
默认端口是8089,--host代表是要压测的网站域名
代码语言:txt复制locust -f ../locust_files/上面的文件名.py --host=http://example.com -P port
4.2配置压测集群(可选)
启动压测主程序,跟上面一样,后面加上参数 --master
主节点,负责分发任务
代码语言:txt复制locust -f ../locust_files/上面的文件名.py --master --host=http://example.com
从节点,负责执行代码脚本
代码语言:txt复制locust -f ../locust_files/上面的文件名.py --slave --master-host=master_IP --host=http://example.com
打开Locust web 界面 http://127.0.0.1:8089 ,
由于example是在本地的,所以ip也是本地的。
四、基于腾讯云打包locust镜像并创建service
1.制作locust docker镜像
1.1 准备locustfile.py文件
在实际的测试中,我们需要根据自己的需要修改locustfile.py文件的内容,此文件用于定义locust测试任务
代码语言:txt复制from locust import HttpLocust, TaskSet, task
class UserBehavior(TaskSet):
def on_start(self):
""" on_start is called when a Locust start before any task is scheduled """
self.login()
def on_stop(self):
""" on_stop is called when the TaskSet is stopping """
self.logout()
def login(self):
self.client.post("/login", {"username":"ellen_key", "password":"education"})
def logout(self):
self.client.post("/logout", {"username":"ellen_key", "password":"education"})
@task(2)
def index(self):
self.client.get("/")
@task(1)
def profile(self):
self.client.get("/profile")
class WebsiteUser(HttpLocust):
task_set = UserBehavior
min_wait = 5000
max_wait = 9000
~
1.2 编写dockerfile文件
dockerfile文件用于生成docker镜像,生成完docker镜像之后需要推送到腾讯云镜像仓库里面,用于创建服务,一般情况下镜像文件生成完之后不需要更改。
代码语言:txt复制FROM hakobera/locust #指定基础镜像
ADD ./locustfile.py / #拷贝locustfile.py文件到容器中
RUN chmod 755 /locustfile.py #执行赋予权限
ENV SCENARIO_FILE /locustfile.py #设置环境变量
ADD run.sh /usr/local/bin/run.sh #拷贝run.sh文件到容器中
RUN chmod 755 /usr/local/bin/run.sh #执行赋予权限
CMD ["/usr/local/bin/run.sh"] #指定Container启动时执行的命令
1.3 编写run.sh脚本
在dockerfile的CMD里面定义了此脚本,所以在容器启动的时候回执行该脚本,该脚本作用是执行自定义参数,比如这里面定义了需要压测的域名是http://example.com,另外也可以用--master、--slave、--master-host等参数来运行分布式压测集群。在实际测试环境中,我们需要更改此文件。
代码语言:txt复制#!/bin/bash
/usr/local/bin/locust -f /locustfile.py --host=http://example.com #脚本定义locust执行的参数
1.4 制作locust docker镜像
(1)创建完 locustfile.py、dockerfile和run.sh三个文件,并放到同一个文件目录下,如图所示:
(2)运行docker build命令构建镜像
代码语言:txt复制docker build -t locust-test . #-t 指定镜像名称
构建成功!
代码语言:txt复制Sending build context to Docker daemon 4.608kB
Step 1/8 : FROM hakobera/locust
---> 586732d7713b
Step 2/8 : ADD ./locustfile.py /
---> Using cache
---> af65dae49401
Step 3/8 : RUN chmod 755 /locustfile.py
---> Using cache
---> 87b8901e6862
Step 4/8 : ENV SCENARIO_FILE /locustfile.py
---> Using cache
---> 9efb8f91ae0f
Step 5/8 : ADD run.sh /usr/local/bin/run.sh
---> 249296be2af9
Step 6/8 : RUN chmod 755 /usr/local/bin/run.sh
---> Running in b2a913ef399e
Removing intermediate container b2a913ef399e
---> 7136b1b60698
Step 7/8 : EXPOSE 8089
---> Running in 2756f5b1d5ff
Removing intermediate container 2756f5b1d5ff
---> 4a422b8d86f9
Step 8/8 : CMD ["/usr/local/bin/run.sh"]
---> Running in c0efe59c1cc6
Removing intermediate container c0efe59c1cc6
---> 36c5a17e1f50
Successfully built 36c5a17e1f50
Successfully tagged locust-test:latest
(3)运行docker images查看构建完成的镜像
代码语言:txt复制root@VM-2-244-ubuntu:/vicwan1# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
locust-test latest 36c5a17e1f50 4 seconds ago 417MB
(4)将镜像推送到腾讯云上公共镜像仓库
代码语言:txt复制sudo docker login --username=23966523 ccr.ccs.tencentyun.com #登录到腾讯云docker registry
sudo docker tag 36c5a17e1f50 ccr.ccs.tencentyun.com/vicwan/vicwan-public:latest #给镜像打name[:tag]
sudo docker push ccr.ccs.tencentyun.com/vicwan/vicwan-public:latest #将镜像推送到腾讯云docker registry
(5)登录到腾讯云查看镜像仓库里面已经有相应的镜像
2.在腾讯云控制台上基于docker镜像创建服务
(1)选择相应的集群
(2)选择locust镜像
(3)service配置
3.验证测试
(1)在腾讯云控制台查看docker服务启动正常
(2)如前面介绍,run.sh脚本中定义的压测地址是http://example.com,这里做下简单的压测
五、基于.yaml文件使用K8s快速搭建Locust压测集群
1 yaml文件
1.1 简介
YAML的意思是:"Yet Another Markup Language"(仍是一种置标语言)的缩写,它实质上是一种通用的数据串行化格式。专门用来写配置文件的语言,非常简洁和强大,比 JSON 格式方便。
它的基本语法规则如下:</br>
(1)大小写敏感</br>
(2)使用缩进表示层级关系</br>
(3)缩进时不允许使用Tab键,只允许使用空格</br>
(4)缩进的空格数目不重要,只要相同层级的元素左侧对齐即可</br>
1.2 Kubectl命令行操作yaml文件
代码语言:txt复制kubectl create -f xxx.yaml #创建服务
kubectl get pods #查看所有Pod列表
kubectl exec <pod-name> -c <container-name> data #指定Pod中某个容器执行data命令
kubectl delete -f xxx.yaml #删除服务
kubectl参考文档
https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#create
2 通过yaml文件创建locust容器服务
2.1 locust通用yaml文件样例
在实际使用中时需要根据实际情况修改一些参数,比如所有的qcloud-app,cpu、内存大小等。
代码语言:txt复制
另外:locustfile.py是关于压测模型的配置(比如压测哪个应用,怎么压测等),run.sh是关于压测部署启动的配置(比如是单实例压测,还是配置压测集群),这两个文件都被打包在image里面,所以需要根据需求改完两个文件之后,重新build一个新的镜像,上传到腾讯云镜像仓库,把下面yaml文件的image路径修改成正确的路径,即可通过yaml文件快速创建locust服务
apiVersion: extensions/v1beta1 #是当前配置格式的版本
kind: Deployment #是要创建的资源类型,这里是 Deployment
metadata: #是该资源的元数据,name是必需的元数据项
creationTimestamp: null
labels:
qcloud-app: locus-test
name: locus-test
namespace: default
spec: #是该 Deployment 的规格说明
replicas: 1 #指明副本数量,默认为 1
revisionHistoryLimit: 5
selector:
matchLabels:
qcloud-app: locus-test
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
template: #定义Pod的模板,这是配置文件的重要部分
metadata: #定义Pod 的元数据,至少要定义一个 label
creationTimestamp: null
labels:
qcloud-app: locus-test
spec: #描述Pod的规格,此部分定义Pod 中每一个容器的属性,name和image是必需的
containers:
- env:
- name: PATH
value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- name: SCENARIO_FILE
value: /locustfile.py
image: ccr.ccs.tencentyun.com/vicwan/vicwan-public:latest
imagePullPolicy: Always
name: locus-test
resources:
limits:
cpu: 500m
memory: 1Gi
requests:
cpu: 250m
memory: 256Mi
securityContext:
privileged: false
terminationMessagePath: /dev/termination-log
dnsPolicy: ClusterFirst
imagePullSecrets:
- name: qcloudregistrykey
- name: tencenthubkey
restartPolicy: Always
securityContext: {}
serviceAccountName: ""
terminationGracePeriodSeconds: 30
volumes: null
status: {}
---
apiVersion: v1
kind: Service
metadata:
annotations:
service.kubernetes.io/qcloud-loadbalancer-clusterid: cls-0wfjr0dx
service.kubernetes.io/qcloud-loadbalancer-internet-charge-type: TRAFFIC_POSTPAID_BY_HOUR
service.kubernetes.io/qcloud-loadbalancer-internet-max-bandwidth-out: "1"
creationTimestamp: null
labels:
qcloud-app: locus-test
name: locus-test
namespace: default
spec:
ports:
- name: tcp-8089-8089
nodePort: 0
port: 8089
protocol: TCP
targetPort: 8089
selector:
qcloud-app: locus-test
sessionAffinity: None
type: LoadBalancer
status:
loadBalancer: {}
2.2 演示通过yaml文件创建locust容器服务
通过yaml文件成功创建locust服务
在腾讯云控制台也已经看到相应的服务