본문 바로가기

인프라,데이터/Docker, Kubernetes

K6로 부하테스트 하기(도커, 쿠버네티스 환경)

K6란?

Grafana에서 만든 오픈 소스 부하테스팅 툴로, 성능 테스트를 쉽게 수행할 수 있다.

부하테스트를 통해 성능 테스트를 수행함으로써 시스템의 신뢰성을 높일 수 있다.

 

K6+도커로 부하테스트

먼저 테스트용 스크립트를 만든다.

import http from 'k6/http';
import { check } from 'k6';

export const options = {
    stages: [
        { target: 200, duration: '30s' },
        { target: 0, duration: '30s' },
    ],
};

export default function () {
    const result = http.get('https://test-api.k6.io/public/crocodiles/');
    check(result, {
        'http response status code is 200': result.status === 200,
    });
}

K6 공홈 예제 스크립트를 가져왔다.

위에 기재된 URL로 30초+30초간 요청을 보내 http response status code를 체크하는 스크립트다.

FROM grafana/k6:0.43.1

COPY ./test.js test.js

ENTRYPOINT ["k6", "run", "test.js"]

그리고 이 스크립트를 사용하는 Dockerfile을 만든다.

docker build . -t k6 --platform linux/arm64
docker run --name k6 -itd k6

M1 맥북의 경우 플랫폼을 지정해서 도커 이미지를 만들고, 컨테이너를 생성하면 컨테이너에서 부하테스트가 돌아간다.

 

K6+쿠버네티스로 부하테스트

필요사항:

  • 쿠버네티스 클러스터
  • kubectl

먼저 클러스터에 namespace를 생성한다.

kubectl create namespace k6

 

다음으로 테스트 스크립트를 작성한다.

import http from 'k6/http';
import { check } from 'k6';

export const options = {
    stages: [
        { target: 200, duration: '30s' },
        { target: 0, duration: '30s' },
    ],
};

export default function () {
    const result = http.get('https://test-api.k6.io/public/crocodiles/');
    check(result, {
        'http response status code is 200': result.status === 200,
    });
}

위와 같은 스크립트다.

위 스크립트를 configmap 안에다가 넣는다.

k create configmap sample-test -n k6 --from-file test.js

이렇게 해도 되고, 

아래와 같이 yaml 파일을 작성해도 된다.

apiVersion: v1
kind: ConfigMap
metadata:
    name: sample-test
    namespace: k6
data:
    test.js: |-
        import http from 'k6/http';
        import { check } from 'k6';
        
        export const options = {
            stages: [
                { target: 200, duration: '30s' },
                { target: 0, duration: '30s' },
            ],
        };
        
        export default function () {
            const result = http.get('https://test-api.k6.io/public/crocodiles/');
            check(result, {
                'http response status code is 200': result.status === 200,
            });
        }

 

그리고 Kubernetes Job을 생성해 K6로 부하테스트를 수행한다.

apiVersion: batch/v1
kind: Job
metadata:
  name: k6
  namespace: k6
spec:
  parallelism: 2   			  # 몇 개의 pod를 돌리는 job을 만들 것인가? 
  template:
    spec: 			 
      containers:
        - name: k6
          image: grafana/k6:0.43.1
          command: ["k6", "run", "/etc/config/test.js"]
          volumeMounts:
            - name: config-volume
              mountPath: /etc/config
      volumes:
        - name: config-volume
          configMap:
            name: sample-test
      restartPolicy: Never
  backoffLimit: 2    			# specify the number of retries before considering a Job as failed

 

위 configmap과 job file을 kubectl apply 해주면, job의 결과 k6 pod가 생성된다.

│ NAMESPACE↑   NAME       PF  READY   RESTARTS STATUS     CPU  MEM  %CPU/R  %CPU/L  %MEM/R  %MEM/L IP            NODE                               AGE     │
│ k6           k6-4sdtr   ●   1/1            0 Running      0    0     n/a     n/a     n/a     n/a xxxx   ip-xxxx.ap-northeast-2.compute.internal   22s     │
│ k6           k6-r4pk5   ●   1/1            0 Running      0    0     n/a     n/a     n/a     n/a xxxx   ip-xxxx.ap-northeast-2.compute.internal   22s

 

