[Sprint] aws EC2와 k6를 이용한 성능 테스트

# 학습 목표

  • k6 도구 활용법을 학습합니다.
  • 성능 테스트 유형별 스크립트를 작성할 수 있습니다.
  • aws ec2 인스턴스를 모니터링할 수 있습니다.
  • aws에서 제공하는 버스트 크레딧을 이해할 수 있습니다.

# 해결 과제

1. aws ec2 인스턴스 생성

  • 각자의 aws 계정에서 EC2 인스턴스를 생성합니다.
  • 버스트 기능이 있는 t2micro를 생성하세요
  • ubuntu 20.04
  1. ssh 접속 생성한 ec2에 접속을 합니다.
  2. install docker on EC2
#업데이트 및 HTTP 패키지 설치
sudo apt update
sudo apt-get install -y ca-certificates   #공인 인증서를 관리하기 위한 패키지
    curl 
    software-properties-common  #소프트웨어 저장소 관리 도구
    apt-transport-https  #HTTPS 프로토콜을 통해 APT 패키지 관리자를 사용할 수 있게 해주는 패키지
    gnupg  #암호화 및 디지털 서명 도구인 GNU Privacy Guard를 설치
    lsb-release #현재 운영 체제의 릴리스 정보를 확인하는 데 사용되는 패키지
# GPG 키 및 저장소 추가
sudo mkdir -p /etc/apt/keyrings
#Docker의 GPG 키를 다운로드하고 파일로 저장합니다. GPG 키는 패키지 관리자가 Docker 저장소에서 제공하는 패키지의 무결성을 확인하는 데 사용
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
#Docker 저장소를 시스템의 패키지 소스 목록에 추가
echo 
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu 
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 도커엔진 설치
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io
  1. run container
  • 성능 테스트를 위한 타깃 서버를 컨테이너로 배포합니다.
sudo docker run --name <이름> -d -p 8080:8080 sebcontents/cozserver:1.0
  • 서버 배포 확인
curl http://localhost:8080

2. install k6

  • 공식 홈페이지를 이용하여 k6를 설치합니다. (트러블 슈팅 주의)
  • 클라우드 상에 빠른 설치를 위해서 snapd도 추천합니다. https://snapcraft.io/install/k6/ubuntu
sudo apt update
sudo apt install snapd
sudo snap install k6
  1. 리포지토리에 유형별 테스트 스크립트가 작성되어 있습니다. 앞에서 설명한 내용과 비교하면서 코드의 구조를 잘 살펴보시기 바랍니다.
  2. run the tests 각각의 스크립트를 실행해 보고 ec2 인스턴스의 CPU 사용률 대시보드를 확인해 보세요. 학습했던 내용의 그래프와 유사하게 관찰되는 지 확인하세요.
k6 run basic_test.js
k6 run load_test.js
k6 run stress_test.js
k6 run spike_test.js
k6 run soak_test.js
  1. inspect aws burst credit 대시 보드의 CPU 크레딧 사용량(개수) 와 CPU 크레딧 밸런스(개수)를 관찰합니다.

# 실습 자료

sprint_k6_test


# 과제 항목별 진행 상황

인스턴스 시작

CPU 사용률이 5%이하로 credit 사용이 거의 없음

basic test

import http from 'k6/http'; // 부하 테스트 유형 http request
import { sleep } from 'k6'; // sleep 함수 가져오기
export let options = {
    insecureSkipTLSVerify: true, // HTTPS 연결에서 TLS 인증서를 확인하지 않도록 하는 기능
    noConnectionReuse: false, // 재사용 연결 사용
    vus: 10, // 가상사용자 수
    duration: '30s' // 실행시간
};

