skip to Main Content

Kubernetes와 JMeter를 사용한 부하테스트

최근 Docker 기반으로 애플리케이션을 개발했다면 애플리케이션 부하테스트 또한 Docker를 사용하여 쉽게 진행할 수 있습니다. Apache JMeter는 로드 테스트와 성능 측정을 위해 설계된 오픈 소스 소프트웨어 Java 애플리케이션입니다. 일반적으로 JMeter 서버 1대를 통해 부하테스트를 진행할 수 있지만 보다 효과적인 테스트를 위해 master/slave 구성하고 JMeter slave 여러대를 통해 많은 부하를 보낼 수 있습니다.

JMeter master/slave를 구성하기 위해서는 많은 시간이 필요하지만 Docker로 구성하면 보다 빠르게 구성 가능하며 부하서버 확장이 필요한 경우 빠르게 생성할 수 있습니다.

구성

구성은 다음과 같습니다. JMeter-master 1대, JMeter-slave 2대로 구성하고 테스트 결과를 확인하기 위해 DB에 내용을 저장하고 Grafana를 통해 웹브라우저에서 내용을 확인합니다.

JMeter-master : jmeter-slave에 부하명령을 보내며 결과를 취합하는 서버입니다.

JMeter-slave : master로부터 명령어를 받아 애플리케이션에 부하를 보내는 서버입니다.

grafana : influxdb에서 저장된 내용을 웹브라우저를 통해 그래프로 보여주는 서버입니다.

influxdb : 부하 결과내용을 저장하는 서버입니다.

예제

예제를 진행하기 위해서는 Kubernetes 1.8 이상 버젼이 설치되어있어야합니다.

진행에 필요한 실행 스크립트는 https://github.com/kubernauts/jmeter-kubernetes 를 참조하시기 바랍니다.

테스트 웹애플리케이션 생성

테스트 웹애플리케이션을 생성합니다. 아코디언 [앱] 에서 tomcat-8-0-jre8 을 선택하고 소스타입은 Git 을 사용합니다. 테스트 애플리케이션은 https://github.com/mantech-accordion/jpetstore-6 을 사용합니다.

jmeter_slaves_deploy.yaml 수정

hostAliases ip에 <NodeIP>를 수정합니다.

kind: Deployment
metadata:
  name: jmeter-slaves
  labels:
    jmeter_mode: slave
spec:
  replicas: 2 
...
    spec:
      hostAliases:
      - ip: "<NodeIP>"
        hostnames:
        - "jpetstore.example.com"
      containers:
      - name: jmslave

jmeter_master_deploy.yaml 수정

hostAliases ip에 <NodeIP>를 수정합니다.

kind: Deployment
metadata:
  name: jmeter-master
  labels:
    jmeter_mode: master
spec:
  replicas: 1
...
    spec:
      hostAliases:
      - ip: "<NodeIP>"
        hostnames:
        - "jpetstore.example.com"
      containers:
      - name: jmmaster

1. git 저장소에서 jmeter-kubernetes을 가져옵니다.

# git 저장소에서 가져옵니다.
git clone https://github.com/kubernauts/jmeter-kubernetes
​
Cloning into 'jmeter-kubernetes'...
remote: Counting objects: 18, done.
remote: Compressing objects: 100% (16/16), done.
remote: Total 18 (delta 0), reused 18 (delta 0), pack-reused 0
Unpacking objects: 100% (18/18), done.
Checking connectivity... done.
​
cd jmeter-kubernetes/

2. jmeter_cluster_create.sh를 실행하여 구성을 시작합니다.

# 실행 권한을 부여합니다.
$ chmod +x jmeter_cluster_create.sh dashboard.sh start_test.sh

# jmeter_cluster_create.sh를 실행합니다.
$ ./jmeter_cluster_create.sh 
checking if kubectl is present
Client Version: v1.9.0+coreos.0
Server Version: v1.9.0+coreos.0
Current list of namespaces on the kubernetes cluster:
​
default
kube-system

