데일리호텔 / 조회수 : 4166
Kubernetes을 활용한 분산 부하 테스팅
동명의 글이 Google Cloud Platform에도 있으니 여기서는 여태까지 한 삽질과 교훈에 집중한다.
처음에는 ngrinder로 부하 테스트 환경을 구축하려 했다. 몇 달 전에 부하 테스트를 진행할 때 잠시 쓴 적이 있었기 때문에 굳이 다른 솔루션을 찾을 이유가 없었다. 하지만 결국 후회하고 다른 솔루션으로 넘어갔는데 그 이유를 중요한 순으로 꼽자면
등이 있다. 이런 까닭에 좀더 간단한 솔루션을 찾아보았다.
몇 가지 대안을 살펴보았는데
Artillery는 테스트 스크립트를 yaml로 기술하기 때문에 얼핏 쉬워보이지만 이런 식의 접근 방법은 매번 실망만 안겨주었다. 조금만 테스트 시나리오가 복잡해지면 일반적인 코딩보다 설정 파일이 훨씬 짜기가 어렵고 이해하기도 어렵다.
config: target: 'https://my.app.dev' phases: - duration: 60 arrivalRate: 20 defaults: headers: x-my-service-auth: '987401838271002188298567' scenarios: - flow: - get: url: "/api/resource"
Gatling은 아직 분산 서비스를 지원하지 않아서 제외했다. 팀 내에 Scala 개발경험이 있는 사람이 극소수인 점도 문제였다.
이런 까닭에 Locust로 넘어왔다. 장점은
한마디로 ngrinder에서 아쉬웠던 점이 모두 해결됐다. 반면 ngrinder에 비해 못한 면도 많긴 하다.
현재로썬 그때그때 가볍게 시나리오를 작성해서 가볍게 돌려보는 게 중요하지 세밀함은 그리 중요하지 않아서 Locust가 더 나아 보인다. 시나리오는 몰라도 통계의 경우, DataDog 같은 모니터링 시스템에서 추가로 정보를 제공받기 때문에 큰 문제도 아니긴 하다.
GoogleCloudPlatform/distributed-load-testing-using-kubernetes에 있는 소소코드를 참고로 작업하면 된다. 단지 Dockerfile의 경우, 테스트 스크립트만 바뀌고 파이썬 패키지는 변경사항이 없는 경우에도 파이썬 스크립트 전체를 새로 빌드하는 문제가 있다.
# Add the external tasks directory into /tasks ADD locust-tasks /locust-tasks
# Install the required dependencies via pip RUN pip install -r /locust-tasks/requirements.txt
그러므로 이 부분을 살짝 고쳐주면 좋다.
ADD locust-tasks/requirements.txt /locust-tasks/requirements.txt
RUN pip install -r /locust-tasks/requirements.txt
ADD locust-tasks /locust-tasks
ngrinder를 Kubernetes v1.4.0 위에서 돌리는데 사용한 설정은 다음과 같다. 참고로 dailyhotel/ngrinder-data는 ngrinder의 데이터만 따로 뽑아서 관리하는 도커 이미지이다.
Controller
apiVersion: v1 kind: Service metadata: name: ngrinder labels: app: ngrinder tier: middle dns: route53 annotations: domainName: “ngrinder.test.com” spec: ports: # the port that this service should serve on — name: port80 port: 80 targetPort: 80 protocol: TCP — name: port16001 port: 16001 targetPort: 16001 protocol: TCP — name: port12000 port: 12000 targetPort: 12000 protocol: TCP — name: port12001 port: 12001 targetPort: 12001 protocol: TCP — name: port12002 port: 12002 targetPort: 12002 protocol: TCP — name: port12003 port: 12003 targetPort: 12003 protocol: TCP — name: port12004 port: 12004 targetPort: 12004 protocol: TCP — name: port12005 port: 12005 targetPort: 12005 protocol: TCP — name: port12006 port: 12006 targetPort: 12006 protocol: TCP — name: port12007 port: 12007 targetPort: 12007 protocol: TCP — name: port12008 port: 12008 targetPort: 12008 protocol: TCP — name: port12009 port: 12009 targetPort: 12009 protocol: TCP selector: app: ngrinder tier: middle type: LoadBalancer — - apiVersion: extensions/v1beta1 kind: Deployment metadata: name: ngrinder spec: replicas: 1 template: metadata: labels: app: ngrinder tier: middle spec: containers: — name: ngrinder-data image: dailyhotel/ngrinder-data:latest imagePullPolicy: Always volumeMounts: — mountPath: /opt/ngrinder-controller name: ngrinder-data-volume — name: ngrinder image: ngrinder/controller:latest resources: requests: cpu: 800m ports: — containerPort: 80 — containerPort: 16001 — containerPort: 12000 — containerPort: 12001 — containerPort: 12002 — containerPort: 12003 — containerPort: 12004 — containerPort: 12005 — containerPort: 12006 — containerPort: 12007 — containerPort: 12008 — containerPort: 12009 volumeMounts: — mountPath: /opt/ngrinder-controller name: ngrinder-data-volume volumes: — name: ngrinder-data-volume emptyDir: {}
Agents
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: ngrinder-agent spec: replicas: 5 template: metadata: labels: app: ngrinder-agent tier: middle spec: containers: — name: ngrinder-agent image: ngrinder/agent:latest imagePullPolicy: Always resources: requests: cpu: 300m args: [“ngrinder.test.com:80”]
#데일리 #데일리호텔 #개발 #개발자 #개발팀 #기술스택 #도입후기 #일지 #Kubernetes #인사이트
관련 스택