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

위 스크립트는 매우 간단합니다.

  1. counter m1, m2, m3, m4를 초기화합니다.
  2. 외부 ip(192.168.24.41)로 curl을 실행합니다. html output을 RES로 저장합니다.
  3. 각각의 output마다 counter를 증가시킵니다.
  4. 2,3 단계를 100번 반복합니다.
  5. 마지막으로 각각의 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)