[Blog Operator] 블로그에 부하를 걸어보자

[Blog Operator] 블로그에 부하를 걸어보자

Intro

현재 Ghost를 Kubernetes에 설치하여 사용하여 Blog를 운영 중이며, Scaling 정책이나 부하가 걸렸을 때에 대해 대비가 되어있지 않은거 같아서 작성하게되었다.

Load Test 툴 준비하기

Load Test를 제공하는 툴의 경우 아주 많지만 대표적으로 Locust, Apache jmeter, k6, Artillery가 있다.

  1. Locust: Python 기반의 부하 툴로, 유연성과 가독성이 뛰어난다. 하지만 부하 결과를 자세하게 제공하지 않는다.
  2. Apache Jmeter: GUI를 제공해서 손쉽게 작성이 가능하다. 하지만 생각보다 높은 메모리 사용량과 코드 기반 시나리오 작성이 상대적으로 복잡하다.
  3. K6: JavaScript를 사용해서 사용하기 쉽고, CLI를 중심으로 설계되었다보니 여러 파이프라인에서도 테스트가 가능하며, 테스트 결과를 InfluxDB와 같은 저장소에 저장하여 Grafana를 통해 모니터링도 자세하게 가능하다.
  4. Artillery: Yaml과 JavaScript로 작성이 가능하고 Cloud로 부하테스트를 할 수 있도록 서비스를 제공하며, 주로 AWS Lambda, Fargate를 활용한 부하 테스트에 적합하다. 하지만 테스트에 대해 잦은 오류가 발생한다.

Load Test 준비하기 - InfluxDB 설치

우선 Docker를 사용하여 간단하게 influxDB를 설치해주자.

influxDB를 설치하는 이유는 k6로 부하는 넣고 이에 대한 데이터를 보관 및 저장하기 위해 설치하엿다.

$ docker run -d --name=influxdb \
  --name k6-influxdb \
  --env INFLUXDB_DB=k6db \
  -p 8086:8086 influxdb:1.8

Load Test 준비하기 - k6 설치 및 코드 작성

설치는 아주 간단하다

sudo dnf install https://dl.k6.io/rpm/repo.rpm
sudo dnf install k6

k6 부하테스트 코드를 아래와 같이 작성해주자.

[scripts.js]

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

export let options = {
  stages: [
    { duration: '5m', target: 100 },
    { duration: '5m', target: 1000 },
  ],
  thresholds: {
    'http_req_duration': ['p(95)<500'],
  },
};

export default function () {
  const res = http.get('https://blog.dispiny.life');

  check(res, {
    'is status 200': (r) => r.status === 200,
  });

  sleep(1);
}

stages는 부하 테스트의 시나리오는 설정하는 곳이다.

  • 첫 번째 단계: 5분 동안 100명의 가상 유저를 대상으로 테스트를 진행한다.
  • 두 번째 단계: 5분 동안 1000명의 유저로 부하를 증가시킨다.

thresholdsd의 경우 성능 기준을 설정하는 부분이다. 여기서 http_req_duration(HTTP 요청에 걸린 시간)이 95%는 500ms 이하여야한다는 조건을 설정하였다.

defaultk6의 테스트 함수이다. 각 가상 유저가 이 함수 내의 코드를 반복적으로 실행한다.

  • http.get('domain'): 지정된 URL에 GET 요청을 보낸다.
  • check: 요청이 성공적으로 완료되었는지 확인하는 함수이다. 이때 응답 코드가 200인지 확인하고, 그 결과를 check 함수로 검증한다.

Load Test 모니터링 구축

우선 기존 인프라를 모니터링하기 위해 설치한 Grafana와 k6 메트릭 값이 저장되는 influxDB를 Data Source를 등록하여 Dashboard 형태로 조회할 수 있도록 구축해보자.

그 후 k6 dashboard을 생성해주자.

k6 Load Testing Results | Grafana Labs

해당 Grafana Dashboard를 사용할 예정이다.

방금 만든 influxdb datasource를 지정 후 import를 클릭해준다.

Load Test 진행하기

$ k6 run \
  --out influxdb=http://localhost:8086/k6db \
  scripts.js

위와 같이 부하 결과를 실시간으로 확인 할 수 있다.

부하가 끝날 때 동안 여러가지 지표를 확인하면서 모니터링을 하자

Load Test 결과 & 개선하기

VU가 50명일때부터 req_duration 이 기존 0.1~0.2초에서 0.2 ~ 0.5초 사이로에 늘어나더니 280명 대 부턴 응답시간이 2초 ~ 4초 사이로 늘어났다.

그리고 ghost를 운영하는 Pod를 확인 해보았을 때

VUs 47명 부터 CPU가 100%을 초과하여 Pod가 Hang된 것으로 추정된다.

현재 구성은 위와 같은 구조로 동작 되고 있는데, nginx reverse proxy에 아래와 같이 Cache 구성을 하였다.

Load Test 개선 후 테스트 결과

위와 같이 에러 없이 평균 94.74ms 최소 67.95ms를 유지했으며, Pod의 경우 아래와 같이 Peak를 찍었을 때의 CPU Usage가 3.62%로 기존 100%이상일 때 보다 96%정도 줄어들었으며

Node의 CPU 사용량 또한 기존 100%에서 Peak 기준 29.8%로 많이 줄어들었다.