export default () => {
    http.get('http://localhost:8080') // get 요청
    sleep(1); // 1초 동안 대기 (실제 사용자 처럼 요청하기 위함)
};
ubuntu@ip-172-31-4-230:~/k6_test$ k6 run basic_test.js

          /      |‾‾| /‾‾/   /‾‾/
     /  /       |  |/  /   /  /
    /  /        |     (   /   ‾‾
   /             |  |   |  (‾)  |
  / __________   |__| __ _____/ .io

  execution: local
     script: basic_test.js
     output: -

  scenarios: (100.00%) 1 scenario, 10 max VUs, 1m0s max duration (incl. graceful stop):
           * default: 10 looping VUs for 30s (gracefulStop: 30s)


     data_received..................: 134 kB 4.4 kB/s
     data_sent......................: 24 kB  796 B/s
     http_req_blocked...............: avg=1.55ms   min=3.65µs   med=5.11µs  max=47.65ms  p(90)=9.3µs    p(95)=15.02µs
     http_req_connecting............: avg=177.11µs min=0s       med=0s      max=6.54ms   p(90)=0s       p(95)=0s
     http_req_duration..............: avg=2.19ms   min=703.53µs med=1.28ms  max=38.84ms  p(90)=2.73ms   p(95)=4.25ms
       { expected_response:true }...: avg=2.19ms   min=703.53µs med=1.28ms  max=38.84ms  p(90)=2.73ms   p(95)=4.25ms
     http_req_failed................: 0.00%  ✓ 0        ✗ 300
     http_req_receiving.............: avg=64.28µs  min=20.88µs  med=38.12µs max=365.33µs p(90)=149.41µs p(95)=161.75µs
     http_req_sending...............: avg=32.65µs  min=9.44µs   med=12.97µs max=1.16ms   p(90)=28.58µs  p(95)=81.05µs
     http_req_tls_handshaking.......: avg=0s       min=0s       med=0s      max=0s       p(90)=0s       p(95)=0s
     http_req_waiting...............: avg=2.1ms    min=642.17µs med=1.17ms  max=38.46ms  p(90)=2.66ms   p(95)=4.08ms
     http_reqs......................: 300    9.953435/s
     iteration_duration.............: avg=1s       min=1s       med=1s      max=1.08s    p(90)=1s       p(95)=1s
     iterations.....................: 300    9.953435/s
     vus............................: 10     min=10     max=10
     vus_max........................: 10     min=10     max=10


running (0m30.1s), 00/10 VUs, 300 complete and 0 interrupted iterations
default ✓ [======================================] 10 VUs  30s

load_test.js

평균 부하 테스트는 프로덕션 환경의 평균 동작을 반영하는 초당 동시 사용자 및 요청 수를 시뮬레이션합니다.

import http from "k6/http"; // 부하 테스트 유형 http request
import { sleep } from 'k6'; // sleep 함수 가져오기
export let options = {
    insecureSkipTLSVerify: true, // HTTPS 연결에서 TLS 인증서를 확인하지 않도록 하는 기능
    noConnectionReuse: false, // 재사용 연결 사용
    stages: [  // 단계별 시나리오를 설정
        { duration: '5m', target: 100 }, // 5분 동안 100개의 가상 사용자를 유지
        { duration: '10m', target: 100 }, // 10분 동안 100개의 가상 사용자 유지
        { duration: '5m', target: 0 },   // 5분 동안 가상 사용자를 0으로 줄임
    ],
    thresholds: {   // 부하 테스트 결과를 평가하는 임계값을 설정
        http_req_duration: ['p(99)<150'], // 지표의 99%가 150ms 이하를 유지
    }
};
export default () => {
    let respose = http.get('http://localhost:8080');
    sleep(1);
};
ubuntu@ip-172-31-4-230:~/k6_test$ k6 run load_test.js

          /      |‾‾| /‾‾/   /‾‾/
     /  /       |  |/  /   /  /
    /  /        |     (   /   ‾‾
   /             |  |   |  (‾)  |
  / __________   |__| __ _____/ .io

  execution: local
     script: load_test.js
     output: -

  scenarios: (100.00%) 1 scenario, 100 max VUs, 20m30s max duration (incl. graceful stop):
           * default: Up to 100 looping VUs for 20m0s over 3 stages (gracefulRampDown: 30s, gracefulStop: 30s)


     data_received..................: 40 MB  33 kB/s
     data_sent......................: 7.2 MB 6.0 kB/s
     http_req_blocked...............: avg=7.02µs   min=3.39µs   med=5.28µs   max=4.27ms  p(90)=7.49µs   p(95)=10.07µs
     http_req_connecting............: avg=239ns    min=0s       med=0s       max=4.06ms  p(90)=0s       p(95)=0s
   ✓ http_req_duration..............: avg=1.47ms   min=511.37µs med=1.17ms   max=22.66ms p(90)=2.25ms   p(95)=2.79ms
       { expected_response:true }...: avg=1.47ms   min=511.37µs med=1.17ms   max=22.66ms p(90)=2.25ms   p(95)=2.79ms
     http_req_failed................: 0.00%  ✓ 0         ✗ 90017
     http_req_receiving.............: avg=106.64µs min=18.66µs  med=72.59µs  max=20.13ms p(90)=195.81µs p(95)=213.94µs
     http_req_sending...............: avg=28.43µs  min=8.68µs   med=13.86µs  max=15.95ms p(90)=39.54µs  p(95)=72.99µs
     http_req_tls_handshaking.......: avg=0s       min=0s       med=0s       max=0s      p(90)=0s       p(95)=0s
     http_req_waiting...............: avg=1.33ms   min=425.17µs med=993.04µs max=22.6ms  p(90)=2.13ms   p(95)=2.64ms
     http_reqs......................: 90017  74.952428/s
     iteration_duration.............: avg=1s       min=1s       med=1s       max=1.3s    p(90)=1s       p(95)=1s
     iterations.....................: 90017  74.952428/s
     vus............................: 1      min=1       max=100
     vus_max........................: 100    min=100     max=100


running (20m01.0s), 000/100 VUs, 90017 complete and 0 interrupted iterations
default ✓ [======================================] 000/100 VUs  20m0s

soak_test.js

  • 장기간에 걸친 시스템의 성능 저하 및 리소스 소비.
  • 확장된 기간 동안 시스템의 가용성 및 안정성.
import http from "k6/http"; // 부하 테스트 유형 http request
import { sleep, check } from 'k6'; // sleep 함수 가져오기
export let options = {
    insecureSkipTLSVerify: true, // HTTPS 연결에서 TLS 인증서를 확인하지 않도록 하는 기능
    noConnectionReuse: false, // 재사용 연결 사용
    stages: [  // 단계별 시나리오를 설정
        { duration: '2m', target: 400 }, // 2분동안 400개의 가상 사용자를 유지
        { duration: '3h56m', target: 400 }, // 3시간 56분동안 400개의 가상 사용자를 유지
        { duration: '2m', target: 0 },     // 2분동안 가상 사용자를 0으로 줄임
    ],  
};
export default function () {
    const res = http.get('http://localhost:8080');
//check 함수를 사용하여 응답을 검사합니다. 
//이 경우, 응답의 상태 코드가 200인지 확인합니다. 
//검사 결과가 false인 경우 오류가 발생
    check(res, { 'status was 200': (r) => r.status == 200 });
    sleep(1);
  };

stress_test.js

스트레스 테스트는 사용량이 많은 조건에서 시스템의 안정성과 신뢰성을 확인합니다. 시스템은 처리 기한, 월급날, 출퇴근 시간, 근무 종료 및 고부하 이벤트를 생성하기 위해 결합될 수 있는 기타 많은 격리된 동작과 같은 비정상적인 순간에 평소보다 높은 작업 부하를 받을 수 있습니다.

spike_test.js

시스템이 갑작스럽고 대량의 사용 급증에서 살아남고 성능을 발휘하는지 확인


# TROUBLE SHOOTING LOG

💡 문제 내용

원인

해결 방안

#References

내용

Leave a Comment