본문 바로가기

Compute/Lambda

AWS Lambda X-ray 및 Insight(Serverless, MSA 모니터링)

서비스 구성

재미와 학습으로 시작했던 서버리스 MSA로 구성한 서비스가 어느새 2년이라는 시간이 지났다.

 

사용자도 꽤 늘어 기능을 추가하다 보니, 현재 40개가 좀 넘는 Lambda가 돌아가고 있다.

(비용은 월 $150 정도)

 

모든 것을 AWS에 위임하여 서비스 중이더라도 장애는 발생되어(특히 외부 API들) 서버리스 MSA 모니터링을 위한 X-Ray와 Lambda Insight에 대해 간략하게 포스팅 한다.

(규모가 작은 서비스지만 모니터링 체계는 크게 다르지 않을 듯 하여..)

 

기본적으로 CloudWatch를 통한 Lambda 모니터링은 아래와 같다.

CloudWatch Lambda

Invocations – 5 동안 함수가 호출된 람다 횟수

기간  함수 코드가 이벤트를 처리하는 데 소요하는 평균, 최소 및 최대 시간

오류 수 및 성공률(%)  오류 수 및 오류 없이 완료된 호출의 백분율

제한  동시성 한도로 인해 호출에 실패한 횟수

IteratorAge  스트림 이벤트 소스에서 Lambda 배치의 마지막 함수를 호출했을 때 해당 항목 시간

Async delivery failures(비동기 전송 실패) – Lambda가 대기열에 쓰려고 할 때 발생한 오류의 개수

Concurrent executions(동시 실행)  이벤트를 처리 중인 함수 인스턴스의 개수

 

위 내용으로는 서비스 가시성 확보, 디버깅, 비용 절감을 위한 모니터링이 부족하다.

 

Lambda의 비용은 호출 횟수 + 이벤트 처리 시간 + 사용한 메모리로 정해진다. 

메모리를 늘린다면 이벤트 처리 시간은 줄어들고, 메모리를 줄인다면 이벤트 처리 시간이 늘어날 수 있으니 유스케이스에 맞게 사용해야 비용을 절감할 수 있다.

 

비용 절감을 포함하여 Lambda X-Ray와 Insight를 사용한다면 1)가시성 확보, 2)디버깅, 3)비용 절감을 모니터링할 수 있다.

 

[X-Ray]

API를 Lambda 중심으로 개발하면 수십~수백개의 Lambda를 이용하게 된다. 이 경우 API에 대한 가시성을 잃게 된다. 따라서 X-Ray를 활용해서 API Gateway와 Lambda의 가시성을 확보하자.

X-Ray

 

API Gateway부터 Lambda 그리고 DynamoDB까지 API 경로 구성과 레이턴시 그리고 Lambda 내/외부 요청 처리 정보를 한 눈에 확인할 수 있다.

Lambda X-Ray

Lambda의 제약으로 인해 Lambda Invoke를 사용하거나 혹은 외부 API를 사용한다면 API 문제를 찾는 건 매우 고달프다. 

 

이 경우 X-Ray를 통해 분산 Tracing 정보를 확인하여 디버깅이 용이하다. Lambda Function에서 내/외부로 호출되는 API 정보 레이턴시 및 상태코드 등 정보를 확인할 수 있다.  

 

추가로 X-Ray Insights 라는 기능도 존재하는데, X-Ray 값에 필터를 걸고 알람을 받을 수도 있다.

아래 그림은 해당 Lambda Function에서 9.9% 요청 실패가 발생되고 있는 것을 보여주며, 알럿은 SNS와 연동도 가능하다.

X-Ray Insight

 

다만 X-Ray의 경우 샘플링 된 데이터이기 때문에 CloudWatch의 Logs의 Lambda Stdout 로그 모니터링은 우선적으로 구성해야 한다.

 

X-Ray 구성은 Lambda에서 온오프가 손쉽게 가능하며 Lambda 코드에 X-Ray 관련 모듈과 호출 몇 줄만 추가해주면 된다.

https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/services-xray.html

 

AWS Lambda와 함께 AWS X-Ray 사용 - AWS Lambda

