Amazon ECS 용량과 가용성

Amazon ECS 용량과 가용성

애플리케이션 가용성은 오류 없는 경험을 제공하고 지연 시간을 최소화하는 데 매우 중요합니다. 이 글에서는 Amazon ECS에서 가용성을 관리하는 방식과 확장 속도를 최대화하는 방법, 수요 급증에 대처하는 방법을 알아봅니다.

출처: 문서

본문

애플리케이션 가용성은 오류 없는 경험을 제공하고 애플리케이션 지연 시간을 최소화하는 데 매우 중요해요. 가용성은 접근 가능하고 수요를 충족할 충분한 용량을 가진 리소스가 있는지에 달려 있습니다. AWS는 가용성을 관리하는 여러 메커니즘을 제공합니다. Amazon ECS에서 호스팅하는 애플리케이션의 경우 여기에는 오토스케일링(autoscaling)과 가용 영역(Availability Zones, AZ)이 포함됩니다. 오토스케일링은 사용자가 정의한 지표에 따라 태스크 또는 인스턴스 수를 관리하고, 가용 영역은 고립되어 있지만 지리적으로 가까운 위치에 애플리케이션을 호스팅할 수 있게 해줍니다.

태스크 크기와 마찬가지로 용량과 가용성도 고려해야 할 트레이드오프가 있습니다. 이상적으로는 용량이 수요와 완벽하게 일치해야 해요. 요청을 처리하고 작업을 처리할 수 있을 만큼 항상 딱 맞는 용량이 있어 서비스 수준 목표(SLO, Service Level Objectives)를 충족할 수 있어야 합니다. 용량이 너무 높아 과도한 비용이 들지도, 너무 낮아 높은 지연 시간과 오류율을 초래하지도 않아야 합니다.

오토스케일링은 지연이 있는(latent) 프로세스입니다. 먼저 CloudWatch가 실시간 지표를 받아야 합니다. 그리고 CloudWatch는 분석을 위해 지표를 집계해야 하는데, 지표의 세분성(granularity)에 따라 최대 몇 분이 걸릴 수 있어요. CloudWatch는 지표를 알람 임계값과 비교하여 리소스의 부족 또는 과잉을 식별합니다. 불안정성을 방지하려면 임계값이 몇 분 동안 초과된 후에 알람이 울리도록 알람을 구성해야 합니다.

또한 새 태스크를 프로비저닝하고 더 이상 필요 없는 태스크를 종료하는 데도 시간이 걸립니다. 이런 잠재적인 지연 때문에 과잉 프로비저닝(over-provisioning)으로 약간의 여유(headroom)를 유지해야 합니다. 과잉 프로비저닝은 단기적인 수요 급증을 수용하는 데 도움이 됩니다. 또한 애플리케이션이 포화 상태에 이르지 않고 추가 요청을 서비스하는 데도 도움이 됩니다. 좋은 방법으로 스케일링 목표를 활용률의 60-80% 사이로 설정할 수 있어요. 이렇게 하면 추가 용량을 프로비저닝하는 동안 애플리케이션이 추가 수요의 급증을 더 잘 처리할 수 있습니다.

또한 과잉 프로비저닝을 권장하는 이유는 가용 영역 실패에 빠르게 대응할 수 있기 때문입니다. AWS는 프로덕션 워크로드가 여러 가용 영역에서 서비스되도록 권장합니다. 가용 영역 장애가 발생하면 나머지 가용 영역에서 실행 중인 태스크가 여전히 수요를 서비스할 수 있기 때문이에요. 애플리케이션이 두 개의 가용 영역에서 실행된다면 일반 태스크 수의 두 배가 필요합니다. 이는 잠재적 장애가 발생하는 동안 즉시 용량을 제공하기 위해서입니다. 애플리케이션이 세 개의 가용 영역에서 실행된다면 일반 태스크 수의 1.5배를 실행할 것을 권장합니다. 즉, 일반 서비스에 필요한 두 개마다 세 개의 태스크를 실행하는 것입니다.

