본문 바로가기
AWS/Lambda

AWS Lambda Troubleshooting 1: Cold Start, 콜드 스타트

by 알파해커 2020. 3. 5.
반응형

현업에서 AWS Lambda를 사용하면서 경험했던 바에 따르면, Lambda를 사용하는 것에 있어 가장 큰 단점이자 어려움은 Cold start인 것 같다.

 

Lambda의 근간이 되는 기술인 Container라는 개념은 Scaling하는데 있어 혁신적인 기술이라고 여겨진다. 왜냐하면, Scale-out하는 상황에서, AWS EC2와 같이, 가상OS가 새로 생성되는 방식이기 아닌, OS 위에 돌아가는 독립적인 하나의 프로그램을 생성하는 개념이기 때문이다.

 

다시말해, 우리가 꺼져있는 컴퓨터를 키는 것이 아니라, 켜져있는 컴퓨터에 프로그램을 하나 키는 것이다. 때문에 당연히 훨씬 가볍다.

 

때문에 Lambda를 쓰게 되면, 가장 낮은 사양으로 셋팅하더라도, 부하가 생기는 순간에, Container가 빨리 빨리 뜨면서 Scale-out이 되고, 그것이 부하들을 다 받아낼 수 있을거라는 기대를 하게 된다. 개념적으로는 맞는 말이다. 그러나 실제로는 그렇게 되지 않는 경우가 많이 존재한다. 

 

그렇지 되지 않는 경우 == 빠르게 Container가 생성되지 않는 경우 == Cold start

 

Cold start라는 것은 결국, 꺼져있는, 완전히 식어버린 컴퓨터를 새로 킨다는 의미이다. 굳이 비유하자면, 잠시 절전 모드의 (그러나 전원이 켜져있는) 컴퓨터를 키는 것보다, 완전히 꺼져버린 컴퓨터를 새로 키는 것이 훨씬 오래 걸릴 것이다.

 

그렇다면, AWS Lambda의 내부동작과 함께, Cold start의 종류를 한번 보자.

 

1. 인스턴스 자체가 떠있지 않은 상황

컨테이너라는 것은 앞서 설명했듯이 프로그램의 개념이다. 이 프로그램이 실행되기 위해서는, 어쨌든 컴퓨터가 켜져야 한다. 이 컴퓨터를 인스턴스라고 한다면, 프로그램을 Container라고 생각할 수 있다. 때문에, Lambda로 들어가는 요청과 요청사이의 간격이 너무 크거나, 최초의 요청이라서, 인스턴스 자체가 내려가 있을 수도 있을 것이다. 이때 Cold start가 발생할 수 있다.

 

2. ENI 적용 시간

Lambda도 결국 서버이다. 서버는 다양한 통신을 할 수 있다. 예를 들어 데이터베이스와 통신을 해야하는 상황이라고 했을 때, Lambda가 통신을 하기위한 Network Interface인 ENI가 Lambda Container에 적용이 되어야 한다. 이는 VPC를 사용하는 Lambda에는 반드시 적용되는 것인데, 원래 이 부분이 Cold start의 가장 주요한 부분이었다. 

 

그럼, 그 문제있는(?) VPC는 반드시 적용해야 하는 것일까?

사실, VPC의 주요 목적 중 하나는, 네트워크 구조 안에 서버 리소스 들을 넣어놓고 관리하고 보호하는데 있다. 그런데, 그건 사실 EC2와 같이 계속 온라인으로 떠있는 서버의 경우이고, Lambda는 요청이 들어왔을때 Container가 떠서 처리하고, 처리가 완료되면 해당 Container가 다시 내려가는 방식이므로 그런 관리/보호 장치가 어쩌면 필요하지 않다.

 

