MLOps/MinIO

MinIO 부하 테스트 with NginX

ai-notes 2024. 7. 16. 16:41
반응형

 

2024.07.09 - [MLOps/MinIO] - MinIO MNMD on Kubernetes with Prometheus

 

MinIO MNMD on Kubernetes with Prometheus

이번에는 Distributed Mode MinIO(MNMD)를 구성한 방법에 대해 작성하고자 합니다.기존에는 3개 서버 정도에 5개의 디스크를 사용하려 했으나, 계획을 변경하여 여러 서버들을 모아 7개 서버에 10개의 디

ainotes.tistory.com

이 글에서 부하 분산에 걱정을 남기며 마무리 했었습니다.

임의로 부하를 테스트할 수 있는 방법을 찾아보니, MinIO에서 warp라는 테스트 도구를 제공하고 있어, 이 도구를 사용하여 부하 테스트를 진행했습니다.


Warp 설치

MinIO 부하 테스트를 위한 warp 설치는 deb파일로 진행했다.

wget https://github.com/minio/warp/releases/download/v0.10.1/warp_Linux_x86_64.deb
sudo apt install ./warp_Linux_x86_64.deb

설치를 마치고 나면, warp 명령어를 이용하여 부하 테스트를 진행할 수 있다.

예시 이미지

부하 테스트에는 여러 종류가 있는데, 대표적으로 Mixed(종합), Put(업로드), Get(다운로드), Delete(삭제) 등이 있다.
이 글에서는 대부분 Put으로 진행을 했는데, Get의 경우 데이터를 다운로드하기 위해 인풋하는 시간(Preparing)이 있는데제법 오래 걸린다. (업로드 벤치마크로 기록이 되긴한다.) 

warp get --host <NodeIP>:<Port>/ --access-key=user --secret-key=password --concurrent 20 --autoterm --duration 15m --noclear
warp put --host <NodeIP>:<Port>/ --access-key=user --secret-key=password --concurrent 20 --autoterm --duration 15m

 

--duration 시간이 짧으면, too few sample로 벤치마크가 기록되지 않을 수 있으므로, 적절한 시간을 부여하는 것이 좋다. 

--concurrent 몇명이 동시에 서비스를 요청할 것인지 설정한다. (default 20)

--autoterm 시간절약을 위해 변화가 어느정도 안정되면 자동으로 종료한다.

NginX

NginX를 이용한 Load Balancing

NginX는 대표적인 경량 웹 서버로 로드 밸런싱, 리버스 프록시 등의 역할을 한다.

NginX를 설치하면서 기대하던 효과는 위 그림과 같은데, 클라이언트의 요청을 NginX로 받고 리버스 프록시를 통해 사용중이지 않은 혹은 순서에 따라 MinIO 서버에 연결 하여 로드 밸런싱을 수행하는 것이다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        volumeMounts:
        - name: config-volume
          mountPath: /etc/nginx/conf.d
      volumes:
      - name: config-volume
        configMap:
          name: nginx-config
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: LoadBalancer
  selector:
    app: nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  minio.conf: |
    upstream minio_s3 {
        least_conn;
        server minio-0.minio-service.minio-data.svc.cluster.local:9000;
        server minio-1.minio-service.minio-data.svc.cluster.local:9000;
        server minio-2.minio-service.minio-data.svc.cluster.local:9000;
        server minio-3.minio-service.minio-data.svc.cluster.local:9000;
        server minio-4.minio-service.minio-data.svc.cluster.local:9000;
    }

    server {
        listen       80;
        listen  [::]:80;

        ignore_invalid_headers off;
        client_max_body_size 0;
        proxy_buffering off;
        proxy_request_buffering off;

        location / {
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;

            proxy_connect_timeout 300;
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            chunked_transfer_encoding off;

            proxy_pass http://minio_s3;
        }
      }

위의 코드로 NginX를 배포하였으며, ConfigMap은 MinIO 공식 홈페이지에서 사용한 설정값을 참조했다.

다만, 온프레미스 환경에서는 Externel IP가 <Pending>에서 변화가 없으므로 MetalLB를 통해 온프레미스 환경에서도 External-IP를 사용할 수 있도록 했다.

MetalLB

MetalLB는 온프레미스 환경에서 LoadBalancer를 사용하기 위해 설치한다.

설치하기전, K8s에 아래 설정을 수행해야 한다.

# 편집기로 strictARP를 true로 수정
kubectl edit configmap -n kube-system kube-proxy
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
  strictARP: true
  
  OR
# 아래 명령어 수행
kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/" | \
kubectl diff -f - -n kube-system

MetalLB는 helm을 이용하여 설치했다.

helm repo add metallb https://metallb.github.io/metallb
helm repo update
helm install metallb metallb/metallb

이후 yaml 파일을 생성해 아래 설정을 적용 했다.

apiVersion: metallb.io/v1beta1 
kind: IPAddressPool
metadata:
  name: ip-pool
spec:
  addresses:
  # 사용할 ip pool
  - 192.168.111.1-192.168.111.5
  autoAssign: true

--- 

apiVersion: metallb.io/v1beta1 
kind: L2Advertisement 
metadata:
  name: l2-network
spec:
  ipAddressPools:
    - ip-pool

이렇게 설치를 마치면,

nginx-service의 External-IP에 MetalLB에서 설정한 IP가 부여된 것을 확인할 수 있다.

이 IP로 접근하면, 리버스 프록시를 통해 MinIO에 접속할 수 있다.

NodePort

쿠버네티스에서는 NodePort만 사용해도 로드 밸런싱을 수행해 준다고 한다. 다만, 사용자가 Worker Node에 접속 후, 해당 노드가 서비스로 바인딩 해주고, 서비스는 노드들의 상태를 봐서 연결을 해주는데 이 과정이 비효율적이라고 한다.

MinIO Service NodePort

 

부하 테스트 결과

위 설치를 모두 마친 후, warp를 이용한 부하 테스트를 진행했다.

warp --host nginx-ip/ --concurrent 20 --duration 10m --access-key id --secret-key password --syncstart hh:mm
warp --host nodeport-ip:port --concurrent 20 --duration 10m --access-key id --secret-key password --syncstart hh:mm

테스트 결과 일부

 

3개 서버를 이용하여 --syncstart로 시작시점을 맞추고 부하테스트를 진행했는데, nginx와 nodeport는 오차 범위내의 차이를 보였다.

 

마치며

특정 IP:NodePort (ex:server-1) 로 2명 이상의 클라이언트가 접속을 하고 요청을 보내면, 동일한 네트워크 스펙을 사용하기 때문에 당연히 server-1의 용량을 초과하여 다운로드나 업로드 속도에 영향을 미칠 것이라고 생각을 했습니다.

그러나 K8s 자체의 로드밸런싱과 MinIO 자체에서도 부하 분산 기능이 있고, 또한 외부에서 오는 요청 자체(많아야 4건 정도)가 많지 않기 때문에 NginX를 붙여도 큰 차이를 보이지 않았던 것 같습니다.

 

반응형