확장 속도 최대화 (Maximizing scaling speed)

오토스케일링은 효과가 나타나기까지 시간이 걸리는 반응형 프로세스입니다. 하지만 스케일 아웃에 필요한 시간을 최소화하는 방법이 몇 가지 있습니다.

이미지 크기 최소화 (Minimize image size)

더 큰 이미지는 이미지 저장소에서 다운로드하고 압축을 푸는 데 더 오래 걸립니다. 따라서 이미지 크기를 작게 유지하면 컨테이너가 시작하는 데 필요한 시간이 줄어듭니다. 이미지 크기를 줄이려면 다음과 같은 구체적인 권장 사항을 따를 수 있어요:

  • 정적 바이너리를 빌드할 수 있거나 Golang을 사용한다면 FROM scratch에서 이미지를 빌드하고 결과 이미지에 바이너리 애플리케이션만 포함하세요.
  • Amazon Linux나 Ubuntu 같은 업스트림 배포판 공급업체의 최소화된 기본 이미지를 사용하세요.
  • 최종 이미지에 빌드 아티팩트를 포함하지 마세요. 멀티 스테이지 빌드(multi-stage builds)가 도움이 될 수 있어요.
  • 가능하면 RUN 스테이지를 압축(compact)하세요. 각 RUN 스테이지는 새 이미지 레이어를 만들고, 레이어 다운로드를 위한 추가 왕복(round trip)이 발생합니다. &&로 연결된 여러 명령이 있는 단일 RUN 스테이지는 여러 RUN 스테이지를 가진 것보다 레이어가 적습니다.
  • ML 추론 데이터 같은 데이터를 최종 이미지에 포함하고 싶다면 시작하고 트래픽을 서비스하는 데 필요한 데이터만 포함하세요. 서비스에 영향을 주지 않고 Amazon S3나 다른 스토리지에서 데이터를 온디맨드로 가져올 수 있다면 해당 위치에 데이터를 저장하세요.

이미지를 가깝게 유지 (Keep your images close)

네트워크 지연 시간이 높을수록 이미지 다운로드에 더 오래 걸립니다. 워크로드가 있는 AWS 리전과 같은 리전의 저장소에 이미지를 호스팅하세요. Amazon ECR은 Amazon ECS를 사용할 수 있는 모든 리전에서 제공되는 고성능 이미지 저장소입니다. 컨테이너 이미지를 다운로드하기 위해 인터넷이나 VPN 링크를 횡단하는 것을 피하세요. 이미지를 같은 리전에 호스팅하면 전반적인 신뢰성이 향상됩니다. 다른 리전의 네트워크 연결 문제와 가용성 문제의 위험을 완화해 주기 때문이에요. 또는 Amazon ECR 교차 리전 복제(cross-region replication)를 구현하는 것도 도움이 될 수 있습니다.

로드 밸런서 상태 확인 임계값 줄이기 (Reduce load balancer health check thresholds)

로드 밸런서는 애플리케이션으로 트래픽을 보내기 전에 상태 확인(health check)을 수행합니다. 대상 그룹(target group)의 기본 상태 확인 구성은 90초 이상 걸릴 수 있습니다. 그동안 로드 밸런서는 상태를 확인하고 요청을 받습니다. 상태 확인 간격(interval)과 임계값 횟수를 낮추면 애플리케이션이 더 빨리 트래픽을 수용하고 다른 태스크의 부하를 줄일 수 있어요.

콜드 스타트 성능 고려 (Consider cold-start performance)

Java 같은 런타임을 사용하는 일부 애플리케이션은 JIT(Just-In-Time) 컴파일을 수행합니다. 시작 시의 컴파일 과정이 애플리케이션 성능에 영향을 줄 수 있어요. 해결 방법은 지연 시간에 민감한 워크로드 부분을 콜드 스타트 성능 패널티가 없는 언어로 다시 작성하는 것입니다.

