nGrinder?
nGrinder는 Naver에서 제공하는 성능 테스트 툴입니다. 직관적인 UI/UX로 많은 회사에서 사용하고 있는 성능 테스트 툴이지만 직접 구축해서 사용해야 합니다.
이 글에서는 다루지 않지만 성능 테스트의 대상이 되는 서버에 설치하는 Monitor도 있습니다. Monitor는 성능 테스트를 진행하는 동안 타겟 서버의 CPU, 메모리 등을 확인할 수 있게 해줍니다. 다만 Monitor를 설치하지 않아도 성능 테스트는 진행할 수 있으므로 이 글에서는 다루지 않습니다.
즉, nGrinder 시스템을 구축하기 위해서는 하나의 Controller와 여러 개의 Agent를 구축해야 합니다. 직접 서버에 war
파일을 다운받아서 구축할 수도 있는데 이 방법은 공식 위키에 잘 나와있습니다. 물론 EC2와 같은 서버에 직접 Controller와 Agent를 설치하면 간단한 성능 테스트 정도는 진행할 수 있습니다. 다만 아래와 같은 단점을 가질 수 있습니다.
- 더 많은 부하를 만들어내기 위해서는 Agent의 수를 늘려야 합니다. 따라서 새로운 Agent가 필요할 때마다 매번 EC2에 Agent를 구축해야 합니다.
- 성능 테스트는 365일 24시간 돌아가는 것이 아니기 때문에 항상 많은 Agent가 필요한 것은 아닙니다. 따라서 Agent는 성능 테스트가 필요할 때만 개수를 늘렸다가 성능 테스트가 끝나면 모두 종료하는 것이 비용적으로 좋습니다. 하지만 EC2에 직접 구축하면 이런 과정이 번거롭습니다.
결국 EC2에 직접 Agent를 구축하면 동적으로 Agent의 수를 조정하는 것이 불편합니다. 성능 테스트가 불편해지면 테스트를 덜 실행하게 되므로 편리하게 Agent를 동적으로 스케일링할 수 있게 구축하는 것이 중요합니다. AWS에서는 아래와 같은 방법들을 생각해볼 수 있습니다.
- 오토 스케일링 그룹
- AWS Beanstalk
- AWS ECS
AWS Beanstalk의 경우 이동욱님의 블로그에 잘 정리되어 있습니다. 이 글에서는 AWS ECS Fargate에 nGrinder를 구축하는 방법을 알아보겠습니다.
ECS 클러스터 생성하기
2022년 1월 8일 기준으로 새로운 ECS 환경 콘솔의 모습으로 이후에 위 사진과 콘솔 UI가 달라질 수 있습니다.
클러스터는 ECS의 가장 기본적인 단위로 서비스나 태스크가 실행되는 곳이라고 생각하면 됩니다. 우리는 Controller 서비스와 Agent 서비스를 클러스터에 배포해서 nGrinder 환경을 구축한다고 생각하면 됩니다.
Controller 구축
작업 정의 혹은 태스크 정의(Task Definition) 는 ECS의 최소 실행 단위인 태스크를 실행하기 위한 일종의 명세라고 생각하면 됩니다. 컨테이너에서 어떤 이미지를 실행할 것인지, CPU나 메모리는 얼마나 할당할 것인지, 어떤 포트를 할당할 것인지 등을 정의한다고 생각하면 됩니다.
태스크는 ECS의 최소 실행 단위로 하나 혹은 둘 이상의 컨테이너 묶음이라고 생각하면 됩니다. 정말 간단하게 생각하면 우리가 클러스터에 실행하려고 하는 각각의 서버를 의미한다고 생각해도 됩니다.
예를 들어 nGrinder Controller가 1개의 EC2 서버에 구축되어 있고 nGrinder Agent가 3개의 EC2 서버에 실행되고 있을 때 이를 ECS 클러스터로 옮기면 nGrinder Controller Task 1개, nGrinder Agent Task 3개가 생기게 됩니다.
따라서 Controller 태스크와 Agent 태스크를 실행하기 위해서 각각의 태스크 정의를 생성해야 합니다.
태스크 정의 생성
컨테이너 이미지 URI의 경우 ngrinder에서 공식적으로 제공하는 Controller 이미지인 ngrinder/controller
를 사용합니다.
Controller의 경우 웹 페이지를 위한 80
포트, Agent가 접속하는 16001
포트, 성능 테스트를 진행할 때Controller와 Agent가 통신할 때 사용하는 12000~12000+
포트를 사용합니다. 12000
번대 포트의 경우 동시에 진행하는 성능 테스트 수만큼 열어주면 됩니다.
환경 변수는 별도로 설정하지 않아도 됩니다.
태스크 크기의 경우 이 글에서는 2vCPU와 4 GB의 메모리를 사용하지만 이는 최적화된 값이 아닐 수 있습니다. 이 값은 언제든지 태스크 정의의 새로운 개정을 생성하면서 수정할 수 있으므로 성능 테스트를 하면서 적절한 값을 찾아서 설정하면 됩니다.
태스크 역할은 따로 부여하지 않으며 네트워크 모드는 AWS Fargate를 사용하므로 awsvpc를 사용하게 됩니다. 스토리지 또한 별도로 설정하지 않습니다.
이렇게 모든 설정을 마친 뒤에 생성 버튼을 눌러주면 Controller에 대한 태스크 정의가 만들어집니다.
보안 그룹 생성
이 뒤에서 Controller를 외부에서 고정된 IP로 접속할 수 있게하기 위해서 로드 밸런서를 연결해야 합니다. 이 과정에서 보안 그룹을 설정해야 하는데 필요할 때 만드는 것보다 한번에 만들어놓고 연결하는 것이 편하니 먼저 보안 그룹을 생성하고 로드 밸런서를 생성하겠습니다.
VPC의 경우 nGrinder 클러스터를 만들 때 사용했던 값을 사용합니다.
Agent의 경우 Controller나 Target에 연결할뿐 사용자 또는 다른 서버에서 Agent에 접속할 일이 없으므로 인바운드 규칙은 설정하지 않습니다. 아웃바운드 규칙의 경우 기본적으로 설정되어 있는 값을 사용합니다.
인바운드 규칙의 경우 Controller 태스트 정의를 만들 때처럼 80, 12000-12000+, 16001 포트를 열어야 합니다. 이때 80
포트는 외부 사용자가 접속할 수 있도록 모든 IP에 대해서 열어주고 12000~12000+
, 16001
포트는 Agent가 Controller에 접속하는 포트이므로 위에서 생성한 Agent 보안 그룹(nGrinder-agent-sg)에 대해서만 열어줍니다.
아웃바운드 규칙의 경우 기본적으로 설정되어 있는 값을 사용합니다.
인바운드 규칙의 경우 80
포트만 외부 사용자가 접속할 수 있도록 모든 IP에 대해서 열어줍니다.
아웃바운드 규칙의 경우 기본적으로 설정되어 있는 값을 사용합니다.
로드 밸런서 생성
Controller의 경우 성능 테스트를 위한 웹 GUI를 제공합니다. Controller의 IP는 매 배포때마다 달라지므로 이를 하나의 단일된 엔드포인트로 제공하기 위해서 로드 밸런서를 사용할 수 있습니다.
이 로드 밸런서는 외부 사용자가 접속할 수 있어야 하므로 Internet-facing을 선택합니다. IP address type의 경우 IPv4를 사용합니다.
nGrinder-lb-sg
)을 연결해 줍니다.
리스너에는 타겟 그룹을 연결해야 하므로 Create target group 링크를 눌러 타겟 그룹을 생성합니다.
서비스 생성
서비스는 태스크를 관리하기 위한 단위로 클러스터 내에 태스크가 지정된 수만큼 실행될 수 있도록 관리하는 책임을 가지고 있습니다. 이뿐만 아니라 실행중인 태스크들을 로드밸런서로 연걸하거나 서비스 디스커버리를 위해 AWS Cloud Map에 등록하는 등의 설정도 할 수 있습니다.
이 글에서는 Agent가 Controller의 IP를 찾기 위해서 서비스 검색 기능을 사용합니다. 다만 새로운 ECS 콘솔 환경에서 서비스를 생성할 때 이 메뉴가 사라져서 이전 콘솔 환경으로 전환해서 서비스를 생성합니다. 이 글을 작성하는 시점에는 이 메뉴가 없으나 이후에는 다시 생길 수도 있으니 상황에 맞게 진행하시면 될 것 같습니다.
이후에 Agent의 태스크 정의를 생성할 때 컨테이너가 실행될 때 설정하는 커맨드를 설정하는데 이 옵션 또한 새로운 콘솔 환경에서 사라져 이 뒤 모든 작업은 구형 콘솔에서 진행합니다.
controller는 태스크를 1개만 실행할 것이므로 1로 설정하면 됩니다.
nGrinder-controller-sg
)을 선택합니다. 자동 할당 퍼블릭 IP는 ENABLED를 선택합니다.
새로운 서비스 검색 서비스를 등록하는 것이므로 새로운 서비스 검색 서비스 생성을 선택하고 서비스 검색 이름에는 컨트롤러를 나타낼 수 있는 이름을 사용하면 됩니다. 여기서는 controller라는 값을 사용합니다.
DNS 레코드 유형의 경우 A
타입을 사용하고 TTL은 적당한 값을 사용하면 됩니다. 여기서는 60초를 사용합니다.
이렇게 서비스 검색을 설정하면 Controller를 새로 배포하더라도 Agent 설정 수정 없이 Agent가 새로운 Controller에 연결할 수 있습니다.
서비스 검색 통합 활성화를 사용하면 DNS를 통해 Controller의 IP를 얻을 수 있습니다. 이 DNS는 {서비스 검색 이름}.{네임스페이스 이름}
형태로 생성되는데 이 값을 Agent 태스크 정의를 만들 때 사용하므로 기억해둬야 합니다. 여기서는 controller.ngrinder
가 됩니다.
controller
작업이 실행되고 있는 것을 확인할 수 있습니다.
RUNNING
상태로 바뀌고 아까 만든 로드밸런서의 DNS로 nGrinder에 접속할 수 있습니다.
로드 밸런서가 nGrinder로 헬스 체크를 하는 과정에서 기본 URL /
로 요청을 하면 302
응답을 줘서 헬스 체크에 실패하는 경우가 있습니다. 이런 경우 ECS는 태스크 실행에 실패한 것으로 보고 태스크 재시작을 반복하게 됩니다. 타겟 그룹 설정을 변경하면 됩니다.
302
코드를 추가하면 됩니다.
Agent 구축
이제 Controller에 연결할 Agent를 구축하면 됩니다. Controller를 구축할 때처럼 먼저 태스크 정의를 만든 뒤 서비스를 생성하면 됩니다.
태스크 정의 생성
새로운 콘솔 환경에서 컨테이너 커맨드 설정이 사라져서 구 콘솔 환경에서 진행합니다.
태스크 역할은 없음을 선택하고 운영 체제 패밀리는 Linux를 선택합니다.
ecsTaskExecutionRole
를 사용하면 됩니다. 만약 ecsTaskExecutionRole
가 없다면 새 역할 생성을 선택합니다.
작업 메모리는 6GB, 작업 CPU는 2 vCPU를 사용합니다. 이 또한 최적의 값이 아닐 수 있으며 언제든지 수정할 수 있으므로 나중에 원한다면 수정하면 됩니다.
ngrinder/agent
를 사용합니다.
Controller와 달리 Agent는 외부에서 Agent로 접속하지 않으므로 포트 매핑은 하지 않습니다.
{서비스 검색 이름}.{네임스페이스 이름}
형태로 생성되며 이 글에서는 controller.ngrinder
가 됩니다. 그래서 명령에 DNS:포트번호
를 적어주면 되는데 이 글에서는 controller.ngrinder:80
가 됩니다.
나머지 설정은 건드릴 부분이 없으므로 추가 버튼을 눌러 컨테이너를 추가해 줍니다. 그리고 생성 버튼을 눌러 Agent의 태스크 정의를 생성을 완료합니다.
서비스 생성
Agent는 Controller와 달리 여러 개의 태스크가 뜰 수 있으므로 작업 개수에 2를 설정합니다. 더 많은 Agent를 사용하고 싶다면 원하는 Agent 개수를 적어주면 됩니다.
nGrinder-agent-sg
)을 선택합니다. 자동 할당 퍼블릭 IP는 ENABLED를 선택합니다.
A
타입을 사용하고 TTL은 적당한 값을 사용하면 됩니다. 여기서는 60초를 사용합니다.
결국 이 설정에 따르면 Agent는 agent.ngrinder
라는 DNS로 접근할 수 있습니다만 이를 사용하지는 않습니다. 서비스 검색은 Agent가 Controller에 연결하기 위해서만 사용합니다.
이후 서비스 생성 버튼을 눌러 Agent 서비스를 생성합니다.
RUNNING
으로 바뀌면 nGrinder 웹 페이지에 접속해 Agent가 연결되었는지 확인하면 됩니다.
확인
Agent 스케일링
만약 Agent 서버의 개수를 조정하고 싶다면 클러스터의 서비스 설정에서 조정할 수 있습니다.
2
인 것을 확인할 수 있습니다.
10
개라는 작업 개수를 맞추기 위해서 8
개의 새로운 Agent가 실행되는 것을 확인할 수 있습니다.
정리
AWS ECS에 nGrinder를 구축하는 방법이 정리된 글이 없기에 글을 한번 작성해봤습니다. 개인적으로는 오토 스케일링 그룹이나 AWS Beanstalk보다 훨씬 편하게 구축하고 스케일링할 수 있는 방법이라고 생각합니다.
만약 AWS ECS Fargate에 대해 익숙하지 않다면 이 글을 참고하면 좋을 것 같습니다. 혹시나 글에 잘못된 내용이 있다면 댓글로 남겨주세요!
로드 밸런서에 여러 개의 Controller 포트를 매핑하는 방법을 찾지 못해 AWS Cloud Map을 사용했는데 혹시 다른 방법이 있으면 댓글로 알려주시면 감사하겠습니다.