kube-proxy load balance test (ko)
1. kube-proxy란?
Kubernetes는 컨테이너를 위한 통합 도구입니다. kube-proxy의 특징은 다음과 같습니다.
- kube-proxy는 kubernetes minion에 실행되는 kubernetes의 구성 요소입니다.
- kube-proxy는 각각의 컨테이너에서 네트워크 프록시 및 load balancer 역할을 합니다.
- kube-proxy는 랜덤 모드 및 확률 설정을 포함한 iptables 통계 확장 모듈을 사용합니다.
본 문서에서 진행하는 테스트를 통해서 kube-proxy가 얼마나 고르게 traffic을 처리하는지 살펴볼 것입니다.
테스트 환경은 다음과 같습니다. (master 1개, minion 4개)
- kubemaster: 192.168.24.31
- kubeminion1: 192.168.24.41
- kubeminion2: 192.168.24.42
- kubeminion3: 10.0.24.43
- kubeminion4: 10.0.24.44
각각의 컨테이너가 각각의 minion에서 동작하도록 하기 위해서 4개의 replica set을 포함한 nginx 컨테이너를 생성할 예정입니다.
우선 nginx deployment yaml manifest 파일(dep_nginx.yml) 을 생성하겠습니다.
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 4
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
protocol: TCP
volumeMounts:
- name: documentroot
mountPath: /usr/share/nginx/html
volumes:
- name: documentroot
hostPath:
path: /srv/nginx
/srv/nginx hostPath를 컨테이너의 /usr/share/nginx/html에 놓았습니다. 왜냐하면 각각의 nginx 서버들이 소유한 html 페이지를 반환 받기를 원하기 때문입니다.
각각의 minion에서 /src/nginx 디렉토리를 생성합니다.
$ sudo mkdir /srv/nginx
각각의 minion에 간단한 html 파일(/srv/nginx/index.html)을 생성하겠습니다.
$ echo "<h1>kubeminion1's nginx</h1>" | sudo tee /srv/nginx/index.html
kubeminion1’s nginx on kubeminion1, kubeminion2’s nginx on kubeminion2, etc…
pods는 전혀 실행하지 않았습니다. nginx pods를 실행하기 위해서 kubectl을 실행하겠습니다.
$ kubectl create -f dep_nginx.yml
4개의 replica를 만드는데 약간의 시간이 소요됩니다. 실행되고 있는 4개의 pods를 확인해 보겠습니다.
$ kubectl get po -o wide
nginx-1024743661-5rh83 1/1 Running 0 1d 10.100.84.4 192.168.24.41
nginx-1024743661-bhcgs 1/1 Running 0 1d 10.100.27.2 192.168.24.42
nginx-1024743661-gr311 1/1 Running 0 1d 10.100.79.3 10.0.24.44
nginx-1024743661-xhuvs 1/1 Running 0 1d 10.100.69.4 10.0.24.43
좋습니다! 각각의 minion에서 4개의 pods가 실행되고 있습니다.
한 가지 더 수행할 작업은 외부 클라이언트가 nginx 웹 컨테이너에 도달할 수 있도록 하기 위해서 서비스를 이 deployment에 놓는 것 입니다.
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 80
protocol: TCP
externalIPs: ["192.168.24.41"]
externalIPs 설정은 192.168.24.41 (kubeminion1)의 nginx 웹 포트에 보여질 예정입니다
서비스 상태가 up인지 확인해보겠습니다.
$ kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-svc 10.100.216.9 192.168.24.41 80/TCP 1d
EXTERNAL-IP가 192.168.24.41입니다. 좋습니다~
각각의 minion에서 iptables 룰이 제대로 설정되었는지 확인하겠습니다.
$ sudo iptables -S -t nat | grep statistic
-A KUBE-SVC-R2VK7O5AFVLRAXSH -m comment --comment "default/nginx-svc:" -m
statistic --mode random --probability 0.25000000000 -j KUBE-SEP-GQOPG5ZI7EFB76CL
-A KUBE-SVC-R2VK7O5AFVLRAXSH -m comment --comment "default/nginx-svc:" -m
statistic --mode random --probability 0.33332999982 -j KUBE-SEP-NQ634KA75OUBVO7B
-A KUBE-SVC-R2VK7O5AFVLRAXSH -m comment --comment "default/nginx-svc:" -m
statistic --mode random --probability 0.50000000000 -j KUBE-SEP-TIWXH2ANNGANIYGQ
좋습니다~ 통계 모듈(랜덤 모드 및 확률 설정을 포함)을 포함한 iptables 룰을 살펴보겠습니다.
모든 설정이 완료되었습니다.
2. 테스트
kube-proxy가 부하를 얼마나 고르게 분배하는지 테스트하기 위해서 curl, bash script를 사용하겠습니다. 물론 더 좋은 테스트 tool이 있지만 이번 테스트에서는 curl 만으로도 충분합니다.
쉘 스크립트입니다.(kube_proxy_lb_test.sh)
#!/bin/bash
m1=0
m2=0
m3=0
m4=0
for ((c=1;c<=100;c++))
do
RES=$(curl -s http://192.168.24.41)
#echo $RES
case $RES in
*kubeminion1*)
m1=$(($m1+1))
;;
*kubeminion2*)
m2=$(($m2+1))
;;
*kubeminion3*)
m3=$(($m3+1))
;;
*kubeminion4*)
m4=$(($m4+1))
;;
esac
done
echo $m1:$m2:$m3:$m4
위 스크립트는 매우 간단합니다.
- counter m1, m2, m3, m4를 초기화합니다.
- 외부 ip(192.168.24.41)로 curl을 실행합니다. html output을 RES로 저장합니다.
- 각각의 output마다 counter를 증가시킵니다.
- 2,3 단계를 100번 반복합니다.
- 마지막으로 각각의 counter를 출력합니다.
3. 결과
각각의 nginx pod 마다 25개의 reponses를 예상했지만 결과는 달랐습니다. 결과는 다음과 같습니다.
test | test no | minion1 | minion2 | minion3 | minion4 | deviation |
---|---|---|---|---|---|---|
100 reqs | 1 | 27 | 27 | 25 | 21 | 22% |
. | 2 | 15 | 34 | 22 | 29 | 56% |
. | 3 | 20 | 24 | 26 | 30 | 33% |
. | 4 | 26 | 22 | 27 | 25 | 19% |
. | 5 | 27 | 25 | 27 | 21 | 22% |
. | 합계 | 115 | 132 | 127 | 126 | 13% |
최대 56%에 달하는 편차는 매우 좋지 않습니다. 그러나 합계 열에서 편차는 13%입니다. 이는 테스트에서 충분한 샘플을 사용하지 않았다는 것을 의미합니다.
그래서 request 횟수를 100에서 1200으로 변경했습니다.
아래 결과를 얻을 수 있었습니다.
test | test no | minion1 | minion2 | minion3 | minion4 | deviation |
---|---|---|---|---|---|---|
1200 reqs | 1 | 325 | 296 | 278 | 301 | 14% |
. | 2 | 293 | 289 | 300 | 318 | 9% |
. | 3 | 298 | 292 | 289 | 321 | 10% |
. | 4 | 324 | 283 | 280 | 313 | 14% |
. | 5 | 296 | 276 | 318 | 310 | 13% |
. | 합계 | 1536 | 1436 | 1465 | 1563 | 8% |
보시다시피 편차는 14%로 훨씬 나아졌습니다.
request 횟수를 12000으로 변경한다면 어떤 결과가 예상되시나요?
test | test no | minion1 | minion2 | minion3 | minion4 | deviation |
---|---|---|---|---|---|---|
12000 reqs | 1 | 3003 | 2977 | 3019 | 3001 | 1% |
. | 2 | 3067 | 2894 | 3025 | 3014 | 6% |
. | 3 | 3025 | 3000 | 2941 | 3034 | 3% |
. | 합계 | 9095 | 8871 | 8985 | 9049 | 2% |
훨씬 나은 load balancing을 볼 수 있습니다.
더 많은 샘플을 확보한다면 편차는 0%에 수렴할 것으로 예상됩니다.
References
- kubernetes
- iptables statistic module (man iptables-extension)