​# 생성할 네임스페이스를 입력합니다.
Enter the name of the new tenant unique name, this will be used to create the namespace
kubernauts
​
Creating Namespace: kubernauts
namespace "kubernauts" created
Namspace kubernauts has been created
​
Creating Jmeter slave nodes
​
Number of worker nodes on this cluster is  2
​
deployment "jmeter-slaves" created
service "jmeter-slaves-svc" created
Creating Jmeter Master
configmap "jmeter-load-test" created
deployment "jmeter-master" created
Creating Influxdb and the service
configmap "influxdb-config" created
deployment "influxdb-jmeter" created
service "jmeter-influxdb" created
Creating Grafana Deployment
deployment "jmeter-grafana" created
service "jmeter-grafana" created
Printout Of the kubernauts Objects
​
NAME                     DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deploy/influxdb-jmeter   1         1         1            0           2s
deploy/jmeter-grafana    1         1         1            0           1s
deploy/jmeter-master     1         1         1            0           3s
deploy/jmeter-slaves     2         2         2            1           4s
​
NAME                            DESIRED   CURRENT   READY     AGE
rs/influxdb-jmeter-5cbd7b8469   1         1         0         2s
rs/jmeter-grafana-65dd5f6b79    1         1         0         1s
rs/jmeter-master-75f66dbb5f     1         1         0         3s
rs/jmeter-slaves-57cc6b9cfc     2         2         1         4s
​
NAME                     DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deploy/influxdb-jmeter   1         1         1            0           2s
deploy/jmeter-grafana    1         1         1            0           1s
deploy/jmeter-master     1         1         1            0           3s
deploy/jmeter-slaves     2         2         2            1           4s
​
NAME                            DESIRED   CURRENT   READY     AGE
rs/influxdb-jmeter-5cbd7b8469   1         1         0         2s
rs/jmeter-grafana-65dd5f6b79    1         1         0         1s
rs/jmeter-master-75f66dbb5f     1         1         0         3s
rs/jmeter-slaves-57cc6b9cfc     2         2         1         4s
​
NAME                                  READY     STATUS              RESTARTS   AGE
po/influxdb-jmeter-5cbd7b8469-mbvtg   0/1       ContainerCreating   0          2s
po/jmeter-grafana-65dd5f6b79-lzjqm    0/1       ContainerCreating   0          1s
po/jmeter-master-75f66dbb5f-264bs     0/1       ContainerCreating   0          3s
po/jmeter-slaves-57cc6b9cfc-b877l     0/1       ContainerCreating   0          4s
po/jmeter-slaves-57cc6b9cfc-plssn     1/1       Running             0          4s
​
NAME                    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
svc/jmeter-grafana      NodePort    10.233.27.49   <none>        3000:31100/TCP               0s
svc/jmeter-influxdb     ClusterIP   10.233.17.59   <none>        8083/TCP,8086/TCP,2003/TCP   1s
svc/jmeter-slaves-svc   ClusterIP   None           <none>        1099/TCP,50000/TCP           3s

3. 구성에 필요한 Pod가 정상적으로 배포되어있는지 상태를 확인합니다.

$ kubectl get -n kubernauts po
NAME                               READY     STATUS    RESTARTS   AGE
influxdb-jmeter-5cbd7b8469-mbvtg   1/1       Running   0          4m
jmeter-grafana-65dd5f6b79-lzjqm    1/1       Running   0          4m
jmeter-master-75f66dbb5f-264bs     1/1       Running   0          4m
jmeter-slaves-57cc6b9cfc-b877l     1/1       Running   0          4m
jmeter-slaves-57cc6b9cfc-plssn     1/1       Running   0          4m

4. Influxdb 를 생성을 위해 dashboard.sh를 실행합니다.

$ ./dashboard.sh 
Creating Influxdb jmeter Database
Creating the Influxdb data source
{"datasource":{"id":1,"orgId":1,"name":"jmeterdb","type":"influxdb","typeLogoUrl":"","access":"proxy","url":"http://jmeter-influxdb:8086","password":"admin","user":"admin","database":"jmeter","basicAuth":false,"basicAuthUser":"","basicAuthPassword":"","withCredentials":false,"isDefault":true,"secureJsonFields":{},"version":1,"readOnly":false},"id":1,"message":"Datasource added","name":"jmeterdb"}

5. Grafana에 접속

http://NodeIP:31100

6. Grafana에 접속하여 Dashboard Template(GrafanaJMeterTemplate.json)를 Import합니다.

7. 마지막으로 start_test.sh를 실행하여 jmx 스크립트를 실행시킵니다.

$ ./start_test.sh 
# 실행할 jmx 스크립트를 입력한다.
Enter path to the jmx file cloudssky.jmx
Creating summariser <summary>
Created the tree successfully using cloudssky.jmx
Configuring remote engine: 10.233.66.65
Configuring remote engine: 10.233.87.12
Starting remote engines
Starting the test @ Mon Feb 12 10:00:14 UTC 2018 (1518429614812)
Remote engines have been started
Waiting for possible Shutdown/StopTestNow/Heapdump message on port 4445
summary +     15 in 00:02:13 =    0.1/s Avg:  2760 Min:  1315 Max:  6677 Err:     0 (0.00%) Active: 4 Started: 4 Finished: 0
summary +     16 in 00:01:03 =    0.3/s Avg:  1506 Min:  1283 Max:  2232 Err:     0 (0.00%) Active: 4 Started: 4 Finished: 0

8. Grafana에 접속하여 부하테스트 결과를 실시간으로 확인 할 수 있습니다.

많은 분들이 개발/운영 중인 애플리케이션의 부하테스트를 진행하려고 시도하지만 사전 플랫폼 작업에 오랜 시간과 자원이 필요하기 때문에 주저하게 됩니다. Kubernetes & Docker를 사용하면 부하테스트 환경을 보다 빠르게 구축할 수 있으며 더 많은 부하가 필요한 경우, 빠르게 확장할 수 있는 구조를 가지고 있습니다. 추가적으로 JMeter gc plugin을 사용하기 위해서는kubernautslabs/jmeter_maste:latest 를 참고하여 plugin을 추가한 Docker를 만들어서 사용합니다.

Back To Top