k8s pod goroutine

# k8s 환경에서 golang 서버를 pod 로 만들어 stress test(부하 테스트)를 했다.
# 부하 테스트 툴은 vegeta 를 사용

# 1개의 pod 를 운영하고 1000/1s 로 부하를 주면
echo "GET http://ysofman.test.com:9999/test" | vegeta attack -duration=10s -rate=1000/1s -timeout=500ms | tee results.bin | vegeta report

# 다음과 같이 17% 성공한다.
# 1000*0.17 = 170tps
Requests      [total, rate]            10000, 1000.05
Duration      [total, attack, wait]    10.151548026s, 9.999496s, 152.052026ms
Latencies     [mean, 50, 95, 99, max]  51.131863ms, 0s, 379.564354ms, 480.801383ms, 561.313466ms
Bytes In      [total, mean]            20482436, 2048.24
Bytes Out     [total, mean]            0, 0.00
Success       [ratio]                  17.42%
Status Codes  [code:count]             0:8258  200:1742

# 부하 테스트 중 해당 pod pprof 를 refresh 하면서 확인해 보면
# goroutine 수가 최대 50개 정도로 부하에 비해 많이 늘어 나지 않는다.
http://ysofman.test.com:9999/debug/pprof

# 그냥 로컬 환경으로 서버를 띄워 부하 테스트 하면 100%성공으로 1000tps 가 나온다.
# pprof 를 확인하면 goroutine 이 200 개 이상으로 늘어났다 줄어든다.
# 원인은 k9s deployment 설정에서 container resource 부분에
# pod가 있는 실제 node 의 리소스가 충분하면 pod 의 컨테이너가 사용할 수 있는 
# cpu 리소스가 100m 0.1core 이상 사용할 수 있도록 허용하고 (requests)
# 최대 cpu 리소스가 250m 0.25core 까지만 사용하도록 제한돼 있었다.(limits)
# 참고로
# requests 를 사용할 수 있는 node 에 스케줄링 된다.
# limits 를 넘어가면 OOM(Out Of Memory)에러와 함께 종료시킨다.
# m은 milli 단위로 1000m = 1 = 1core 를 사용할 수 있다.
resources:
 limits:
   cpu: 250m
 requests:
   cpu: 100m

# goroutine 을 core 개수만큼 goroutine 을 동시에서 처리할 수 있는데
# runtime.NumCPU() 가 8 이고,
# runtime.GOMAXPROCS(8) 로 8개 코어(프로세서)를 사용할 수 있도록 설정해도
# k8s 차원에서 pod core 를 1/4core 로 제한해서
# 부하처리를 위한 goroutine 들이 pending 되어 대다수 응답이 타임아웃된다.
# cpu limits 를 8 로 늘리면 1000tps (100%성공률) 성능이 나온다.

comments:

댓글 쓰기