그럼에도 불구하고, VPC를 적용했던 것은, 크게 두 가지 이유가 있었다.

  • 먼저, Lambda가 외부에 있는 써드파티 서버에 붙어서 통신을 해야하는데, 해당 써드파티 서버에서 방화벽 관리를 하고 있고, 그 방화벽에서 IP를 통해 들어오는 요청을 White list로 관리하고 있다면, VPC 이용해서 Lambda Container를 고정 IP로 묶어서 사용 경우가 있을 수 있다. (이 방법은 Lambda의 장점인 Scale-out을 포기한 극단적인 사례라고 볼 수 있지만, Cost를 아끼는것이 최대 목적이라면 적용 가능한 방법이라고 볼 수 있다.)

  • 보통 서비스 시스템을 구성할때 WAS를 DB에 연결하게 되는데, 여기서 WAS의 역할을 Lambda가 하고 있다면, Lambda를 DB에 연결하게 될 것이다. 그런데 DB는 보통 내부 서버에게만 열어둔다. DB는 서버 시스템에서 마지막까지 지켜야하는 가장 소중한 자산이므로, 외부에 노출되는 망을 이용하지 않는다. 다시 말해, 같은 VPC안에 있는 서버만 DB에 접속해서 RW 를 할 수 있도록 한다는 것이다. 그런데 Lambda에 VPC를 적용하지 않으면, 사실상 외부망에서 DB를 접속할수있게 열어두는 것이므로, DB를 보호하기 위해 VPC를 적용하는 것이다..

결과적으로 이런 부분 때문에, AWS에서도 VPC+ENI 이슈를 해결하려고 노력했고, 실질적인 결과도 있었다(아래 링크를 참고하자. 발표한 내용이 사실이라면, 엄청난 성능 향상을 만들어 냈다. 한국 리전에도 적용되었는지는 잘모르겠다.)

 

https://aws.amazon.com/ko/blogs/korea/announcing-improved-vpc-networking-for-aws-lambda-functions/

 

AWS Lambda 함수의 VPC 기능 개선 – 함수 구동 속도 향상 및 효율적 ENI 사용 | Amazon Web Services

