ECS 태스크가 EC2보다 느릴 경우, 시도해볼 수 있는 것들에 대한 정리 (feat. ECS exec)
ECS task가 EC2에서보다 느린 이유에 대해서 알아보고 성능 테스트를 해보겠습니다.
ECS Fargate에서 작업을 하다가, 뭔가 EC2보다 cpu 성능 뿐만 아니라, 네트워크 성능도 잘 안나오는 것 같아 2개의 게시물을 참고로 해서 실험을 해보았습니다
첫번째 참고글입니다.
아래 글은 Reddit에서 찾은 글입니다.
해당 글의 작성자는 nginx를 ECS를 통해 실행하는 것 같은데요. 하지만 EC2에서 실행할 때보다 성능이 나오지 않아 고민하고 있는 것 같습니다.
위 글에 대한 요약을 번역해보았습니다.
EC2 컨테이너 인스턴스의 CPU 수보다 작은 작업 수준 CPU 크기 조정을 사용하지 않는다고 가정할 때, ECS 자체에는 이와 같은 애플리케이션 성능 저하를 일으키는 요인이 없습니다. 많은 고객이 ECS 작업을 실행하는 초대형 인스턴스를 최대한 활용하고 있습니다.
설명만으로는 병목 현상이 발생한 위치를 파악하기가 어렵습니다...
보통 다음과 같은 요소들이 의심되는데요.
•
부하 테스트 설정
◦
유사한 동시성 수준을 사용하고 있는지?
◦
부하 테스트에 사용되는 동시성은 어떤 수준인지?
◦
응답 대기 시간의 차이는 응답 속도와 처리량에 큰 영향을 줄 수 있다고 합니다.
◦
다중 스레드 환경에서 동시성을 높이면 요청을 병렬화하고 전체 응답 속도를 향상시킬 수 있습니다
•
응답 대기 시간
◦
동일한 동시성 수준에서 응답 대기 시간이 변경되었는지?
◦
동시성이 낮을수록 응답 대기 시간이 전체 처리량에 미치는 영향이 커진다고 합니다
•
DNS
◦
DNS 또한 고려했는지?
◦
DNS 응답 대기 시간은 다중 계층 환경에서 문제를 일으킬 수 있습니다..!
◦
PHP/FPM 앱 서버가 DB에 연결하려고 할 때 호스트 이름 대신 DB 서버의 고정 IP 주소를 일시적으로 사용하여 앱 계층을 빠르게 변경하면 이를 배제할 수 있습니다.
•
로드 밸런싱
◦
AWS 로드 밸런서를 사용하고 있는지?
◦
그렇다면 사용 중인 구성은 어떤 것인지?
네트워크 대역을 검사하기 위해 컨테이너와 독립형 EC2 인스턴스 간에 양방향으로 iperf 테스트를 수행해볼 수 있습니다.
컨테이너에서 양방향으로 iperf를 실행했을 때 대역폭이 51.2Gbits/sec로 표시되었습니다. 이는 꽤 괜찮은 수치라고 하네요.
AWS re:post에서도 동일한 처방을 내려주었습니다.
ECS 작업의 성능은 EC2 인스턴스와 비교하여 사용하는 용량 유형에 따라 달라집니다.
EC2를 사용하는 경우, 네트워크 대역폭은 선택한 인스턴스의 네트워킹 성능에 의해 결정됩니다.
AWS는 다른 EC2 인스턴스의 네트워크 대역폭에 대한 문서를 제공합니다. AWS Fargate를 사용하는 경우, 네트워킹 성능은 작업 크기(서버 크기)에 따라 결정되며, 더 큰 작업일수록 더 높은 성능을 제공합니다.
(Larger tasks with more CPU and memory get higher networking performance.)
컨테이너 내에서 iperf와 같은 도구를 사용하여 네트워킹 성능을 테스트할 수 있습니다.
You could either use Amazon ECS exec to open a shell to one of your running containers
ECS에서 iperf를 사용하려면 컨테이너에 iperf를 설치한 후, 도커 exec하듯이 ECS exec를 해볼 수 있습니다.
ECS exec를 사용하기 위한 준비는 아래 문서를 참고해주시면 됩니다.
문서 모음
위의 문서를 통해 Session Manager를 설치합니다
mac 버젼 설치 링크
session-manager-plugin
aws ssm start-session --target instance-id
Shell
복사
아래 ecs service 내 exec를 활성화 후, force deploy를 합니다
aws ecs update-service \
--cluster 클러스터명 \
--service 서비스명 \
--enable-execute-command
Plain Text
복사
아래 aws cli 내 execute command 명령어를 통해 접근 가능하게 됩니다.
aws ecs execute-command \
--region <REGION> \
--cluster <CLUSTER NAME> \
--task <TASK ID> \
--container <CONTAINER NAME> \
--interactive
--command "/bin/sh"
Plain Text
복사
aws ecs describe-tasks \
--cluster cluster-name \
--tasks task-id
Shell
복사
위와 같이 뜬다면, 접근 가능한 상태입니다
혹시 위 과정 중에서, 아래와 같은 에러를 마주했다면 아래 방법을 따라서 해보세요!
An error occurred (InvalidParameterException)
when calling the ExecuteCommand operation:
The execute command failed because execute command
was not enabled when the task was run or the execute command agent isn’t running.
Wait and try again or run a new task with execute command enabled and try again.
Shell
복사
1.
enableExecuteCommand 매개변수가 true 또는 false로 설정되었는지 확인
a.
command
aws ecs describe-tasks --cluster <example-cluster-name> --tasks <example-task-id>| grep enableExecuteCommand
Plain Text
복사
2.
enableExecuteCommand 매개변수가 false인 경우, 매개변수를 true로 업데이트
서비스 내 태스크에 대해 Amazon ECS Exec 사용 여부를 결정합니다
•
CLI
aws ecs update-service \
--cluster <example-cluster-name> \
--service <example-service> \
--region <example-region> \
--enable-execute-command \
--force-new-deployment
Plain Text
복사
3.
ecsTaskExecutionRole에 다음 정책을 추가하세요.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssmmessages:CreateControlChannel",
"ssmmessages:CreateDataChannel",
"ssmmessages:OpenControlChannel",
"ssmmessages:OpenDataChannel"
],
"Resource": "*"
}
]
}
JSON
복사
그리고 ECS 작업을 업데이트해야 합니다. (ECS 서비스의 배포를 강제합시다.)
위의 설정을 마쳤다면 아래 콘솔에서 ecs exec가 가능해집니다.
위의 과정을 마치고, exec를 해서 컨테이너에 들어가 실험을 하려던 와중, iperf 테스트에 대한 흥미로운 글을 발견했습니다.
솔직히 말해서, 필자는 iperf 테스트를 진행하는 것이 조금 귀찮았습니다.
아래 개발자 분께서 저와 같은 애로를 겪고, 미리 테스트를 해주셨습니다. (저는 좋아요를 눌렀습니다)
위의 글을 참고하면 Fargate에서의 대역폭 성능을 확인할 수 있었습니다
조금 인용하자면,
인용글
메모리의 성능은 네트워크 대역폭과 비례하지 않는 것도 알 수 있는데요. 주로 CPU가 늘어날 때마다 대역폭이 상승 하였으며, 2vCPU부터는 네트워크 대역폭의 큰 상승은 없는 것으로 확인됐습니다.
그리고 0.25 vCPU 를 사용하는 경우 Fargate로 들어오는 트래픽 보다 Fargate에서 나가는 트래픽이 두 배 가까이 높은 것으로 관측되었습니다.
따라서 위의 대역폭을 참고하여 서비스 배포 시에 몇개의 태스크를 생성할 것인지 어림잡아 짐작이 가능할 것으로 보입니다. 보통 네트워크 대역폭이 Inbound/outbound를 합친 성능을 의미하므로 전송량에 따라 적절히 태스크 수를 예상할 수 있겠습니다.
또한 1vCPU / 2GB Memory 의 Fargate만 사용해도 최대치의 90% 가까운 네트워크 성능을 내므로 리소스의 가격대비 성능은 1vCPU / 2GB Memory 선택이 가장 좋다고 볼 수 있겠네요.
두번째 참고글입니다
아래 글의 질문자는 ECS로 python script를 돌리고 있지만, 프로세스가 그렇게 무겁지 않은데도 성능이 너무 안나온다는 문제가 있다고 합니다.
위의 문제는 결국 ECS를 띄울 때, 발생하는 로드밸런서의 헬스 체크 문제였다고 합니다.
ECS 헬스 체크가 fail하면서 성능이 하락할 수 있는지 확인이 필요할 것 같습니다.
The health check is also most likely looking for 200 OK & as your application running in Fargate is returning 404 Not Found for GET / the health check is failing and Fargate is shutting the task down.