타깃 추적 대신 단계 스케일링 사용 (Use step scaling, not target-tracking scaling policies)

Amazon ECS 태스크에 대한 Application Auto Scaling 옵션은 여러 가지가 있습니다. 타깃 추적(target tracking)은 가장 사용하기 쉬운 모드입니다. 이를 사용하면 CPU 평균 사용률 같은 지표의 타깃 값만 설정하면 됩니다. 그러면 오토 스케일러가 그 값을 달성하는 데 필요한 태스크 수를 자동으로 관리합니다. 단계 스케일링(step scaling)을 사용하면 스케일링 지표의 특정 임계값과 임계값이 초과될 때 추가하거나 제거할 태스크 수를 직접 정의하므로 수요 변화에 더 빠르게 대응할 수 있어요. 그리고 더 중요한 것은 임계값 알람이 위반 상태로 유지되는 시간을 최소화하여 수요 변화에 매우 빠르게 대응할 수 있다는 점입니다. 자세한 내용은 Amazon Elastic Container Service 개발자 가이드의 Service Auto Scaling 문서를 참고하세요.

Amazon EC2 인스턴스로 클러스터 용량을 제공한다면 다음 권장 사항을 고려하세요:

  • 더 큰 Amazon EC2 인스턴스와 더 빠른 Amazon EBS 볼륨 사용 (Use larger Amazon EC2 instances and faster Amazon EBS volumes) — 더 큰 Amazon EC2 인스턴스와 더 빠른 Amazon EBS 볼륨을 사용하면 이미지 다운로드 및 준비 속도를 개선할 수 있어요. 주어진 Amazon EC2 인스턴스 패밀리 내에서 인스턴스 크기가 커질수록(예: m5.xlarge에서 m5.2xlarge로) 네트워크와 Amazon EBS 최대 처리량이 증가합니다. 또한 Amazon EBS 볼륨을 사용자 지정하여 처리량과 IOPS를 늘릴 수 있습니다. 예를 들어 gp2 볼륨을 사용한다면 기본 처리량이 더 많은 더 큰 볼륨을 사용하세요. gp3 볼륨을 사용한다면 볼륨 생성 시 처리량과 IOPS를 지정하세요.
  • Amazon EC2 인스턴스에서 실행되는 태스크에 bridge 네트워크 모드 사용 (Use bridge network mode for tasks running on Amazon EC2 instances) — Amazon EC2에서 bridge 네트워크 모드를 사용하는 태스크는 awsvpc 네트워크 모드를 사용하는 태스크보다 더 빨리 시작됩니다. awsvpc 네트워크 모드를 사용하면 Amazon ECS가 태스크를 시작하기 전에 인스턴스에 탄력적 네트워크 인터페이스(ENI)를 연결합니다. 이로 인해 추가 지연 시간이 발생합니다. 다만 bridge 네트워킹 사용에는 몇 가지 트레이드오프가 있어요. 이 태스크는 자체 보안 그룹을 갖지 못하고 로드 밸런싱에도 몇 가지 영향이 있습니다. 자세한 내용은 Elastic Load Balancing 사용자 가이드의 로드 밸런서 대상 그룹 문서를 참고하세요.

수요 급증 처리 (Handling demand shocks)

일부 애플리케이션은 갑작스러운 큰 수요 급증을 경험합니다. 뉴스 이벤트, 대규모 세일, 미디어 이벤트, 또는 입소문이 나서 아주 짧은 시간에 트래픽이 급격히 증가하는 어떤 이벤트 등 다양한 이유로 발생합니다. 계획되지 않았다면 수요가 사용 가능한 리소스를 빠르게 앞지를 수 있어요.

