locust + k8s 분산 부하 테스트 구현

SeungHyuk Shin·2022년 12월 8일
0
post-thumbnail

백앤드 개발을 하다보면 많이 사용되는 도구 중의 하나가 부하 테스트 툴인데, 대표적인 도구로는 Apache Jmeter, nGrinder,SOAP UI 등의 도구가 있지만 다소 사용이 어렵고 스케일링을 하는데 어려움이 있는데, locust라는 도구는 설치와 사용이 편리하고, 테스트 시나리오를 파이썬 스크립트로 작성을 하기 때문에 다양한 시나리오 구현이 가능하다.

흔히 개발자들이 고민하는 코드가 스레드 세이프한지 혹은 레이스 컨디션 등을 잘 처리하는지 실제로 테스트 해보기에도 좋은 것 같다.

사내에서 개발 하는 서비스가 트래픽이 많은 서비스가 아니다 보니 높은 트래픽이 몰렸을때의 성능을 테스트하고 개선해보고 싶어 loucst를 이용해 분산 부하 테스트를 구현해 보았다.

원래 helm chart를 지원했으나 더 이상 공식적으로 지원하지 않기에 직접 yaml을 작성해 loucst를 쿠버네티스 클러스터에 배포를 했다. 분산 부하다 보니 시나리오를 실행 하는 master 역할을 하는 파드와 시나리오를 직접 목표 url로 요청하는 워커 파드로 구성되어있다고 생각 하면된다.

GCP 공식 가이드 github를 참고해 작성했다.

이 글에서는 locust를 사용하는 방법 보다는 쿠버네티스 배포 방법 위주로 글을 정리하고자 한다.


우선 locust 배포 설정을 확인해보자면

apiVersion: "apps/v1"
kind: "Deployment"
metadata:
  name: locust-worker
  labels:
    name: locust-worker
spec:
  replicas: 5
  selector:
    matchLabels:
      app: locust-worker
  template:
    metadata:
      labels:
        app: locust-worker
    spec:
      containers:
        - name: locust-worker
          image: ${이미지 주소}
          env:
            - name: LOCUST_MODE
              value: worker
            - name: LOCUST_MASTER
              value: locust-master
            - name: TARGET_HOST
              value: ${목표 호스트}
---
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
  name: locust-master
  labels:
    name: locust-master
spec:
  replicas: 1
  selector:
    matchLabels:
      app: locust-master
  template:
    metadata:
      labels:
        app: locust-master
    spec:
      containers:
        - name: locust-master
          image: ${이미지 주소}
          env:
            - name: LOCUST_MODE
              value: master
            - name: TARGET_HOST
              value: ${목표 호스트}
          ports:
            - name: loc-master-web
              containerPort: 8089
              protocol: TCP
            - name: loc-master-p1
              containerPort: 5557
              protocol: TCP
            - name: loc-master-p2
              containerPort: 5558
              protocol: TCP

여기서 주목해야 하는 곳은 LOCUST_MODE를 worker로 지정해두고 이미지가 실행될때 run.sh을 통해 worker로 실행할지 master로 실행할지 정하게 되고 워커가 LOCUST_MASTER에 메타데이터의 라벨을 따라 어느 마스터를 바라봐야할지 정하게 된다. 워커의 숫자는 5개로 지정해두었다.

if [[ "$LOCUST_MODE" = "master" ]]; then
    LOCUS_OPTS="$LOCUS_OPTS --master"
elif [[ "$LOCUST_MODE" = "worker" ]]; then
    LOCUS_OPTS="$LOCUS_OPTS --worker --master-host=$LOCUST_MASTER"
fi

다음은 service 설정이다.

kind: Service
apiVersion: v1
metadata:
  name: locust-master
  labels:
    app: locust-master
spec:
  ports:
    - port: 5557
      targetPort: loc-master-p1
      protocol: TCP
      name: loc-master-p1
    - port: 5558
      targetPort: loc-master-p2
      protocol: TCP
      name: loc-master-p2
  selector:
    app: locust-master
---
akind: Service
apiVersion: v1
metadata:
  name: locust-master-web
  annotations:
    networking.gke.io/load-balancer-type: "Internal"
  labels:
    app: locust-master
spec:
  ports:
    - port: 8089
      targetPort: loc-master-web
      protocol: TCP
      name: loc-master-web
  selector:
    app: locust-master
  type: LoadBalancer

앞서 정의한 master node를 External IP (Load Balancer)로 밖으로 빼서, 웹 콘솔 접속등을 가능하게 하는 설정인데, 주의할점은 locust 웹 콘솔은 별도의 사용자 인증 기능이 없기 때문에, 위의 설정을 그대로 사용하면, 인증 기능이 없는 웹콘솔이 인터넷에 그래도 노출이 되기 때문에, 권장하지 않는다.

ClusterIP로 Service를 정의한 후, kubectl의 port forwarding 기능을 사용하거나 또는 앞에 인증용 프록시 서버를 두는 것을 권장한다. 구글 클라우드의 경우에는 Identity Aware Proxy(IAP)라는 기능을 이용하여, 구글 클라우드 계정으로 로그인을 해야 웹사이트를 접근할 수 있는 프록시 기능을 제공한다.

혹은 ingress의 whiltelist source range를 통해 요청이 들어오는 IP를 제한할 수 있다.


마지막으로 Ingress 설정이다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: locust-master-ingress
  namespace: default
spec:
  rules:
     - host: ${도메인 주소} # Ingress IP와 매핑되는 도메인
       http:
           paths:
             - backend:
                 service:
                   name: locust-master-web
                   port:
                     number: 8089
               path: /
               pathType: Prefix

이후 인그레스를 통해 접속했을때 나오는 화면이다. 오른쪽위에 워커또한 잘 떠있는 확인 할 수 있다.

0개의 댓글