Lambda에서는 X-Ray SDK를 사용하여 Invocation 하위 세그먼트를 다운스트림 호출, 주석 및 메타데이터에 대한 추가 하위 세그먼트로 확장할 수 있습니다. 함수 세그먼트에 직접 액세스하거나 핸들러

docs.aws.amazon.com

 

비용은 시간당 2,000 건의 요청을 처리할 경우 10% 샘플링 비율로 $ 0.24로 매우 저렴하다. (샘플링을 정할 수 있음)

 

온오프가 손쉽게 가능하기 때문에 필요에 따라 사용 여부도 정할 수 있다.

 

 

[Lambda Insight]

Lambda Insight의 경우 CloudWatch로 부족한 성능 지표를 추가로 확인할 수 있다.

CloudWatch 기본 메트릭의 경우 람다 실행 횟수와 사용 시간은 확인할 수 있지만, Memory, CPU, Network와 같은 성능 지표는 확인할 수 없다.

특히 실제 Lambda의 비용은 앞서 말했듯이 Invocation와 Duration으로 정해지는데, 메모리 관련 지표는 확인할 수 없어 비용을 예상하는데 어려움이 있다. Lambda의 비용은 예상이 어렵기 때문에  Lambda Insight를 통해 예상 비용을 모니터링 할 것을 권장한다. 

Lambda Insight

비용 절감을 위해 Lambda 로그의 메모리 사용률을 살펴볼 필요가 없다. 

CloudWatch Lambda Logs

 

Memory Usage를 통해 Lambda 메모리를 최적화 하고 비용을 절감 하자.

Stdout 로그와 별개로 인프라 레벨을 로깅한다. 따라서 요청 단위 로그들을 Logs query를 통해 분석이 가능하다.

Lambda performance logs

Lambda Insight 설정은 매우 쉽다. Lambda Monitoring Conf에서 온오프만 해주면 된다.

Lambda Insight

비용 또한 저렴한데, 매월 100만 건 호출, Log 1.1KB 기준으로 월 $2.92 정도 발생된다.

 

[Logs Insights]

또한 Logs Insights를 통해 아래 쿼리를 실행하면 Lambda 실행 성능을 확인할 수 있다. 

filter @type = “REPORT” 
| stats 
 count(@type) as countInvocations , 
 count(@initDuration) as countColdStarts ,     
(count(@initDuration)/count(@type))*100 as percentageColdStarts,
 max(@initDuration) as maxColdStartTime,
 avg(@initDuration) as avgerageColdStartTime,
 avg(@duration) as averageDuration,
 max(@duration) as maxDuration,
 min(@duration) as minDuration,
 avg(@maxMemoryUsed) as averageMemoryUsed,
 max(@memorySize) as memoryAllocated,  (avg(@maxMemoryUsed)/max(@memorySize))*100 as percentageMemoryUsed 
by bin(1h) as timeFrame

 

런타임은 Python3으로 콜드스타트가 약 5~10% 정도 발생되며 평균 900ms 정도가 되는 것을 알 수 있다.

 

이번에는 런타임이 Node.js 11인 Lambda Function의 콜드스타트를 확인해봤다. 람다 실행 횟수가 적어 콜드스타트 발생 비율이 50%에 육박하는 것을 알 수 있다. 그러나 콜드스타트 시간은 600ms로 Python보단 더 나은 성능을 보여준다.

 

이 서비스의 경우 1000ms는 이해할 수 있는 수치로 서버리스로 사용 가능했다.

 

Log Insights와 별개로 ColdStart에 대해 얘기해보자면, 해외 사례의 경우 중~대규모 서비스의 경우 1% 이하의 ColdStart 비율을 유지하고 있다는 포스팅을 확인한 적이 있다.

 

1% 이하의 요청이 500ms라면 어차피 정적페이지는 CDN을 통해 서빙되기 때문에 일반적인 웹서비스에서 용인될 수 있는 수치라고 생각된다. 

 

그럼 X-Ray와 Lambd Insight 그리고 Logs Insihgts를 활용한 서버리스 MSA 모니터링에 대해 알아봤다.

 

두 서비스 사용 시 작은 비용이 추가되지만 활용한 것을 권장한다.

 

특히 복잡하게 꼬인 MSA 환경에서 Lambda Invoke나 외부 API를 사용할 경우에는 필수가 아닐까 생각된다.