Dev/DevOps, Infra

[AWS, Post-mortem] EC2 리소스 과다 사용으로 인한 인스턴스 상태 확인 실패 문제와 SQS dead-letter queues

HJChung 2021. 9. 12. 16:38

AI 분석이 필요한 메세지가 AWS standard SQS에 들어오면 AI analyzer가 해당 메세지를 가져가서 분석을 시작하는 형태의 서비스가 있습니다.

이런 서비스에서 AI 분석 도중 EC2가 멈추고 Status check에서도 instance reachability check failed가 뜨는 경우가 발생할 때 어떤 식으로 대응을 해 나갈 것인지 고민하는 과정을 가졌습니다.

그리고 그 과정에서 알게된 SQS dead-letter queues에 대해서 정리하였습니다. 


AI analyzer가 도커 형태로 띄워져 있는 EC2 서버의 유형은 아래와 같다. 

인스턴스 GPU vCPU 메모리 (GiB) GPU 메모리(GiB) 스토리지(GB) 네트워크 성능(Gbps)
g4dn.4xlarge 1 16 64 16 225 최대 35

어떤 한 메세지에 대해서 AI 분석이 시작되도록 해놓고 한참 지나니 EC2가 멈추는 현상이 발생했다. 그리고 ssh로 connect를 해보려고 해도  instance reachability check failed가 떴다. 

 

처음에는 EC2 maintenance event인가 싶어서 빨리 scaler 구현을 해야겠다고 생각했는데, 이상하게 해당 메세지의 분석을 돌릴 때만 이런 문제가 발생했다. 

 

음.... 이럴 때 해야할 것은

 

1. 문제 재현하기

해당 메세지 분석이 실행될 때만 이런 에러가 발생하는 것인지 확실하게 확인을 해야 (문제 재현을 할 수 있어야) 그다음 원인이 무엇인지 파악할 수 있다. 
그래서 다른 메세지로 시도해 보았는데 그 문제가 발생하지 않았다. 

 

결국 어떤 특정 메세지(문제를 발생시키는 그 메세지)의 분석이 어떠한 이유로 EC2에서 문제를 발생시키는 것이었다. 

 

2. 원인 알아보기

EC2에서 확인 할 수 있는 에러 메세지는 <instance reachability check failed> 이다. 이 에러가 어떤 경우에 나타날 수 있는지 에러를 구글링 해보았다. 

https://aws.amazon.com/ko/premiumsupport/knowledge-center/system-reachability-check/

 

연결할 수 없는 EC2 Linux 인스턴스의 상태 확인 실패 문제 해결

Amazon Elastic Compute Cloud(Amazon EC2) Linux 인스턴스에 연결할 수 없어 상태 확인 중 하나 또는 둘 다에 실패합니다. 상태 확인 실패 문제를 해결하려면 어떻게 해야 합니까?

aws.amazon.com

AWS 공식문서에서 정리하고 있는 바에 따르면 

 

인스턴스 상태 확인: 인스턴스 상태 확인 실패는 다음과 같은 운영 체제 수준 오류로 인해 인스턴스에 문제가 있음을 나타냅니다.

  • 운영 체제 부팅 실패
  • 올바른 볼륨 마운트 실패
  • 파일 시스템 문제
  • 호환되지 않는 드라이버
  • 커널 패닉
  • 인스턴스 리소스의 과다 사용에 의한 심각한 메모리 압력으로 인해 인스턴스 상태 확인이 실패할 수도 있습니다.

 

라고 나와있다.

NVIDIA Driver는 잘 호환되는 것을 확인 한 바가 있고

EFS도 함께 사용하고 있기 때문에 볼륨 마운트나 파일 시스템 문제일 수도 있겠다 싶었는데 여기선 문제가 없었다. 

 

마지막으로 AI 분석이 십 몇분이 넘어가도록 진행되다가 EC2가 퍼지는 것으로 봐서 인스턴스 리소스 과다 사용으로 인해 리소스 부족(특히 메모리 부족)으로 인한 문제이지 않을까 라고 생각이 들었다. 

그래서 htop 명령어로 사스템 사용량 즉 CPU 사용량, 메모리 사용량 등을 확인하면서 진짜 맞는지 보았다. 

 

그 결과 문제가 생기는 메세지의 분석이 시작되고 십몇 분 동안 실행이 되다가 Memory 사용량이 거의 다 찰 때(61.2G) 쯤 EC2가 먹통이 되는 것을 확인했다. 

 

그래서 '해당 메세지의 AI inference 코드가 돌면서 EC2 Linux 인스턴스가 리소스 과다 사용으로 인해 인스턴스 상태 확인에 실패하는 문제였다'라고 일단 원인을 파악할 수 있었다. 

 

 

