실습
- Demo 사이트 POD, Node 다운 시 서비스 이상 여부 검증
- K6, Vegeta Tool 이용한 부하 테스트
Why HA & 부하 테스트?
현재 저희 고객사 시스템은 서비스 오픈 전 1~2일 정도 개발자 포함 운영자 분들이 모여서 HA 및 부하 테스트를 진행 합니다. 물리 노드 네트워크 케이블도 뽑아 보고 디스크도 뽑아 보면서 운영 상황에 발생 할 수 있는 여러 장애 상황을 미리 검증을 합니다.
물론 결과는 예상과 다르게 다양한 장애 상황이 발생 합니다. 분명히 POD, Node 이중화 되도록 잘 설계하고 적용하였는데 특정 POD는 안 넘어가던지 넘어가는 시간이 예상 시간 보다 훨씬 더 소요되는지 등 다양한 상황이 발생 합니다. 노드의 Local Disk를 사용해서 수동으로 PVC를 삭제해야 다른 노드로 넘어가는 것들이 대표적 사례입니다.
부하 테스트 역시 비슷합니다. 생각하지도 못한 부문이 성능 Bottle neck이 되고는 합니다. 물론 bottle neck을 안다고 해서 바로 처리하지 못하는 경우도 많습니다. 하지만 사전에 이를 인지하는 것만 으로도 의미있는 작업입니다.
기존 VM 기반에서는 실 운영 환경과 Staging 환경이 다른 경우가 대부분 입니다. 아무리 비슷하게 꾸민다고 하여도 장비 Spec 등에서 차이가 많습니다. 그리고 대부분의 경우 비용 절감 등의 이유로 처음부터 Staging이 없거나 있어도 정말 최소한으로 구성하는 경우가 대부분입니다. (아직 Test/Staging/Production 환경 구분없고 Test 장비는 아예 없는 사이트도 있더군요.)
그리고 Staging 시스템 구성 시 운영 시스템 구성하는 것만큼 동일하게 시간이 소요 됩니다. 하지만 Kube 환경은 Code 기반으로 동일 시스템 구성 시 기존 Code를 적용(apply)만 하면 되므로 시간을 많이 절약 할 수 있습니다.
하지만 컨테이너, Kube 환경은 최소한의 시스템 구성으로도 실제 운영 환경과 유사한 것이 장점입니다. 컨테이너 특성 상 호스트 노드 환경에 독립적이기 때문입니다. 따라서 서비스 오픈 전 그리고 소스 코드, 구성 변경 후 스테이징 환경에서 충분히 HA, 부하 Test 등을 수행하여 문제가 발생하지 않는 걸 검증하면 실 운영 환경에서도 대부분 문제가 발생하지 않습니다.
물론 이러한 테스트를 최대한 자동화하여 여러 사람이 필요하지 않게 하는 것이 베스트 입니다. 예를 들어 HA Test는 Chaos Engineering을 이용 하실 수 있습니다. (개인적으로 Litmus 사용하였는데 잘 동작 하였습니다.) 특히 MSA 환경으로 POD 갯수가 수백~수천개 되면서 테스트 시나리오도 많이 복잡합니다. 장애 시나리오도 단순 POD 다운이 아니라 네트워크 throughput, connection에 따른 영향을 받는 서비스가 달라지는 등 다양한 케이스가 있습니다.
데모 사이트 HA Test
먼저, 간단한 데모 사이트를 구성합니다. 데모사이트 전체 코드는 아래 링크로 대신 합니다.
https://gist.github.com/junghoon2/e6e75be685b37de9de9ef1e26ab33d9b
적용(apply) 하시면 frontend, redis master, redis slave POD를 확인 할 수 있습니다.
[spkr@erdia22 73.DemoPJT (kspray:default)]$ k apply -f guestbook-all-in-one.yml
service/redis-master unchanged
deployment.apps/redis-master created
service/redis-slave unchanged
deployment.apps/redis-slave created
service/frontend unchanged
deployment.apps/frontend created
[spkr@erdia22 73.DemoPJT (kspray:default)]$ kgp
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
frontend-6c6d6dfd4d-4lgzv 1/1 Running 0 7s 10.233.79.25 ksp2 <none> <none>
frontend-6c6d6dfd4d-5tswn 1/1 Running 0 7s 10.233.79.26 ksp2 <none> <none>
frontend-6c6d6dfd4d-dk7lj 1/1 Running 0 7s 10.233.79.28 ksp2 <none> <none>
redis-master-f46ff57fd-f4dh6 1/1 Running 0 7s 10.233.79.24 ksp2 <none> <none>
redis-slave-7979cfdfb8-rcz6h 1/1 Running 0 7s 10.233.79.29 ksp2 <none> <none>
redis-slave-7979cfdfb8-src2f 1/1 Running 0 7s 10.233.79.27 ksp2 <none> <none>
웹 접속을 위하여 Load Balancer IP를 확인합니다.
[spkr@erdia22 73.DemoPJT (kspray:default)]$ kgs
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
frontend LoadBalancer 10.233.20.105 172.17.30.171 80:31208/TCP 140m app=guestbook,tier=frontend
kubernetes ClusterIP 10.233.0.1 <none> 443/TCP 3d2h <none>
redis-master ClusterIP 10.233.53.36 <none> 6379/TCP 140m app=redis,role=master,tier=backend
redis-slave ClusterIP 10.233.63.199 <none> 6379/TCP 140m app=redis,role=slave,tier=backend
EXTERNAL IP(172.17.30.171)로 접속하면 아래와 같은 페이지를 보실 수 있습니다.
간단히 방명록을 작성 하실 수 있습니다.
이제 HA Test 중 POD Down 테스트를 하겠습니다. HA Test 시나리오는 각 회사 상황에 맞게 POD 및 Node down 등을 횟수를 조정하면서 수행합니다.
먼저, 서비스 이상 유무 확인을 위하여 간단한 스크립트를 사용 하겠습니다. 매 1초마다 curl 요청을 보내어 서비스 down 여부를 체크하는 스크립트 입니다.
[spkr@erdia22 ~ (kspray:default)]$ while true;do curl -I 172.17.30.171; sleep 1; done
HTTP/1.1 200 OK
Date: Fri, 04 Jun 2021 04:43:10 GMT
Server: Apache/2.4.10 (Debian) PHP/5.6.20
Last-Modified: Wed, 09 Sep 2015 18:35:04 GMT
ETag: "399-51f54bdb4a600"
Accept-Ranges: bytes
Content-Length: 921
Vary: Accept-Encoding
Content-Type: text/html
HTTP/1.1 200 OK
Date: Fri, 04 Jun 2021 04:43:11 GMT
Server: Apache/2.4.10 (Debian) PHP/5.6.20
Last-Modified: Wed, 09 Sep 2015 18:35:04 GMT
ETag: "399-51f54bdb4a600"
Accept-Ranges: bytes
Content-Length: 921
Vary: Accept-Encoding
Content-Type: text/html
순차적으로 frontend 및 redis POD를 다운(delete) 합니다.
[spkr@erdia22 ~ (kspray:default)]$ kgp
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
frontend-6c6d6dfd4d-4lgzv 1/1 Running 0 14m 10.233.79.25 ksp2 <none> <none>
frontend-6c6d6dfd4d-5tswn 1/1 Running 0 14m 10.233.79.26 ksp2 <none> <none>
frontend-6c6d6dfd4d-dk7lj 1/1 Running 0 14m 10.233.79.28 ksp2 <none> <none>
redis-master-f46ff57fd-crdn9 1/1 Running 0 6m30s 10.233.79.30 ksp2 <none> <none>
redis-slave-7979cfdfb8-rcz6h 1/1 Running 0 14m 10.233.79.29 ksp2 <none> <none>
redis-slave-7979cfdfb8-src2f 1/1 Running 0 14m 10.233.79.27 ksp2 <none> <none>
[spkr@erdia22 06.Deployment (kspray:demo)]$ k delete pod frontend-6c6d6dfd4d-4lgzv
pod "frontend-6c6d6dfd4d-4lgzv" deleted
[spkr@erdia22 ~ (kspray:default)]$ k delete pod redis-master-f46ff57fd-crdn9 redis-slave-7979cfdfb8-rcz6h redis-slave-7979cfdfb8-src2f
pod "redis-master-f46ff57fd-crdn9" deleted
pod "redis-slave-7979cfdfb8-rcz6h" deleted
pod "redis-slave-7979cfdfb8-src2f" deleted
예상대로 순차적으로 Fronted 및 Redis POD를 down 하여도 서비스에는 이상 없습니다. 각각 이중화, 삼중화가 되어 있습니다. (Redis Master POD의 경우 2 초 만에 재시작됩니다. 데이터가 없어서 그런지 굉장히 빠르네요.)
[spkr@erdia22 ~ (kspray:default)]$ kgpw
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
(생략)
redis-master-f46ff57fd-nljdg 1/1 Running 0 25s 10.233.79.36 ksp2 <none> redis-master-f46ff57fd-nljdg 1/1 Terminating 0 40s 10.233.79.36 ksp2 <none> <none>
redis-master-f46ff57fd-9lqzv 0/1 Pending 0 0s <none> <none> <none> <none>
redis-master-f46ff57fd-9lqzv 0/1 Pending 0 0s <none> ksp2 <none> <none>
redis-master-f46ff57fd-9lqzv 0/1 ContainerCreating 0 0s <none> ksp2 <none> <none>
redis-master-f46ff57fd-nljdg 1/1 Terminating 0 41s 10.233.79.36 ksp2 <none> <none>
redis-master-f46ff57fd-9lqzv 0/1 ContainerCreating 0 1s <none> ksp2 <none> <none>
redis-master-f46ff57fd-nljdg 0/1 Terminating 0 42s 10.233.79.36 ksp2 <none> <none>
redis-master-f46ff57fd-9lqzv 1/1 Running 0 2s 10.233.79.37 ksp2 <none> <none>
redis-master-f46ff57fd-nljdg 0/1 Terminating 0 45s 10.233.79.36 ksp2 <none> <none>
redis-master-f46ff57fd-nljdg 0/1 Terminating 0 45s 10.233.79.36 ksp2 <none> <none>
Redis Master POD를 삭제하면 이전에 저장한 방명록 데이터가 삭제됩니다. PVC를 설정하지 않았기 때문입니다.
[spkr@erdia22 ~ (kspray:default)]$ k delete deployments.apps redis-master
deployment.apps "redis-master" deleted
노드 리부팅 및 Poweroff 테스트를 하면 서비스가 중단되는 걸 확인 할 수 있습니다. Frontend 3개의 POD가 동일 노드(ksp2)에서 실행 중이라서 그렇습니다. (affinity 설정으로 해결 가능합니다.)
[spkr@erdia22 ~ (kspray:default)]$ kgp
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
frontend-6c6d6dfd4d-dk7lj 1/1 Running 0 27m 10.233.79.28 ksp2 <none> <none>
frontend-6c6d6dfd4d-rmxt7 1/1 Running 0 12m 10.233.79.31 ksp2 <none> <none>
frontend-6c6d6dfd4d-vpqhx 1/1 Running 0 11m 10.233.79.32 ksp2 <none> <none>
이처럼 HA Test를 통하여 사전에 여러 취약점 확인이 가능합니다. 저희 고객사는 Custom Golang application + Elastic, Kafka, Mqtt, RbbbitMQ, MariaDB, NGINX, Tomcat 등 다양한 Application을 사용 중인데 각 Application에 따라 다양한 HA Test 시나리오가 있었습니다. 각 Application에 따라 적절한 조치가 필요합니다.
참고로, POD, Node 다운 이 외 CPU 및 Disk 부하, Autoscale 정상 여부 확인 등 다양한 시나리오가 있습니다. 첫술에 배부를 수는 없고 개별 환경에 따라 조금씩 테스트 항목 증가가 필요합니다. (Chaos Engineering을 검토하시면 됩니다.)
https://docs.litmuschaos.io/docs/chaoshub/#generic-chaos
부하테스트 Vegeta
사이트마다 사용하시는 부하테스트 Tool들이 다양하게 있습니다. 가장 많이 사용하는 JMeter 부터 k6, vegeta 등 여러가지가 있습니다. 그 중 숙련도 및 상황에 맞게 선택 하시면 됩니다. (JMeter는 UI 환경이라 되도록 CLI 지원하는 Tool을 사용하시는 것을 권고합니다. 반복 사용 시 업무 속도가 향상됩니다.)
K6 : https://k6.io/docs/
Vegeta : https://github.com/tsenart/vegeta
(우리가 아는 베지타 맞습니다.)
본 포스팅에서는 CLI 환경에서 간단하게 사용 할 수 있는 vegeta 예제 입니다. 초 당 250회 접속하여 부하 테스트를 하는 예시입니다.
[spkr@erdia22 68.HttpLoadTestVegeta (kspray:default)]$ echo "GET http://172.17.30.171/" | vegeta attack -name=250qps -rate=250 -duration=30s | tee results.250qps.bin |vegeta report
Requests [total, rate, throughput] 7500, 250.03, 250.01
Duration [total, attack, wait] 29.999s, 29.996s, 2.861ms
Latencies [min, mean, 50, 90, 95, 99, max] 1.934ms, 3.469ms, 2.903ms, 5.127ms, 6.387ms, 10.593ms, 19.715ms
Bytes In [total, mean] 6907500, 921.00
Bytes Out [total, mean] 0, 0.00
Success [ratio] 100.00%
Status Codes [code:count] 200:7500
Error Set:
- rate=250, 초 당 250번 수행
- duration=30s, 30초 간 수행
- Latency min, mean, 50, 90 등 각 구간 별 응답 속도 지연 확인 가능
- Success, 응답 비율
(기능이 제한적이고 실제 NGINX Session 수 측정 시 정확한 숫자가 측정이 안되는 문제가 있기도 하였습니다.)
물론 기본적인 상황이지만 개별 상황에 맞게 적절한 부하 생성 Tool을 선택하셔서 반드시 부하 테스트도 정례화 하시는 것을 권고 드립니다. 아마도 부하 테스트 시간 1시간이 이 후 장애 시 소요되는 하루 이상의 시간을 절약 할 수 있을 것 입니다.
그럼, 감사합니다.
'쿠버네티스 교육' 카테고리의 다른 글
24. Kube 교육 - Traefik Ingress L7 스위치 (0) | 2021.06.04 |
---|---|
23. Kube 교육 - Polaris(보안 취약점 확인) (0) | 2021.06.04 |
21. Kube 교육 - ArgoCD for GitOps (0) | 2021.06.04 |
20. Kube 교육 - Local GitLab Repository (0) | 2021.06.04 |
19. Kube 교육 - Harbor (0) | 2021.06.04 |