AWS Lambda 기능이 Amazon VPC 네트워크에서 작동하는 방식을 크게 개선했습니다. 오늘부터 함수 구동 성능이 향상되고 탄력적 네트워크 인터페이스(Elastic Network Interfaces)를 효율적으로 사용 가능합니다. 이러한 개선 사항은 추가 비용 없이 모든 기존 및 새로운 VPC 기능에 적용됩니다. 모든 리전에 걸쳐 향후 몇 개월 동안 점차적으로 사용 가능해 질 것입니다.AWS Lambda는 2016 년 2 월에 처음으로 VPC를 [

aws.amazon.com

그러나 어쨌든 Lambda에 VPC를 적용하는 것이 Best practice인지는 생각해 볼 일이다. 가능하면, DB를 Lambda에 붙이지 않고 가볍게 쓰는게 좋지 않을까.

 

 

(VPC는 또 다른 방대한 주제이므로, VPC에 대한 더 자세한 이야기는 따로 다음에..)

 

3. Dwell Time

Lambda로 요청을 보내면, 요청이 바로 특정 컨테이너로 들어가는 것이 아니다. 요청은 Lambda Queue에 쌓이게되고, 그 Queue에서 하나씩 꺼내서 적당한 Container로 보내지는 것이다. 이때, Queue에서 요청을 꺼내 Container로 보내는 시간을 Dwell Time이라고 한다. Cold start가 발생한 시점을 AWS X-ray 통해서 분석해보면 (X-ray에 대해서도 다음 기회에..), 이 Dwell Time이 길어지면서 발생한 적도 심심찮게 있었다.

 

그럼 Dwell Time은 언제 길어질까?

  • 한 계정에서 동시에 띄울수있는 최대 Lambda Container 수(ConcurrentExecutions) 수는 제한되어 있다.

  • 만약 1000개가 그 제한량이라고 한다 가정해보자. 어느날 요청이 엄청나게 들어와서 Container가 동시에 뜨는 상황일때, 요청의 수에 따라 Container가 1개부터 1000개까지 선형적으로 증가하게 될까? 그렇지 않다.

  • Container가 Bulk로 증가할 수 있는 양은 계단적이다. 예를 들어, 1000개의 요청이 동시에 들어왔다면, 500개 정도 처리할 수 있는 Container가 먼저 Bulk로 뜨고, 시간이 좀 지난 후, 또 나머지 500개를 처리할 수 있는 Container들이 뜨는 방식이다.

  • 아마도, 하나의 인스턴스에 올라갈 수 있는 최대 Container 수에 따라, 특정 단위의 Container 수가 계단식으로 증가할 수 있는 것이 아닌가 추측해본다.

  • 하나의 인스턴스에서 모든 Container가 가득찼을때, 새로운 인스턴스를 생성시키고, 그곳에 Container를 띄우는데까지 시간이 걸릴 것이고, Queue에 들어가있는 요청은 그 시간을 기다리게 되면서 Cold start가 발생할 것으로 추측된다.

  • 혹은, 아까 언급한 것과 같이, 하나의 계정에는 Max Concurrent Executions 수가 정해져 있는데, 그것이 가득찰만큼 요청이 많이 들어와서, 먼저 들어간 요청이 처리될때 까지 Queue에서 기다리고 있을 수도 있을 것이다.

  • 보통 한 계정에는 하나의 온라인 서비스를 만들기 위해, 여러 종류의 Lambda를 만들어 놓는다. 예를 들어, 영화 예매 온라인 서비스를 만든다고 했을때, '영화 예매' 요청을 처리하는 Lambda와 '예매 취소' 요청을 처리하는 Lambda를 따로 둘 수 있다.

  • 이렇게 다양한 Lambda가 있을때, 하나의 Lambda에 너무 많은 요청이 들어가서(그것으로 인해 계정에 할당된 Concurrent Executions에 영향이 있을수도 있을만큼), 그것이 다른 Lambda에도 영향이 있으면 안되므로, 각 Lambda에서 생성될 수 있는 Container수를 제한할 수 있는 방법(= Reserved Concurrent Executions)도 있다. 그것을 설정된 상태에서 예약된 수 보다 많은 요청이 동시에 들어오면 Throttle이 발생한다.

 

해결 방법

그럼 이런 다양한 원인에 의해 발생할 수 있는 Cold start를 우리는 어떻게 해결할 수 있을까?

 

1. Lambda의 사양을 높인다.

Lambda의 사양을 올리는 방법은 해당 Lambda에 적용되는 메모리의 양을 올리는 것이다. 가장 낮은 메모리가 128MB이다. AWS에서 공식 발표한 것은 아니지만, 경험적(+업계 소문)으로는 메모리를 올리면, 인스턴스의 사양이 올라간다고 한다. 때문에 처리 속도 자체가 빨라질 수 있다고.. 확실한 것은 아니다. 그게 아니라 하더라도, 메모리를 꽤 쓰는 로직이 들어가있다면, 메모리가 부족해지면서 성능이 떨어지는 문제도 발생할 수 있을 것이다. 

 

그렇기 때문인지, 현업에서 Cold start문제가 생겼을 때, 메모리를 올리는 것으로 대응해서 해결된 것이 적지않게 있었다. 

단, 메모리를 올린다는 것은 비용이 증가하는 것을 의미한다.

 

Lambda의 과금 방식은 (메모리 별 가격) * (요청이 처리되는 시간) * (요청 수) 이므로, 메모리를 올리는 것은 최종 비용을 늘리는 것일 수 있지만, 메모리를 늘림으로 인해, 요청이 처리되는 시간이 줄어든다면, 반대로 최종 비용이 떨어질 수도 있는 일이다. 따라서, 비용 계산은 각자 상황에 맞게 계산기를 잘 두드려봐야한다.

 

2. Provisioned Concurrency를 사용한다.

아까도 말했듯이 Cold start는 결국 '꺼져있는 상태'인것이 문제이다. 그러면 미리 켜두면 되지 않을까. 다른 표현으로는 Warm start를 하자는 것이다. Cold start 문제는 AWS에서도 당연히 잘 인지하고있고, Warm start를 할 수 있도록 도와주는 Provisioned Concurrency 서비스도 나왔다. Cold start 문제가 상당부분 해결이 될 것이다. 단, (당연히) 비용이 발생한다.

 

https://www.pulumi.com/blog/aws-lambda-provisioned-concurrency-no-cold-starts/

 

Provisioned Concurrency: Avoiding Cold Starts in AWS Lambda

Using Pulumi to configure AWS Lambda provisioned concurrency

www.pulumi.com

https://aws.amazon.com/ko/blogs/korea/new-provisioned-concurrency-for-lambda-functions/

 

AWS Lambda 함수, Provisioned Concurrency를 통해 빠른 성능 제공 (서울 리전 포함) | Amazon Web Services

AWS Lambda가 출시되고 5년이 흘렀지만 여전히 팀은 더 쉽게 애플리케이션을 구축하고 실행할 수 있는 새로운 방법을 찾고 있습니다. 특히, 중요 애플리케이션이 서버리스로 이동하면서 애플리케이션의 성능을 제어하는 더 많은 기능이 필요해졌습니다. 오늘 출시되는 Provisioned Concurrency는 함수를 지속적으로 초기화하고 아주 빠르게 준비하여 두 자리 수 밀리초로 응답하는 기능입니다. 이 기능은 웹 및 모바일 백엔드, 지연 시간에 민감한 마이

aws.amazon.com

 

3. 자체적인 Warm start

Provisioned concurrency가 비용 때문에 부담스럽다면, 자체적으로 Warmer를 만들 수도 있을 것이다. CloudWatch Event의 스케쥴러를 이용해서 5분 단위로 요청을 보내게 설정을 한다든지, 배포 환경을 따로 만들어놨다면 그곳에 스케쥴러를 적용해서 할 수도 있을 것이다. 비용이 발생하지 않거나, 덜 발생하는 대신, 직접해야하기 때문에 귀찮을 수는 있다.

 

4. 가장 이상적인것은 일정량의 요청이 꾸준히 들어오는 것

경험적으로 이상적이라고 느껴졌던 방법은, 일정량의 요청이 꾸준히 들어오는 것이다. 그것이 많은 양이든 적은 양이든 꾸준히 일정량의 요청이 들어와서 그 요청을 처리할 수 있는 Container가 계속 떠있는 상황이라면 당연히 Cold start 문제가 최소화 된다. 사실 그렇게 사용하는 것은 Scale out 장점을 반감 시키는 것이기도 하지만, Lambda의 최대 장점인, 운영 비용은 줄일 수 있을 것이다. (물론 요청의 수준이 특정 threshold를 넘어서면, EC2를 운영하는 것보다 더 많은 비용이 발생하는 Cross 지점이 있다. 그때는 일반적으론 EC2로 갈아타는 것이 좋을 것이다*.)

 

* 당연하겠지만, 리소스 구성을 반드시, Lambda 혹은 EC2 둘 중의 하나로 고르지 않아도 된다. 오히려, 요청에 따라 다르게 처리될 수 있도록, 그 두 종류의 리소스를 함께 써서 Hybrid 형태의 아키텍쳐 구성이 Best practice에 가깝다. 

 

반응형

'AWS > Lambda' 카테고리의 다른 글

Lambda를 활용한 저비용 분산 캐시  (0) 2020.04.06
AWS Lambda Troubleshooting 3: Error handling  (0) 2020.03.08
AWS Lambda Troubleshooting 2: Connection  (0) 2020.03.07
Serverless, 서버리스란?  (0) 2020.02.26

댓글