이렇게 생성된 pod의 로그를 보면

│ running (0m58.0s), 015/200 VUs, 3749 complete and 0 interrupted iterations                                                                                             │
│ default   [  97% ] 015/200 VUs  0m58.0s/1m00.0s                                                                                                                        │
│                                                                                                                                                                        │
│ running (0m59.0s), 008/200 VUs, 3810 complete and 0 interrupted iterations                                                                                             │
│ default   [  98% ] 008/200 VUs  0m59.0s/1m00.0s                                                                                                                        │
│                                                                                                                                                                        │
│ running (1m00.0s), 002/200 VUs, 3837 complete and 0 interrupted iterations                                                                                             │
│ default   [ 100% ] 002/200 VUs  1m00.0s/1m00.0s                                                                                                                        │
│                                                                                                                                                                        │
│      ✓ http response status code is 200                                                                                                                                │
│                                                                                                                                                                        │
│      checks.........................: 100.00% ✓ 3839     ✗ 0                                                                                                           │
│      data_received..................: 4.3 MB  72 kB/s                                                                                                                  │
│      data_sent......................: 530 kB  8.8 kB/s                                                                                                                 │
│      http_req_blocked...............: avg=18.33ms min=834ns    med=1.48µs   max=399ms    p(90)=2.93µs  p(95)=345.88ms                                                  │
│      http_req_connecting............: avg=9.16ms  min=0s       med=0s       max=201.09ms p(90)=0s      p(95)=172.96ms                                                  │
│      http_req_duration..............: avg=1.61s   min=180.81ms med=202.9ms  max=9.24s    p(90)=5.09s   p(95)=7.1s                                                      │
│        { expected_response:true }...: avg=1.61s   min=180.81ms med=202.9ms  max=9.24s    p(90)=5.09s   p(95)=7.1s                                                      │
│      http_req_failed................: 0.00%   ✓ 0        ✗ 3839                                                                                                        │
│      http_req_receiving.............: avg=35.3µs  min=13.02µs  med=33.77µs  max=345.96µs p(90)=45.9µs  p(95)=51.54µs                                                   │
│      http_req_sending...............: avg=8.71µs  min=4.37µs   med=6.95µs   max=63.69µs  p(90)=13.46µs p(95)=19.17µs                                                   │
│      http_req_tls_handshaking.......: avg=9.14ms  min=0s       med=0s       max=180.86ms p(90)=0s      p(95)=172.76ms                                                  │
│      http_req_waiting...............: avg=1.61s   min=180.76ms med=202.86ms max=9.24s    p(90)=5.09s   p(95)=7.1s                                                      │
│      http_reqs......................: 3839    63.94181/s                                                                                                               │
│      iteration_duration.............: avg=1.63s   min=180.88ms med=204.07ms max=9.59s    p(90)=5.1s    p(95)=7.19s                                                     │
│      iterations.....................: 3839    63.94181/s                                                                                                               │
│      vus............................: 2       min=2      max=199                                                                                                       │
│      vus_max........................: 200     min=200    max=200                                                                                                       │
│                                                                                                                                                                        │
│                                                                                                                                                                        │
│ running (1m00.0s), 000/200 VUs, 3839 complete and 0 interrupted iterations                                                                                             │
│ default ✓ [ 100% ] 000/200 VUs  1m0s                                                                                                                                   │
│ Stream closed EOF for k6/k6-4sdtr (k6)

부하테스트의 상태를 볼 수 있다.

이 결과를 그래프로도 볼 수 있는데, https://k6.io/docs/results-output/real-time/datadog/ 을 참고해서 Datadog K6 대시보드를 만들 수 있다.