수요 급증을 처리하는 가장 좋은 방법은 이를 예상하고 그에 따라 계획하는 것입니다. 오토스케일링은 시간이 걸릴 수 있으므로 수요 급증이 시작되기 전에 애플리케이션을 스케일 아웃할 것을 권장합니다. 최상의 결과를 위해 공유 캘린더를 사용하는 팀 간의 긴밀한 협업이 포함된 비즈니스 계획을 가질 것을 권장합니다. 이벤트를 계획하는 팀은 사전에 애플리케이션을 담당하는 팀과 긴밀하게 협력해야 해요. 그러면 그 팀이 명확한 일정 계획을 세울 충분한 시간을 갖게 됩니다. 이벤트 전에 스케일 아웃하고 이벤트 후에 스케일 인하도록 용량을 예약할 수 있어요. 자세한 내용은 Application Auto Scaling 사용자 가이드의 예약 스케일링(Scheduled scaling) 문서를 참고하세요.

Enterprise Support 플랜을 사용한다면 테크니컬 어카운트 매니저(TAM)와도 반드시 협력하세요. TAM은 서비스 쿼터를 확인하고 필수 쿼터가 이벤트 시작 전에 상향되었는지 확인해 줍니다. 이렇게 하면 실수로 서비스 쿼터에 부딪히는 것을 방지할 수 있어요. 또한 로드 밸런서 같은 서비스를 프리워밍(prewarming)하여 이벤트가 원활하게 진행되도록 도와줄 수 있습니다.

계획되지 않은 수요 급증을 처리하는 것은 더 어려운 문제입니다. 계획되지 않은 급증은 진폭이 충분히 크다면 수요가 빠르게 용량을 앞지를 수 있습니다. 또한 오토스케일링이 반응할 수 있는 능력을 앞지를 수도 있어요. 계획되지 않은 급증에 대비하는 가장 좋은 방법은 리소스를 과잉 프로비저닝하는 것입니다. 어느 때든 예상되는 최대 트래픽 수요를 처리할 충분한 리소스가 있어야 해요.

계획되지 않은 수요 급증에 대비해 최대 용량을 유지하는 것은 비용이 많이 들 수 있습니다. 비용 영향을 완화하려면 큰 수요 급증이 임박했음을 예측하는 선행 지표(leading indicator) 지표 또는 이벤트를 찾으세요. 지표 또는 이벤트가 신뢰성 있게 상당한 사전 통지를 제공한다면, 이벤트가 발생하거나 지표가 설정한 특정 임계값을 초과할 때 즉시 스케일 아웃 프로세스를 시작하세요.

애플리케이션이 갑작스러운 계획되지 않은 수요 급증에 취약하다면, 비필수 기능은 희생하지만 고객에게 중요한 기능은 유지하는 고성능 모드를 애플리케이션에 추가하는 것을 고려하세요. 예를 들어 애플리케이션이 비용이 많이 드는 맞춤형 응답 생성에서 정적 응답 페이지 제공으로 전환할 수 있다고 가정해 보겠습니다. 이 시나리오에서는 애플리케이션을 전혀 스케일링하지 않고도 처리량을 크게 늘릴 수 있어요.

마지막으로 모놀리식(monolithic) 서비스를 분리하여 수요 급증을 더 잘 처리하는 것을 고려할 수 있습니다. 애플리케이션이 실행 비용이 높고 확장이 느린 모놀리식 서비스라면 성능에 중요한 부분을 추출하거나 다시 작성하여 별도의 서비스로 실행할 수 있어요. 그러면 이 새 서비스는 덜 중요한 구성 요소와 독립적으로 확장될 수 있습니다. 성능에 중요한 기능을 애플리케이션의 다른 부분과 별도로 스케일 아웃할 수 있는 유연성은 용량 추가에 걸리는 시간을 줄이고 비용을 절약하는 데도 도움이 됩니다.

더 알아보기 (Learn more)

  • Service Auto Scaling과 예약 스케일링에 대한 자세한 내용은 AWS 개발자 가이드의 관련 문서를 참고하세요.