3. 해결법 고민 및 적용

  • 도커 자원 할당 제한 - 메모리 제한
    • EC2가 완전히 퍼지는 것을 막기 위해 어플리케이션에 할당할 메모리는 60G로 제한한다 (지금처럼 EC2 자체에 문제가 생기지 않도록 EC2가 도는데 필요한 메모리라고 생각되는 1~2G 남겨두기)
    • 이렇게 되면 EC2가 죽지 않고 문제가 되는 docker container에서 돌고 있는 application만 이상이 생길 텐데 always restart해서 재시작이 가능하게 하기 

 

  • AI analyzer가 그렇게 되었다고, slack alert로 장애 공지 보내기
    • EC2 monitor에서는 Status Check failed 뜨면 alert.
    • SQS에서는 Approximate Age Of Oldest Message가 일정 시간을 넘어가면 alert, ApproximateNumberOfMessagesVisible 가 일정 개수가 넘어가면 alert.

 

  •  code level 에서 어디서 메모리를 많이 잡아먹는지 알기

 

정도로 계획하고 적용하였다. 

 

 

4. SQS dead-letter queues

docker-compose 파일에 

restart: always
mem_limit: "60g" # 60GB로 메모리 제한

이 되어 있으니까 이전과 다르게 한 58. 몇 GB쯤에서 분석이 멈추고, 다시 0으로 돌아가 분석이 처음부터 다시 시작되고를 반복했다. 

 

이렇게 EC2가 완전히 이상이 생겨버리는 것은 해결했는데,,,, 

문제는, 그 문제가 생긴 분석이 마무리되지 않는 메세지가 계속 SQS 큐에 남아있어서 몇 번이고 분석을 다시 시도하게 된다는 것이다. 

 

그래서, Queue에서 Retry가 많이 일어나서 일정 회수 이상 분석을 시도했는데도 성공하지 않는다면 Dead-Letter Queue로 보내고 유저에게는 분석할 수 없다고 안내메세지를 보내야 한다. 

Amazon SQS supports dead-letter queues, which other queues (source queues) can target for messages that can't be processed (consumed) successfully. 

Dead-letter queues로 보내지는 메세지가 생기면 그때도 slack으로 라던지 alert를 보내게 만든다면 어떤 메세지에서 실패가 지속되었는지 등의 로그 등을 검사하거나 디버깅이 용이하다. 

 

origin enqueue에서 메세지의 ReceiveCount가 maxReceiveCount를 초과하게 되면 Dead-letter queue로 옮겨진다. 

 

1) Dead-Letter Queue로 사용할 standard 큐 만들기

dead-letter-queue라는 이름의 큐를 만들어주었다. 여기서 주의할 것은, <Amazon SQS dead-letter queues - How do dead-letter queues work?> 에서 important 에도 나와있듯이 Message retention period는 origin enqueue의 Message retention period보다 길게 잡아야한다. 

 

origin enqueue에서 dead-letter queue로 넘어왔다고 하더라도 그 메세지의 timestamp가 바뀌는 것은 아니기 때문이다. 

예를 들어 dead letter queue의 message retention period가 4 days라면 origin enqueue에서 1일 후 dead letter queue로 넘어왔왔다 하더라도 여기서 3일 후에 메세지는 삭제된다. 

 

2) dead-letter queue를 적용할 origin enqueue로 가서 앞서 만든 큐를 적용시킨다. 

Maximum receives로 몇 번 retry 후 보낼 것인지를 설정해 줄 수 있다. 

 

 

3) 적용 결과 보기

위에서 maximum receives를 3으로 해주었으므로 3회 재 시도후에도 분석이 완료되지 않은 메세지가 dead-letter queue로 넘어가서 더이상 EC2에서 반복적인 분석이 이루어지지 않는 것을 알 수 있다. 

 

 

 

 

 

이제 Dead-letter queues로 보내지는 메세지가 생기면 그때도 slack으로 바로 alert가 갈 수 있도록 하고 싶다. 

비슷한 고민을 하고 있는 stackoverflow 글을 찾았는데 

하지만 좋은 생각이 떠오르지 않고 실시간으로 그렇게 하려면 lambda를 사용해야 하는 건가 라는 생각도 든다. 

 

 

 

 

Reference

Basic Amazon SQS architecture

https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html

 

Amazon SQS dead-letter queues - Amazon Simple Queue Service

Standard queues allow a high number of inflight messages. If the majority of your messages can’t be consumed and aren’t sent to a dead-letter queue, your rate of processing valid messages can slow down. Thus, to maintain the efficiency of your queue, m

docs.aws.amazon.com

[SQS] Queue 에서 Retry가 많이 일어나서 Dead-Letter Queue를 이용한 Redrive Policy 구성

Why is my EC2 Linux instance unreachable and failing one or both of its status checks?

My EC2 Linux instance failed the instance status check due to over-utilization of its resources. How do I troubleshoot this?