스터디 팀원과 같이 db종류에 따른 트래픽 부하를 테스트 하기 위해 프로젝트를 진행하고 있는데, 테스트 도구로는 nGrinder를 사용하기로 결정하였다.
그런데 docker hub에 올라와 있는 nGrinder는 ADM64기반 칩셋 지원 이미지만 올라와 있고, 내 M1 맥북과 같은 실리콘 맥 혹은 arm 기반 윈도우를 위한 컨테이너 이미지가 지원되지 않았다.
물론 nGrinder에서 소스코드 또한 제공해 주기 때문에 로컬로 설치 하는 방법이 있긴 하지만, 더이상 로컬에 뭔가를 설치하고 싶지 않음 + docker를 사용해보며 더 공부하고 싶은 생각이 들어서, 소스코드를 사용해 직접 aarch64 nGrinder image를 만들어서 올리기로 하였다. 사실 정확히는 소스코드가 아닌 빌드된 .war파일을 사용하였다.
(누군가는 이미 했겠지 하고 잠깐 검색해봤지만 성공한 결과를 찾을 수 없었다...)
먼저 https://github.com/naver/ngrinder/releases 에서 제공하는 nGrinder .war 파일을 다운로드 받는다.
다음으로는 .war파일과 같은 경로에 아래와 같은 Dockerfile을 작성한다.
FROM openjdk:11-slim
ARG WAR_FILE=./*war
COPY ${WAR_FILE} app.war
ENTRYPOINT ["java", "-jar", "/app.war"]
같은 경로에 docker-compose.yml file을 작성한다.
version: "3.8"
services:
ngrinder:
container_name: arm_ngrinder
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:8080"
현재 디렉토리 구조
.
├─ docker-compose.yml
├─ Dockerfile
└─ ngrinder-controller-3.5.8.war
위 경로에서
docker-compose up -d
를 입력하면 nGrinder controller 컨테이너가 빌드되어 도커에 올라가게 된다.
일단, 우리는 agent또한 빌드해야 하고, agent의 소스는 nGrinder controller에서 제공하기 때문에 우선 localhost:8080
에 접속하자
로그인화면이 뜨게 되는데, 처음 로그인 ID/PASSWORD는 admin/admin으로 설정되어 있으니 로그인을 하게되면,
오른쪽 위의 admin을 클릭하면 Download Agent를 눌러 Agent의 code를 얻을 수 있다.
.tar 파일의 압축을 풀고 다음 디렉토리 구조를 만든다.
현재 디렉토리 구조
.
├ngrinder-agent
│├─ Dockerfile
│├─ agent
│ ├─ lib
│ ├─ run-agent.sh
│ ├─ run-agent-bg.sh
│ .
│ .
│ .
└ngrinder-controller
├─ docker-compose.yml
├─ Dockerfile
└─ ngrinder-controller-3.5.8.war
ngrinder-agent 디렉토리 안의 Docker file은 다음과 같이 작성한다.
FROM openjdk:11-slim
COPU /agent /home/agent
CMD /home/agent/run_agent.sh -ch ngrinder-controller-arm
마지막으로 ngrinder-agent, ngrinder-controller가 들어있는 경로에 docker-compose.yml 파일을 작성한다.
version: "3.8"
services:
ngrinder-controller:
container_name: ngrinder-controller-arm
build:
context: ./ngrinder-controller
dockerfile: Dockerfile
restart: always
ports:
- "8080:8080"
- "12000-12009:12000-12009"
- "16001:16001"
networks:
- ngrinder
ngrinder-agent:
container_name: ngrinder-agent-arm
depends_on:
- ngrinder-controller
build:
context: ./ngrinder-agent
dockerfile: Dockerfile
restart: always
networks:
- ngrinder
networks:
ngrinder:
driver: bridge
현재 디렉토리 구조
.
├docker-compose.yml
├ngrinder-agent
│├─ Dockerfile
│├─ agent
│ ├─ lib
│ ├─ run-agent.sh
│ ├─ run-agent-bg.sh
│ .
│ .
│ .
└ngrinder-controller
├─ docker-compose.yml
├─ Dockerfile
└─ ngrinder-controller-3.5.8.war
이 상태로 docker-compose up -d를 입력하면
controller와 agent 컨테이너 모두 올라가는 것을 확인 할 수 있으며,
controller에서도
설정한 1개의 Agent가 할당된 것을 확인할 수 있다.
만약 더 많은 Agent 컨테이너를 올리고 싶다면 아래와 같이 docker-compose.yml을 수정하면 된다
version: "3.8"
build:
context: ./ngrinder-controller
dockerfile: Dockerfile
restart: always
ports:
- "8080:8080"
- "12000-12009:12000-12009"
- "16001:16001"
networks:
- ngrinder
ngrinder-agent-1:
container_name: ngrinder-agent-arm-1
depends_on:
- ngrinder-controller
build:
context: ./ngrinder-agent
dockerfile: Dockerfile
restart: always
networks:
- ngrinder
ngrinder-agent-2:
container_name: ngrinder-agent-arm-2
depends_on:
- ngrinder-controller
build:
context: ./ngrinder-agent
dockerfile: Dockerfile
restart: always
networks:
- ngrinder
networks:
ngrinder:
driver: bridge
처음에 시도할때는 금방 될 줄 알았는데 생각보다 시간을 많이 쏟게 되었다.
내가 놓친부분이 networks를 bridge로만 설정하면 호스트/포트 설정이 따로 필요 없을 줄 알았는데, 내가 브릿지 네트워크를 오해하고 있기 때문에 문제가 발생하였었다.
왜 Agent가 계속 못찾는 것인지 확인을 해보다가
docker inspect ngrinder_ngrinder를 통해 네트워크 설정을 보고,
내가 bridge기능을 오해한 것을 깨달았다.
나는 bridge기능이 컨테이너들을 같은 네트워크 상에 올려주는 걸로 이해했는데, 그런 식으로 작동하는 기능이 아니라
다른 기능들도 있지만, 컨테이너 이름을 해당 컨테이너의 호스트 주소로 자동으로 변환하는 내부 DNS 서비스를 제공하고 이를 통해 다른 컨테이너에 접근 할 수 있는 것이었다.
그래서 Dockerfile을 작성할때 -ch(controller host) 옵션을 ngrinder-contoller-arm으로 설정해주므로써 controller container에 접근 할 수 있게 되었다.
또 이 방법은 간단하지만 쉽게 springboot application을 올릴 수 있고, 사실은 실리콘 맥 뿐만아니라, AMD64 기반 PC에서도 사용할 수 있는 방법이다.
어차피 JVM 애플리케이션이면 naver에서 애초에 arm container를 지원해줬으면 좋았겠지만, 혹시 모를 버그/문제를 보증 할 수 없기 때문에 따로 제공하지 않는 거지 않을까 싶긴 하다 ㅎㅎ
덕분에 쉽게 실행할 수 있었습니다ㅠㅠ
참고로 여기 오타났어요!
COPU /agent /home/agent
COPU -> COPY
만약에 저처럼 도커를 잘 모르는 분이 계시다면 참고하시길 바라겠습니다!
아 그리고 /agent 는 실제로 본인이 작성한 폴더 이름이어야하더라구요
무작정 복붙해놓고 파일 이름을 저장해놨더니...하핳 에러가 발생하더라구요
공유해주셔서 감사드립니다! (꾸벅)