Managed Level - Console
- 구성
- 일반구성: 기본 설정 관련
- 메모리: 메모리에 비례하는 CPU가 함수에 할당/Compute Optimizer 옵트인 가능
- 임시 스토리지: /tmp 디렉터리, 최대 10GB까지 대기 시간이 짧은 안전한 임시 파일 시스템 액세스
- 제한 시간, 실행 역할
- 트리거
- 소스: Alexa, Apache Kafka, API Gateway, ALB, CW Logs, CodeCommit, Cognito Sync Trigger, DynamoDB, EventBridge, Kinesis, MQ, MSK, S3, SNS , SQS 등..
- 권한
- Lambda 실행 역할 / 태그 기반 액세스 제어 / 리소스 기반 정책 등..
- 대상
- 소스가 비동기식 호출: SNS, SQS, Lambda, EventBridge
- 소스가 스트림 호출: Kinesis, DynamoDB
- 함수 URL: Lambda에 고유한 HTTP(S) 엔드포인트 추가
- 언제 사용할까?
- 환경 변수: key-value
- 태그
- VPC: (default로 퍼블릭으로 액세스 가능한 리소스로 deploy)
- 'Lambda VPC → 계정 VPC' 로의 연결 제공
- 각 서브넷의 Hyperplane ENI에 함수를 할당
- Lambda에서 생성 및 관리하는 관리형 네트워크 리소스
- Lambda VPC에서 계정 VPC로 NAT 기능 제공(처음 생성되거나 VPC 설정 업데이트 시 생성)
- https://aws.amazon.com/ko/blogs/compute/announcing-improved-vpc-networking-for-aws-lambda-functions/
- https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/foundation-networking.html#foundation-nw-eni
- 모니터링 및 운영 도구: CW, X-Ray, CW Lambda Insights
- 동시성: 함수에 대한 최대 동시 실행 횟수 설정
- 비동기식 호출: 처리되지 않은 이벤트 처리
- lambda가 자체적으로 재시도를 처리(최대 2번)
- 그래도 스로틀 발생, 오류 반환 시 대기열에 보관(최대 6시간)
- 보관 이후에 삭제하는데 이를 SQS나 SNS로 전송(배달 못한 편지 대기열)
- 코드 서명: 신뢰할 수 있는 코드만 함수에서 실행되도록
- 활성화 하면 모든 코드 배포를 검사하고 코드 패키지가 신뢰할 수 있는 소스에 의해 서명되었는지 확인
- AWS Signer를 사용?
- 데이터베이스 프록시
- 데이터베이스 연결 풀 관리
- 파일시스템: EFS 연결
- 상태 머신: Step Functions
- 일반구성: 기본 설정 관련
- 별칭: 함수 버전을 매핑
- 버전
Code Level(Python 기준)
- Lambda Handler Function:
- Lambda 콘솔의 기본 이름: lambda_function.lambda_handler
- lambda_handler: 함수 이름(핸들러 이름 바꾸고 싶으면 여길 바꾸면 됨)
- lambda_function: 핸들러 코드가 저장된 파일
- Lambda 콘솔의 기본 이름: lambda_function.lambda_handler
##Global Scope
def lambda_handler(event, context):
## business logic here
return response
- event:
- Lambda가 Invoke 될 때 다른 서비스에서 이벤트 (혹은 데이터) 를 전달 받는다.
- 어떤 서비스로부터 Invoke 되었는지에 따라 event의 구조가 달라진다.
- Invoke 방식에는 Event / RequestResponse 로 나뉨.
- RequestResponse: API Gateway → Lambda
- Event: Response를 바라진 않음. 이벤트 전달이 목적!(Asynchronous)
- Lambda가 Event 방식으로 호출된 경우, 실행 결과로 response 값이 있으면 이 데이터는 Invoke를 요청한 클라이언트에게 다시 전달될까? → NO!
import os
def lambda_handler(event, context):
print('## ENVIRONMENT VARIABLES')
print(os.environ)
print('## EVENT')
print(event)
여기서 착각했던게 있는데...
이 테스트 이벤트의 경우에는 테스트를 위한거고 실제적으론 함수를 invoke 하는 서비스의 이벤트를 받는 것!
테스트 용으로 람다 함수가 잘 작동하는지 확인하고 해당 서비스와 트리거를 하던 연결을 하던 해서 사용하면 될듯..
(아마 서비스마다 들어오는 이벤트 형식이 지정되어있는 것 같다... 테스트 이벤트 템플릿 보면 겁네 많음)
- context:
- Lambda의 Runtime 정보를 핸들러에게 제공
- function_name, function_version, invoked_function_arn, memory_limit_in_mb, aws_request_id, log_group_name 등..(로깅 등의 용도로 사용할 수 있는 메타데이터)
- 오랫동안 실행되는 Lambda의 경우 get_remaining_time_in_millis() 가 쓸모 있을지도..
- Lambda의 Runtime 정보를 핸들러에게 제공
import time
def lambda_handler(event, context):
print("Lambda function ARN:", context.invoked_function_arn)
print("CloudWatch log stream name:", context.log_stream_name)
print("CloudWatch log group name:", context.log_group_name)
print("Lambda Request ID:", context.aws_request_id)
print("Lambda function memory limits in MB:", context.memory_limit_in_mb)
# We have added a 1 second delay so you can see the time remaining in get_remaining_time_in_millis.
time.sleep(1)
print("Lambda time remaining in MS:", context.get_remaining_time_in_millis())
- Global Scope:
- 핸들러 바깥의 영역으로 init(cold start 시)에만 실행되는 부분
- Worker 노드가 종료되지 않으면 메모리에 남아있음(캐시처럼 사용할 수 있는 트릭)
- 모놀리식 구조로 코드 작성했을 때 RDS 커넥션 추가해도 괜찮다..
- but, 함수를 기능별로 나눴을 경우 RDS 커넥션 해두고 끊지 않으면 DB 쪽에서 max_connection에 걸릴 수도.. → Global Scope에 연결하는 것보다 사용할 때마다 연결 하고 끊는게 좋다
- init은 했는데 terminate을 따로 안해주니까 이런 경우에 시스템이 어떻게 동작할까에 대한 고민을 해라!
- 로깅:
- 자동으로 Lambda 함수를 모니터링 하고 함수 지표를 CloudWatch로 보냄
- 함수를 삭제해도 로그 그룹이 자동으로 삭제되지 않음
- 로그 그룹을 삭제 | 로그가 자동으로 삭제되는 보존 기간을 구성
- 오류:
- Lambda invoke → 호출 요청 수신 → 검증 과정
- 실행 역할 권한 검증 → 이벤트 문서가 유효한 JSON 문서인지 확인 → 파라미터 값 검사
- 요청이 검증을 통과하면 Lambda가 함수 인스턴스로 요청을 보냄
- Lambda 런타임 환경의 경우 이벤트 문서를 객체로 변환한 후 함수 핸들러에 전달
- 오류 발생 반환: 예외 유형(오류의 원인), 메시지 및 HTTP 상태 코드
- 2XX: Lambda 런타임 또는 함수 오류(Lambda가 요청은 수락한 상태)
- 4XX: 일반적으로 요청에 문제가 있음(결국 lambda invoke 하는 서비스의 문제)
- 5XX: Lambda 관련 문제나 구성 또는 리소스 관련 문제
- https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/API_Invoke.html#API_Invoke_Errors
- Lambda invoke → 호출 요청 수신 → 검증 과정
Infra Level
- Lambda Invoke:
- Invocation Type: Invoke 시 어떤 방식으로 실행할지 결정 가능
- Event: Asynchronous 방식
- Lambda 함수가 성공했는지 여부를 알 수 없음
- Invoke Event를 잘 수신했다(Accept의 의미): "StatusCode: 2XX"
- → 코드가 잘 동작했는지 확인할 수 있는 방법이 없어 DLQ가 필수다!
- S3, SNS, EventBridge (CloudWatch Events) 등
- RequestResponse(default): Synchronous 방식
- "StatusCode: 200" : 성공적으로 잘 수행했다
- Kinesis, DynamoDB Streams, SQS, ALB, API Gateway
- DryRun: 파라미터 및 권한을 검사해서 실행 가능한지에 대한 체크(실제 Invoke는 아님)
- Event: Asynchronous 방식
- Asynchronous invocation:
- event를 queue(SQS)에 넣는다 : Lambda 내부적으로 queue를 가지고 있음
- lambda 함수가 적절한 타이밍에 큐에 쌓인 이벤트를 처리를 못하면 이벤트가 손실 될 수 있음
- 따라서, 반드시 수행되어야하는 태스크는 별도의 고객 소유 SQS를 통해 Invoke 시켜야함
- lambda + sqs + lambda 의 구조가 best practice
- 하나의 이벤트를 중복처리하는 경우도 존재:
- Event-driven 방식으로 동작하는 함수는 반드시 Idempotency(멱등성)를 고려하여 작성
- 함수 실패의 경우 Dead Letter Queue를 통해 알림 받기 가능
- event를 queue(SQS)에 넣는다 : Lambda 내부적으로 queue를 가지고 있음
- Invocation Type에 따른 Lambda 트러블 슈팅:
- 대량의 데이터를 SQS에 넣었다. Lambda를 Invoke 시키는 시나리오에서 Lambda 실패, 데이터는 어디로 갈까? Lambda 함수는 기다리고 있으면 다시 또 실행될까?
- SQS는 RequestResponse(Synchronous) 방식: retry를 몇 번 시도 후 그래도 실패하면 실패 이벤트 처리로 넘어감. → 실패 시 고객이 SQS의 처리상태를 통해 직접 알 수 있음
- 대량의 파일을 S3에 업로드해서 Lambda를 Invoke 시키는 시나리오에서 실패했다, 이벤트는 어디로 갈까? Lambda 함수는 기다리고 있으면 다시 또 실행될까?
- S3 는 Event(Asynchronous) 방식: retry 몇 번 시도 후 실패시 이벤트 손실이 생길 수 있음 → DLQ를 지정하는 방법밖에 없음(Lambda 내부 문제)
- 대량의 데이터를 SQS에 넣었다. Lambda를 Invoke 시키는 시나리오에서 Lambda 실패, 데이터는 어디로 갈까? Lambda 함수는 기다리고 있으면 다시 또 실행될까?
- Invocation Type: Invoke 시 어떤 방식으로 실행할지 결정 가능
- 컴포넌트들이 달성하고자 하는 목표?
- Load Balancing
- Scaling Up and Down
- Handling Failures
- Predictable Low Latency
- Security Isolation
- Managing Utilization
- ...
- Synchronous Invoke:
- Front End Invoke: IAM Policy, Role 확인(authentication) / Concurrency 더 수행할 수 있는지 / 메타데이터 확인 등
- Counting Service: concurrency limit을 넘지 않는지
- 근데 concurrency를 초과해서 실행될 수 있음 → limit에 도달하자마자 막으면 고객들이 maximum concurrency를 누릴 수 없음
- Worker Manager: Front End와 함께 AutoScaling
- Worker: sandbox 구성(해당 cpu, memory limit 설정, 고객 코드, runtime, 실행환경 초기화 등..)
- Firecracker: 실제로 코드가 동작하는 과정
- Lambda 내부 요소의 Worker 위에서 실행되는 가상화 기술(원래는 EC2 인스턴스 였음)
- (https://aws.amazon.com/ko/blogs/korea/firecracker-lightweight-virtualization-for-serverless-computing/)
- Firecracker: 실제로 코드가 동작하는 과정
- Placement Service
(Alb(우리한텐 안보임)가 받아 Front End로 Front End가 Worker Mgr에게 sandbox 가져오라고 명령
sandbox 있으면 Worker 가져오고,
없으면 Placement 에게 sandbox 만들 수 있는 Worker 달라고 요청, Worker를 Worker Mgr에게 전달, Worker Mgr가 sandbox에 init command 날리고 Front End에게 전달 Front End가 코드 invoke 명령어 내리고
결과가 Alb를 통해 나간다.)
→ Warm Sandbox 존재: Claim Worker 과정과, init 과정이 필요 없음! (빠르게 invoke 가능) ⇒ Warm Start
→ Warm Sandbox 없음: Claim Worker 과정과 init 과정 필요 (지연이 있음) ⇒ Cold Start
- Asynchronous Invoke:
- Poller: 큐에 저장된 이벤트 꺼내와서 처리되는 과정을 전부 관리
- State Manager/Stream Tracker: Poller 서비스를 스케일링, 이벤트 소스 스트림을 관리하거나 등..
- Leasing Service: 어떤 Poller 서비스가 어떤 이벤트를 담당할건지
(synchronous와 Front End까진 같다, Font End에서 Worker Mgr로 가면 sync / SQS로 가면 async
Front End에서 SQS로 넣게 되면 함수 결과값으로 StatusCode: 2XX 던져주고 끝.
SQS에서 Poller가 이벤트 가져와야하는데 어떤 Poller가 어떤 이벤트 담당할지 결정하는게 Leasing Service(그림엔 없음)
SQS에서 메시지를 가져온 Poller가 새로운 클라이언트가 되어서 Front End를 호출할 때 RequestResponse 방식으로 호출 - 이 뒤로는 sync와 똑같이 이루어진다.)
'Cloud > AWS' 카테고리의 다른 글
[AWS] Serverless Service - Lambda 편 (3) (0) | 2022.11.06 |
---|---|
[AWS] Serverless Service - Lambda 편 (2) (0) | 2022.11.05 |
[AWS] API Gateway - Websocket API (0) | 2022.11.01 |
[AWS] Lambda Warm Start / Cold Start (0) | 2022.10.28 |
[AWS] Fan-Out 시나리오 -1(easy) (0) | 2022.10.11 |