본문 바로가기

Cloud/AWS(Amazon Web Service)

AWS Lambda를 사용한 서버리스 아키텍처(LambdaServerless Architectures with AWS Lambda)

반응형

소개-서버리스 란?

 


AWS Lambda— 기본 사항

 

 


AWS Lambda— 심층 다이빙

Lambda 함수 코드

 

Lambda 함수 이벤트 소스

 

 

Lambda 함수 구성

Lambda 함수 코드를 작성하고 패키징 한 후 함수를 트리거 할 이벤트 소스를 선택하는 것 외에도 Lambda 내에서 코드가 실행되는 방법을 정의하는 다양한 구성 옵션이 있습니다.


함수 메모리

실행중인 Lambda 함수에 할당 된 리소스를 정의하기 위해 함수 리소스(메모리/RAM)를 늘리거나 줄이는 단일 다이얼이 제공됩니다. Lambda 함수에 128MB의 RAM을 최대 1.5GB까지 할당 할 수 있습니다. 이렇게하면 실행 중 함수 코드에 사용 가능한 메모리 양이 결정될뿐만 아니라 동일한 다이얼이 함수에 사용 가능한 CPU 및 네트워크 리소스에도 영향을줍니다.


Lambda 함수의 가격과 성능을 최적화 할 때는 적절한 메모리 할당을 선택하는 것이 매우 중요합니다. 성능 최적화에 대한 자세한 내용은이 백서 뒷부분의 모범 사례를 검토하십시오.

버전 및 별칭

Lambda 함수를 참조하거나 이전에 배포 한 코드로 되돌려 야 할 경우가 있습니다. Lambda를 사용하면 AWS Lambda 함수의 버전을 지정할 수 있습니다. 각각의 모든 Lambda 함수에는 기본 버전 $LATEST가 내장되어 있습니다. $LATEST 버전을 통해 Lambda 함수에 업로드 된 최신 코드를 처리 할 수 ​​있습니다. 당신은 $LATEST을 참조하여 코드의 스냅 샷을 가질 수 있고, PublishVersion API를 통해 번호가 매겨진 버전을 만들 수 있습니다. 또한 UpdateFunctionCode API를 통해 함수 코드를 업데이트할 때,  선택적 부울 매개 변수 publish가 있다. 요청에서 publish : true를 설정하면 Lambda는 마지막으로 게시 된 버전에서 증가 된 새 Lambda 함수 버전을 만듭니다.


언제든지 Lambda 함수의 각 버전을 독립적으로 호출 할 수 있습니다. 각 버전에는 다음과 같이 자체 Amazon 리소스 이름 (ARN)이 있습니다.

Invoke API를 호출 하거나 Lambda 함수의 이벤트 소스를 작성할 때 실행할 특정 버전의 Lambda 함수를 지정할 수도 있습니다. 버전 번호를 제공하지 않거나 포함되지 않은 ARN을 사용하는 경우 버전 번호 $LATEST가 기본적으로 호출됩니다.

Lambda 함수 컨테이너는 함수의 특정 버전에 따라 다릅니다. 예를 들어 Lambda 런타임 환경에서 함수 버전 5에 대해 이미 여러 함수 컨테이너가 배치되어 사용 가능한 경우 동일한 함수의 버전 6은 기존 버전 5 컨테이너 위에서 실행할 수 없습니다. 컨테이너 세트는 각 함수 버전마다 설치 및 관리됩니다.

 

버전 번호로 Lambda 함수를 호출하면 테스트 및 운영 활동 중에 유용 할 수 있습니다. 그러나 실제 응용 프로그램 트래픽에 대해 특정 버전 번호로 Lambda 함수를 트리거하지 않는 것이 좋습니다. 그렇게하려면 코드를 업데이트 할 때마다 Lambda 함수를 호출하는 모든 트리거와 클라이언트를 업데이트하여 새 함수 버전을 가리켜 야합니다. 대신 Lambda 별칭을 사용해야합니다. 함수 별명을 사용하면 이벤트 소스를 호출하고 특정 Lambda 함수 버전을 가리킬 수 있습니다.

 

그러나 언제든지 해당 별칭이 참조하는 버전을 업데이트 할 수 있습니다. 예를 들어, 별칭 라이브를 통해 버전 번호 5를 호출하는 이벤트 소스 및 클라이언트는 버전 별명 6을 가리 키도록 라이브 별명을 업데이트하자마자 함수의 버전 번호 6으로 축소 될 수 있습니다. 함수 버전 번호를 참조 할 때와 유사하게 ARN 내에서 참조될 수 있습니다:

다음은 Lambda 별칭에 대한 몇 가지 제안과 사용 방법입니다.

 

  • live / prod / active – 프로덕션이 트리거하거나 클라이언트가 통합하는 Lambda 함수 버전을 나타낼 수 있습니다.
  • blue / green – 별명을 사용하여 blue / green 배포 패턴을 사용합니다.
  • 디버그 – 응용 프로그램을 디버깅하기 위해 테스트 스택을 만든 경우보다 심층적 인 분석을 수행해야 할 때 이와 같은 별칭과 통합 될 수 있습니다.

함수 별명 사용을위한 문서화 된 전략을 작성하면 정교한 서버리스 배치 및 운영 방법을 사용할 수 있습니다.

 

 

IAM 역할

AWS Identity and Access Management (IAM)는 AWS 서비스 및 API와의 상호 작용 권한을 정의하는 IAM 정책 을 생성하는 기능을 제공합니다. 정책은 IAM 역할과 연결될 수 있습니다 . 특정 역할에 대해 생성 된 모든 액세스 키 ID 및 비밀 액세스 키는 해당 역할에 연결된 정책에 정의 된 작업을 수행 할 권한이 있습니다.

 

Lambda와 관련 하여 각 Lambda 함수에 IAM 역할 ( 실행 역할 이라고 함 )을 할당합니다. 해당 역할에 연결된 IAM 정책은 기능 코드가 상호 작용할 권한이있는 AWS 서비스 API를 정의합니다. 두 가지 이점이 있습니다.

 

소스 코드는 AWS 자격 증명 관리 또는 로테이션을 수행하여 AWS API와 상호 작용할 필요가 없습니다. AWS SDK와 기본 자격 증명 공급자를 사용하면 함수에 할당 된 실행 역할과 관련된 임시 자격 증명을 사용하여 Lambda 함수가 자동으로 생성됩니다.

소스 코드는 자체 보안 상태와 분리되어 있습니다. 개발자가 Lambda 함수 코드를 변경하여 함수에 액세스 할 수없는 서비스와 통합하려고하면 함수에 할당 된 IAM 역할로 인해 해당 통합이 실패합니다. (실행 역할과 별도의 IAM 자격 증명을 사용하지 않은 경우 정적 코드 분석 도구를 사용하여 소스 코드에 AWS 자격 증명이 없는지 확인해야합니다).
각 Lambda 함수에 특정, 개별 및 최소 권한 IAM 역할을 할당하는 것이 중요합니다. 이 전략은 다른 Lambda 함수의 인증 범위를 늘리지 않고도 각 Lambda 함수가 독립적으로 발전 할 수 있도록합니다.

 


람다 함수 권한

permissions라는 개념을 통해 Lambda 함수를 호출 할 수있는 푸시 모델 이벤트 소스를 정의 할 수 있습니다. 권한이 있으면 함수를 호출 할 수있는 AWS 리소스 이름 (ARN)을 나열 하는 함수 정책을 선언 합니다.

풀 모델 이벤트 소스(예 : Kinesis 스트림DynamoDB 스트림)의 경우, 람다 기능에 할당된 IAM 실행 역할이 적절한 작업을 허용하는지 확인해야 한다. 필요한 권한을 관리하지 않으려는 경우 AWS는 각 풀 기반 이벤트 소스와 관련된 관리되는 IAM 역할 세트를 제공합니다. 그러나 최소 권한 IAM 정책을 보장하려면 리소스 별 정책으로 고유 한 IAM 역할을 생성하여 원하는 이벤트 소스에만 액세스 할 수 있도록해야합니다.

 

 

네트워크 구성

Lambda 함수 실행 은 AWS Lambda 서비스 API의 일부인 Invoke API를 사용하여 수행됩니다 . 따라서 관리 할 기능에 대한 직접 인바운드 네트워크 액세스가 없습니다. 그러나 함수 코드는 외부 종속성 (내부 또는 공개 호스팅 웹 서비스, AWS 서비스, 데이터베이스 등)과 통합해야 할 수도 있습니다. Lambda 함수에는 아웃 바운드 네트워크 연결을위한 두 가지 광범위한 옵션이 있습니다.

 

  • 기본값 – Lambda 함수는 Lambda가 관리하는 VPC(Virtual Private Cloud) 내부에서 통신합니다. 인터넷에 연결할 수는 있지만 자신의 VPC 내에서 실행되는 개인적으로 배포 된 리소스에는 연결할 수 없습니다.
  • VPC – Lambda 함수는 VPC 내에서 프로비저닝 된 ENI(Elastic Network Interface)와 자신의 계정 내에서 선택한 서브넷을 통해 통신 합니다. 이러한 ENI에는 보안 그룹이 할당 될 수 있으며 트래픽은 해당 ENI가있는 서브넷의 라우팅 테이블을 기반으로 라우팅됩니다 (EC2 인스턴스가 동일한 서브넷에 배치 된 것과 동일).

Lambda 기능에 개인 배포 리소스에 대한 연결이 필요하지 않은 경우 기본 네트워킹 옵션을 선택하는 것이 좋습니다. VPC 옵션을 선택하려면 다음을 관리해야합니다.

 

  • 고 가용성을 위해 여러 가용 영역이 사용되고 있는지 확인하기 위해 적절한 서브넷을 선택하십시오.
  • 용량을 관리하기 위해 각 서브넷에 적절한 수의 IP 주소 할당
  • Lambda 기능이 필요한 연결 및 보안을 갖출 수 있도록 VPC 네트워크 설계를 구현합니다.
  • Lambda 함수 호출 패턴이 새로운 ENI를 제 시간에 생성해야하는 경우 Lambda 콜드 스타트 ​​시간이 증가합니다. (ENI 제작에는 오늘 몇 초가 걸릴 수 있습니다.)

그러나 사용 사례에 개인 연결이 필요한 경우 Lambda와 함께 VPC 옵션을 사용하십시오.

 

환경 변수
SDLC(Software Development Life Cycle) 모범 사례에 따르면 개발자는 코드와 구성을 분리해야합니다. Lambda와 함께 환경 변수를 사용하여 이를 달성 할 수 있습니다. Lambda 함수의 환경 변수를 사용하면 코드를 변경하지 않고도 데이터를 함수 코드 및 라이브러리에 동적으로 전달할 수 있습니다. 환경 변수는 함수 구성의 일부로 작성하고 수정하는 키-값 쌍입니다. 기본적으로 이러한 변수는 유휴 상태로 암호화됩니다. Lambda 함수 환경 변수로 저장 될 민감한 정보의 경우 암호화 된 암호문을 변수 값으로 저장하여 함수를 생성하기 전에 AWS KMS(AWS Key Management Service)를 사용하여 해당 값을 암호화하는 것이 좋습니다. 그런 다음 Lambda 함수가 실행시 메모리에서 해당 변수를 해독하게 하십시오.


다음은 환경 변수 사용을 결정하는 방법에 대한 몇 가지 예입니다.

  • 로그 설정 (FATAL, ERROR, INFO, DEBUG 등)
  • 종속성 및/또는 데이터베이스 연결 문자열 및 자격 증명
  • 기능 플래그 및 토글

Lambda 함수의 각 버전은 자체 환경 변수 값을 가질 수 있습니다. 그러나 번호가 지정된 Lambda 함수 버전에 대한 값이 설정되면 변경할 수 없습니다. Lambda 함수 환경 변수를 변경하기 위해 $LATEST 버전으로 변경 한 다음 새 환경 변수 값이 포함 된 새 버전을 게시 할 수 있습니다. 이를 통해 이전 버전의 함수와 관련된 환경 변수 값을 항상 추적 할 수 있습니다. 롤백 절차 중에 또는 응용 프로그램의 과거 상태를 심사 할 때 종종 중요합니다.

 

데드 레터 큐

서버리스 환경에서도 예외가 발생할 수 있습니다. (예를 들어, Lambda 이벤트를 구문 분석 할 수 없는 새 함수 코드를 업로드했거나 AWS 내에 함수가 호출되지 못하게하는 작동 가능한 이벤트가있을 수 있습니다.) 비동기 이벤트 소스(이벤트 InvocationType)에서,  AWS는 함수 호출을 담당하는 클라이언트 소프트웨어를 소유합니다. AWS는 호출이 성공하거나 호출이 발생하지 않은 경우 동기적으로 알리는 기능이 없습니다. 이 모델에서 함수를 호출하려고 할 때 예외가 발생하면 재시도 간의 백 오프와 함께 호출이 두 번 더 시도됩니다. 세 번째 시도 후, 이벤트는 버려지거나 함수에 대해 구성한 경우 데드 레터 큐에 놓입니다.

 

데드 레터 큐는 모든 실패한 호출 이벤트의 대상으로 지정한 SNS 주제 또는 SQS Queue입니다. 실패 이벤트가 발생하면 데드 레터 큐를 사용하면 이벤트 중에 처리에 실패한 메시지 만 보존 할 수 있습니다. 함수가 다시 호출되면 데드 레터 큐에서 실패한 이벤트를 대상으로 다시 처리 할 수 ​​있습니다. 데드 레터 큐에 대한 함수 호출 시도 재 처리 / 재시도 메커니즘은 사용자의 몫입니다. 데드 레터 큐에 대한 자세한 내용 은이 자습서를 참조하십시오. 애플리케이션에서 데드 레터 큐를 사용해야하는 경우 실행이 지연 되더라도 Lambda 함수의 모든 호출이 결국 완료 되는 것이 중요합니다 .


타임아웃

타임아웃이 리턴되기 전에 단일 함수 실행이 완료 될 수 있는 최대 시간을 지정할 수 있습니다. Lambda 함수의 최대 타임아웃은 게시 시점에서 300초입니다. 즉, Lambda 함수를 한 번만 호출하면 300초 이상 실행할 수 없습니다. Lambda 함수의 시간 초과를 항상 최대로 설정해서는 안됩니다. 애플리케이션이 빨리 실패해야하는 경우가 많이 있습니다. Lambda 함수는 실행 시간을 기준으로 100ms 단위로 청구되기 때문에 함수에 대한 시간 초과를 피하면 함수가 단순히 시간 초과를 기다리는 동안 청구되지 않을 수 있습니다(아마 외부 종속성을 사용할 수없는 경우 실수로 무한 루프를 프로그래밍했거나 다른 유사한 시나리오일 수 있다).

 

또한 실행이 완료되거나 Lambda 함수에 대한 시간 초과가 발생하고 응답이 반환되면 모든 실행이 중지됩니다. 여기에는 Lambda 함수가 실행 중에 생성되었을 수있는 백그라운드 프로세스, 하위 프로세스 또는 비동기 프로세스가 포함됩니다. 따라서 중요한 활동에 백그라운드 또는 비동기 프로세스에 의존해서는 안됩니다. 코드는 시간 초과 또는 함수 응답을 반환하기 전에 해당 활동이 완료되었는지 확인해야합니다.


 

서버리스 모범 사례

이제 Lambda 기반 서버리스 애플리케이션의 구성 요소를 다루었으므로 권장 모범 사례를 살펴 보겠습니다. 서버리스 아키텍처에도 적용되는 많은 SDLC(Software Development Life Cycle) 및 서버 기반 아키텍처 모범 사례가 있습니다.(단일 장애 지점 제거, 배포 전 변경 사항 테스트, 중요한 데이터 암호화 등)

그러나 서버리스 아키텍처에 대한 모범 사례를 달성하는 것은 운영 모델이 어떻게 다른지에 따라 또 다른 작업이 될 수 있습니다. 인프라의 운영 체제 또는 하위 수준 구성 요소에 액세스하거나 이에 대한 우려가 없습니다. 이로 인해 사용자 자신의 애플리케이션 코드 / 아키텍처, 개발 프로세스 및 애플리케이션에서 활용하는 AWS 서비스의 기능에 중점을 두어 모범 사례를 따를 수 있습니다.

먼저 AWS Well-Architected Framework에 따라 서버리스 아키텍처를 설계하기위한 모범 사례를 검토합니다. 그런 다음 서버리스 애플리케이션을 구축 할 때 개발 프로세스에 대한 모범 사례와 권장 사항을 다룹니다.

 

서버리스 아키텍처 모범 사례

AWS Well-Architected Framework는 작업량을 우리의 모범 사례와 비교하고 기능적 요구 사항에 집중할 수 있도록 안정적이고 효율적인 시스템을 생산하기 위한 지침을 얻는 전략을 포함합니다. 보안, 신뢰성, 성능 효율성, 비용 최적화, 운영 우수성 등 5대 축을 기반으로 한다. 프레임워크의 많은 지침은 서버리스 애플리케이션에 적용된다. 그러나 서버리스 아키텍처에 고유한 구체적인 구현 단계나 패턴이 있다. 다음 섹션에서는 각 Well-Architectured 기둥에 대해 서버리스 권장 사항을 다룹니다.

 

보안 모범 사례

애플리케이션에 보안을 설계하고 구현하는 것이 항상 최우선 순위가 되어야합니다- 이것은 서버리스 아키텍처에서는 변경되지 않는 사실입니다. 서버리스 애플리케이션을 서버가 호스팅하는 애플리케이션과 비교할 때의 주요 차이점은 분명합니다- 보안 할 서버가 없습니다. 그러나 여전히 애플리케이션의 보안에 대해 생각해야합니다. 여전히 서버리스 보안에 대한 책임 분담 모델이 있습니다.

Lambda 및 서버리스 아키텍처를 사용하면 안티 바이러스 / 맬웨어 소프트웨어, 파일 무결성 모니터링, 침입 탐지 / 예방 시스템, 방화벽 등을 통해 애플리케이션 보안을 직접 구현하지 않고도 안전한 애플리케이션 코드 작성, 소스에 대한 엄격한 액세스 제어를 통해 보안 모범 사례를 보장합니다. Lambda 함수가 통합 된 각 서비스에 대한 코드 변경 및 AWS 보안 모범 사례를 따르십시오.

다음은 많은 서버리스 사용 사례에 적용 할 수있는 서버리스 보안 모범 사례에 대한 간략한 목록입니다. 사용자 고유의 특정 보안 및 규정 준수 요구 사항을 잘 이해하고 여기에 설명 된 것 이상을 포함 할 수 있습니다.

함수 당 하나의 IAM 역할

AWS 계정 내의 모든 Lambda 함수는 IAM 역할과 1 : 1 관계를 가져야합니다. 여러 함수가 정확히 동일한 정책으로 시작하더라도 함수의 미래에 대한 최소 권한 정책을 보장 할 수 있도록 항상 IAM 역할을 분리하십시오.

예를 들어 여러 Lambda 함수에서 AWS KMS 키에 액세스해야하는 Lambda 함수의 IAM 역할을 공유 한 경우 해당 함수는 모두 동일한 암호화 키에 액세스 할 수 있습니다.


임시 AWS 자격 증명

Lambda 함수 코드 또는 구성에 수명이 긴 AWS 자격 증명이 포함되어 있지 않아야합니다. (이것은 정적 코드 분석 도구가 코드 기반에서 절대 발생하지 않도록하는 데 유용합니다!) 대부분의 경우 IAM 실행 역할이 다른 AWS 서비스와 통합하는 데 필요한 전부입니다. 자격 증명을 제공하지 않고 AWS SDK를 통해 코드 내에 AWS 서비스 클라이언트를 생성하기 만하면됩니다. SDK는 역할에 대해 생성 된 임시 자격 증명의 검색 및 회전을 자동으로 관리합니다. 다음은 Java를 사용한 예입니다.

이 코드 스니펫은 AWS SDK for Java가 함수에 할당 된 임시 IAM 자격 증명을 사용하여 요청을 DynamoDB API에 자동으로 서명하는 DynamoDB 테이블과 상호 작용하기위한 객체를 생성하는 데 필요한 모든 것입니다.

그러나 실행 역할이 함수에 필요한 액세스 유형에 충분하지 않은 경우가 있습니다. 이는 Lambda 함수가 수행 할 수있는 일부 계정 간 통합의 경우이거나 Amazon Cognito 40 자격 증명 역할과 DynamoDB의 세분화 된 액세스 제어 를 결합하여 사용자 별 액세스 제어 정책이있는 경우 일 수 있습니다 .41 계정 간 사용 사례의 경우, 실행 역할에 AWS Security Token Service 내의 AssumeRole API에 대한 액세스 권한이 부여 되고 임시 액세스 자격 증명을 검색하도록 통합 되어야합니다 .42

사용자 별 액세스 제어 정책의 경우 해당 함수에 해당 사용자 자격 증명 을 제공 한 다음 Amazon Cognito API GetCredentialsForIdentity .43 과 통합해야합니다 .이 경우 코드를 통해 이러한 자격 증명을 적절하게 관리하여 활용할 수 있도록해야합니다. Lambda 함수 호출과 연관된 각 사용자의 올바른 신임 정보. 애플리케이션 이 사용자 세션 데이터의 일부로 DynamoDB 또는 Amazon ElastiCache 와 같은 장소에 이러한 사용자 별 자격 증명을 암호화하고 저장하는 것이 일반적 이므로 반환 요청에 대해 후속 요청을 위해이를 생성하는 것보다 지연 시간이 줄어들고 확장 성이 더 높아질 수 있습니다. 사용자.44

 

지속되는 비밀

Lambda 함수에서 사용해야하는 수명이 긴 비밀(예 : 데이터베이스 자격 증명, 종속성 서비스 액세스 키, 암호화 키 등)이있을 수 있습니다. 애플리케이션에서 비밀 관리 수명주기에 대한 몇 가지 옵션을 권장합니다.

 

  • 암호화 헬퍼가 있는 Lambda 환경 변수
    • 장점 – 함수 런타임 환경에 직접 제공되어 비밀 검색에 필요한 대기 시간 및 코드를 최소화합니다.
    • 단점 – 환경 변수는 함수 버전에 연결됩니다. 환경 변수를 업데이트하려면 새로운 함수 버전이 필요합니다 (더 엄격하지만, 안정적인 버전 히스토리를 제공해줌).
  • Amazon EC2 Systems Manager Parameter Store
    • 장점 – Lambda 함수와 완전히 분리되어 비밀과 함수가 서로 관련되는 방식에 대한 최대 유연성을 제공합니다.
    • 단점 – 매개 변수/비밀을 검색하려면 매개 변수 저장소에 대한 요청이 필요합니다. 상당하지는 않지만, 환경 변수에 대한 지연 시간과 부가적인 서비스 종속성이 추가되며 약간 더 많은 코드를 작성해야합니다.

비밀 사용

비밀은 항상 메모리에만 존재해야하며 디스크에 로그되거나 기록되지 않아야합니다. 애플리케이션이 계속 실행되는 동안 비밀을 취소해야 할 경우 비밀 회전을 관리하는 코드를 작성하십시오.

 

API 인증

Lambda 함수의 이벤트 소스로 API Gateway를 사용하는 것은 API 클라이언트의 인증 및 권한을 소유한다는 점에서 다른 AWS 서비스 이벤트 소스 옵션과 다릅니다. API Gateway는 기본 AWS SigV4 인증, 생성된 클라이언트 SDK 및 사용자 지정 권한 부여자와 같은 기능을 제공하여 많은 양의 작업을 수행 할 수 있습니다. 그러나 여전히 API의 보안 상태가 사용자의 요구 사항을 충족하는지 확인해야합니다.하지만, 당신은 여전히 API의 보안 자세가 당신이 설정한 바와 충족되도록 보장할 책임이 있다.


VPC 보안

Lambda 함수가 VPC 내부에 배포 된 리소스에 액세스해야하는 경우 최소 권한 보안 그룹, Lambda 함수 관련 서브넷, 네트워크 ACL 및 Lambda 함수에서만 들어오는 트래픽을 허용하는 라우팅 테이블을 통해 네트워크 보안 모범 사례를 적용해야합니다. 목적지에 도달하십시오.

이러한 사례와 정책은 Lambda 함수가 종속 항목에 연결되는 방식에 영향을 미칩니다. Lambda 함수 호출은 여전히 ​​이벤트 소스와 호출 API를 통해 발생합니다 (VPC 구성의 영향을받지 않음).

 

배포 액세스 제어

UpdateFunctionCode API 호출은 코드 배포와 유사합니다. UpdateAlias ​​API를 통해 별칭을 새로 게시 된 버전으로 이동하는 것은 코드 릴리스와 유사합니다. 극도로 민감한 함수 코드/ 별칭을 가능하게하는 Lambda API에 대한 액세스를 처리하십시오. 따라서 인적 오류 가능성을 제거하기 위해 모든 함수(최소한 함수)에 대해 이 API에 대한 사용자의 직접 액세스를 제거해야합니다. Lambda 함수에 대한 코드 변경은 자동화를 통해 수행해야합니다. 이를 염두에두고 Lambda에 배포하기위한 시작점이 CI/CD (Continuous Integration / Continuous Delivery) 파이프 라인이 시작되는 곳이 됩니다. AWS CodePipeline 을 트리거하는 새 코드 패키지가 업로드되는 S3 버킷 인 리포지토리의 릴리스 브랜치 일 수 있습니다. 파이프 라인 또는 조직 및 프로세스와 관련된 다른 곳 어디에 있든 팀 구조와 역할에 맞는 엄격한 액세스 제어 메커니즘을 적용해야하는 새로운 장소가됩니다.

 

 

안정성 모범 사례

미션 크리티컬 유스 케이스를 지원하도록 서버리스 애플리케이션을 구축 할 수 있습니다. 미션크리티컬 애플리케이션과 마찬가지로, Amazon.com의 CTO 인 Werner Vogels가 말한 “모든 것이 항상 실패합니다”라는 주장을 염두에 두고 아키텍처를 설계하는 것이 중요합니다. 서버리스 애플리케이션의 경우, 이는 논리 버그를 코드에 도입하고, 응용프로그램 종속성에 실패하며, 서버리스 애플리케이션에 여전히 적용되는 기존의 모범 사례 사용을 방지하고 고려해야 하는 기타 유사한 응용프로그램 수준 문제를 의미할 수 있다. 서버리스 애플리케이션에 대한 이벤트에서 벗어난 인프라 수준의 서비스 이벤트의 경우 고 가용성 및 내결함성을 달성하기 위해 애플리케이션을 구성한 방법을 이해해야합니다.

고 가용성

고 가용성은 프로덕션 애플리케이션에 중요합니다. Lambda 함수의 가용성 상태는 실행할 수있는 가용 영역 수에 따라 다릅니다. 함수가 기본 네트워크 환경을 사용하는 경우 해당 AWS 리전의 모든 가용 영역 내에서 자동으로 실행할 수 있습니다. 기본 네트워크 환경에서 함수에 대한 고 가용성을 구성하기 위해 필요한 것은 없습니다. 함수가 자체 VPC 내에 배포 된 경우 서브넷(및 해당 가용 영역)은 가용 영역 중단시 함수를 계속 사용할 수 있는지 여부를 정의합니다.
따라서 VPC 설계여러 가용 영역의 서브넷이 포함되어 있어야합니다. 가용 영역 중단이 발생할 경우 나머지 서브넷에 필요한 동시에 실행되고 있는 함수의 수만큼 지원할 수있는 적절한 IP 주소를 계속 유지하는 것이 중요합니다.

내결함성

필요한 애플리케이션 가용성으로 인해 여러 AWS 리전을 활용해야하는 경우, 설계시 내결함성을 먼저 고려해야합니다. Lambda 함수 코드 패키지를 여러 AWS 리전으로 복제하는 것은 복잡한 것이 아닙니다. 복잡 할 수 있는 것은 애플리케이션 스택의 모든 계층에서 장애 조치 결정을 조정하는 것입니다. 이는 Lambda 함수뿐만 아니라 이벤트 소스(및 이벤트 소스의 추가 업스트림 종속성) 및 지속성 계층을 위한 다른 AWS 리전으로의 전환을 이해하고 조정해야한다는 것을 의미합니다. 결국, 다중 지역 아키텍처는 애플리케이션에 따라 매우 다릅니다. 다중 지역 디자인을 실현하기 위해 수행해야 할 가장 중요한 일은 디자인에서 이를 먼저 설명하는 것입니다.

회복

함수를 실행할 수 없는 경우 서버리스 애플리케이션이 어떻게 행동해야하는지 고려하십시오. API Gateway가 이벤트 소스로 사용되는 유스 케이스의 경우, 오류 메시지를 정상적으로 처리하고 함수를 다시 실행할 수 있을 때까지 실행 가능한(성능이 저하 되었을 지라도) 사용자 경험을 제공하는 것처럼 간단 할 수 있습니다.

비동기 사용 사례의 경우 중단 기간 동안 함수 호출이 유실되지 않도록하는 것이 매우 중요합니다. 함수가 복구 된 후 수신 된 모든 이벤트가 처리되도록하려면 데드 레터 큐를 활용 하고 복구가 발생한 후 해당 큐에있는 이벤트를 처리하는 방법을 구현해야합니다.

 

성능 효율성 모범 사례

성능 모범 사례를 살펴보기 전에 사용 사례를 비동기적으로 사용 할 수있는 경우(비용 최적화를 제외하고) 함수의 성능에 대해 걱정할 필요가 없습니다. InvocationType 이벤트를 사용하거나 풀 기반 호출 모델 을 사용하는 이벤트 소스 중 하나를 활용할 수 있습니다 . 이러한 방법만으로도 Lambda가 이벤트를 개별적으로 처리하는 동안 애플리케이션 로직이 진행될 수 있습니다. Lambda 함수 실행 시간을 최적화하려는 경우 Lambda 함수의 실행 시간은 주로 세 가지 요소(최적화하기 가장 간단한 순서)의 영향을 받습니다. 함수 구성에 할당 한 리소스, 선택한 언어 런타임, 그리고 당신이 쓰는 코드.

 

최적의 메모리 크기 선택
Lambda는 함수에 사용할 수 있는 컴퓨팅 리소스의 양(함수에 할당 된 RAM 크기)을 늘리거나 줄일 수있는 단일 다이얼을 제공합니다. 할당 된 RAM의 양은 함수가 받는 CPU 시간네트워크 대역폭에도 영향을줍니다. 단순하게, 함수가 적절히 빠르게 실행될 수 있는 가장 적은 양의 리소스를 선택하는 것은 안티 패턴입니다.

Lambda는 100ms 단위로 청구되기 때문에 이 전략은 애플리케이션에 대기 시간을 추가 할뿐만 아니라 추가 된 대기 시간이 리소스 비용 절감을 능가하는 경우 전체적으로 더 비쌀 수 있습니다.

사용 가능한 각 리소스 수준에서 Lambda 함수를 테스트하여 애플리케이션에 대한 최적의 가격/성능 수준을 결정하는 것이 좋습니다. 리소스 수준이 증가함에 따라 함수의 성능이 로그적으로 향상되어야합니다. 실행중인 로직은 함수 실행 시간의 하한을 정의합니다. 함수에 사용 가능한 추가 RAM / CPU / 대역폭이 더 이상 실질적인 성능 향상을 제공하지 않는 리소스 임계 값도 있습니다. 그러나 Lambda에서 리소스 수준이 증가함에 따라 가격이 선형 적으로 증가합니다. 테스트에서는 함수에 대한 최적의 구성을 선택하기 위해 로그 함수가 구부러지는 위치를 찾아야합니다.

다음 그래프는 예제 함수에 이상적인 메모리 할당을 통해 비용을 높이고 대기 시간을 줄일 수있는 방법을 보여줍니다. 여기서 더 낮은 메모리 옵션보다 512MB를 사용하기위한 100ms 당 추가 계산 비용은 더 많은 리소스를 할당함으로써 함수에서 감소 된 대기 시간의 양보다 중요합니다. 그러나 512MB 후에는이 특정 함수의 논리에 대한 성능 향상이 줄어들 기 때문에 100ms 당 추가 비용이 총 비용을 더 높입니다. 총 비용을 최소화하기위한 최적의 선택으로 512MB가 남습니다.

 

 

 

함수의 메모리 사용량은 호출마다 결정되며 CloudWatch Logs 에서 볼 수 있습니다. 각 호출마다 REPORT : 항목이 표시됩니다 (아래 참조). 

Max Memory Used : 필드를 분석하여 함수에 더 많은 메모리가 필요한지 또는 함수의 메모리 크기를 과다 프로비저닝했는지 확인할 수 있습니다.

 

언어 런타임 성능
언어 런타임 성능을 선택하는 것은 지원되는 각 런타임의 편안함과 기술 수준에 따라 달라집니다. 그러나 성능이 애플리케이션의 주요 고려 사항이라면 다른 런타임 환경에서와 같이 Lambda에서 각 언어의 성능 특성이 기대할 수 있습니다. 컴파일 된 언어(Java 및 .NET)는 컨테이너의 첫 호출 시 초기 시작 비용이 가장 많이 들지만,  후속 호출에 대한 최상의 성능을 보여줍니다. 해석 된 언어 (Node.js 및 Python)는 컴파일 된 언어에 비해 초기 호출 시간이 매우 빠르지 만 컴파일 된 언어와 동일한 수준의 최대 성능에 도달 할 수 없습니다.

 

애플리케이션 사용 사례가 대기 시간에 민감하고 초기 호출 비용이 자주 발생하기 쉬운 경우(매우 급증하거나 자주 사용하지 않는 경우) 해석되는 언어 중 하나를 권장합니다.

애플리케이션이 트래픽 패턴 내에서 피크 또는 밸리가 크지 않거나 Lambda 함수 응답 시간에 대한 사용자 경험이 차단되지 않은 경우 이미 가장 익숙한 언어를 선택하는 것이 좋습니다.

 

코드 최적화
Lambda 함수의 성능의 대부분은 Lambda 함수를 실행하는 데 필요한 논리와 종속 관계에 따라 결정됩니다. 우리는 모든 최적화가 애플리케이션마다 다르기 때문에 모든 최적화를 다룰 수는 없습니다. 그러나 Lambda에 맞게 코드를 최적화하는 일반적인 모범 사례가 있습니다. 이는 컨테이너 재사용을 활용하고(이전 개요에서 설명한대로) 콜드 스타트 초기 비용을 최소화하는 것과 관련이 있습니다.

다음은 웜 컨테이너가 호출 될 때 함수 코드의 성능을 향상시키는 방법에 대한 몇 가지 예입니다.

  • 초기 실행 후 코드에서 로컬로 검색하는 외부화 된 구성 또는 종속성을 저장하고 참조하십시오.
  • 모든 호출에서 변수/객체의 재 초기화를 제한하십시오(전역/정적 변수, 싱글 톤 등 사용).
  • 이전 호출 중에 설정된 연결 (HTTP, 데이터베이스 등)을 유지하고 재사용하십시오.

마지막으로 Lambda 함수에 콜드 스타트가 걸리는 시간을 제한하려면 다음을 수행해야합니다.

  1. 프라이빗 IP를 통해 VPC 내의 리소스에 연결해야하는 경우가 아니면 항상 기본 네트워크 환경을 사용하십시오. 이는 Lambda 함수의 VPC 구성 (VPC 내 ENI 생성과 관련)과 관련된 추가 콜드 스타트 ​​시나리오가 있기 때문입니다.
  2. 컴파일 된 언어보다 해석 된 언어를 선택하십시오.
  3. 함수 코드 패키지를 런타임 요구 사항으로만 정리하십시오. 이를 통해 호출 전에 Amazon S3에서 코드 패키지를 다운로드하는 데 걸리는 시간이 줄어 듭니다.


애플리케이션 성능 이해
하나 이상의 Lambda 함수를 포함 할 수있는 애플리케이션 아키텍처의 다양한 구성 요소를 파악하려면 AWS X-Ray를 사용하는 것이 좋습니다. X-Ray는 각 구성 요소를 통해 애플리케이션 요청의 전체 수명주기를 추적 할 수 있습니다 다음 그림과 같이 각 구성 요소의 대기 시간 및 기타 메트릭을 개별적으로 보여줍니다.

 

 

운영 우수성 모범 사례

서버리스 애플리케이션을 만들면 기존 애플리케이션에 수반되는 많은 운영 부담이 제거됩니다. 그렇다고해서 운영 효율성에 대한 초점을 줄여야한다는 의미는 아닙니다. 즉, 운영 초점을 더 적은 수의 책임으로 좁히고 더 높은 수준의 운영 우수성을 달성 할 수 있습니다.

로깅
Lambda의 각 언어 런타임은 함수가 기록 된 명령문을 CloudWatch Logs로 전달하는 메커니즘을 제공합니다. 로그를 적절하게 사용하는 것은 말할 것도없고 Lambda 및 서버리스 아키텍처에는 새로운 것이 아닙니다. 오늘날 모범 사례로 간주되지 않지만, 많은 운영 팀은 애플리케이션이 배포 된 서버에서 로그를 생성 할 때 로그를 보는 데 의존합니다. 서버가 없기 때문에 Lambda에서는 불가능합니다. 또한 현재 실행중인 Lambda 함수의 코드를 "스텝 스루"할 수는 없습니다(AWS SAM Local을 사용 하여 수행 할 수는 있음). 배포 된 함수의 경우 함수 동작을 조사하기 위해 생성 한 로그에 크게 의존합니다. 따라서 생성하는 로그는 계산에 너무 많은 추가 계산 시간을 요구하지 않고 발생하는 문제를 추적/심사하는 데 도움이되는 정확한 상세 균형을 찾는 것이 특히 중요합니다.

Lambda 환경 변수를 사용하여 함수가 참조 할 수있는 LogLevel 변수를 만들어 런타임 중에 만들 로그 문을 결정할 수 있도록하는 것이 좋습니다. 적절한 로그 수준을 사용하면 운영 심사 중에만 추가 컴퓨팅 비용과 스토리지 비용을 선택적으로 발생시킬 수 있습니다.

지표 및 모니터링
Lambda는 다른 AWS 서비스와 마찬가지로 많은 CloudWatch 지표를 즉시 제공합니다. 여기에는 함수가 받은 호출 수, 함수의 실행 기간 및 기타와 관련된 메트릭이 포함됩니다. CloudWatch를 통해 제공된 모든 지표에서 각 Lambda 함수에 대해 경보 임계 값(높음 및 낮음)을 생성하는 것이 가장 좋습니다 . 함수가 호출되는 방식이나 실행하는 데 걸리는 시간이 크게 변경되면 아키텍처의 문제가 처음으로 나타날 수 있습니다.

 

애플리케이션이 수집해야하는 추가 지표(예 : 애플리케이션 오류 코드, 종속 성별 대기 시간 등)에는 CloudWatch 또는 선택한 모니터링 솔루션에 이러한 사용자 지정 지표를 저장하는 두 가지 옵션이 있습니다.

 

  • 사용자 지정 지표를 만들고 Lambda 함수가 실행되는 동안 필요한 API와 직접 통합하십시오. 이는 종속성이 가장 적으며 가능한 빨리 메트릭을 기록합니다. 그러나 Lambda 실행 시간과 리소스를 다른 서비스 종속성과 통합하는 데 소비해야합니다. 이 경로를 따르면 메트릭 캡처 코드가 특정 Lambda 함수와 밀접하게 연결되는 대신 Lambda 함수에서 모듈화되고 재사용 가능한지 확인하십시오.
  • Lambda 함수 코드 내에서 메트릭을 캡처하고 Lambda에서 제공된 로깅 메커니즘을 사용하여 로깅하십시오. 그런 다음 함수 스트림에서 CloudWatch Logs 지표 필터를 생성하여 지표를 추출하여 CloudWatch에서 사용할 수 있도록합니다. 또는 CloudWatch Logs 스트림에서 구독 필터로 다른 Lambda 함수를 생성하여 필터링 된 로그 문을 다른 지표 솔루션으로 푸시하십시오. 이 경로는 더 복잡한 정보를 제공하며 메트릭 캡처를위한 이전 솔루션만큼 거의 실시간이 아닙니다. 그러나 외부 서비스 요청을 작성하지 않고 로깅을 통해 메트릭을보다 빠르게 작성할 수 있습니다.


배포
Lambda에서 배포를 수행하는 것은 새 함수 코드 패키지를 업로드하고 새 버전을 게시하며 별칭을 업데이트하는 것 만큼 간단합니다. 그러나 이러한 단계는 Lambda를 사용한 배포 프로세스의 일부일뿐입니다. 각 배포 프로세스는 애플리케이션에 따라 다릅니다. 사용자나 애플리케이션 동작을 방해하지 않는 배포 프로세스를 디자인하려면 각 Lambda 함수와 해당 이벤트 소스 및 종속성 간의 관계를 이해해야합니다. 고려해야 할 사항은 다음과 같습니다.

 

  • 병렬 버전 호출 – 새 버전의 Lambda 함수를 가리 키도록 별칭을 업데이트하면 서비스 측에서 비동기적으로 발생합니다. 이전 소스 코드 패키지를 포함하는 기존 함수 컨테이너가 별칭이 업데이트 된 새 함수 버전과 함께 계속 호출되는 시간이 짧습니다. 이 프로세스 동안 이 계속 예상대로 작동하는 것이 중요합니다. 이것의 아키팩트는 배포 후에 데이터베이스 테이블, 메시지 대기열 등과 같은 스택 종속성이 해제되어 새 함수 버전을 대상으로하는 모든 호출을 관찰 한 후에야 해제되지 않을 수 있습니다.
  • 배포 일정 – 최대 트래픽 시간 동안 Lambda 함수 배포를 수행하면 시작보다 콜드 시작 시간이 길어질 수 있습니다. Lambda 환경에서 프로비저닝되는 새/콜드 함수 컨테이너의 즉각적인 영향을 최소화하려면 트래픽이 적은 기간 동안 항상 함수 배치를 수행해야합니다.
  • 롤백 – Lambda는 Lambda 함수 버전 (예 : 생성 시간, 증분 숫자 등)에 대한 세부 정보를 제공합니다. 그러나 애플리케이션 수명주기에서 해당 버전을 어떻게 사용하고 있는지 논리적으로 추적하지는 않습니다. Lambda 함수 코드를 롤백 해야하는 경우, 프로세스가 이전에 배포 된 함수 버전으로 롤백하게 하는 것이 중요합니다. 


부하 테스트

Lambda 함수를 로드 테스트하여 최적의 타임아웃 값을 결정하십시오. 함수 실행 시간을 분석하여 예상보다 더 많은 함수의 동시성을 증가시킬 수있는 종속성 서비스의 문제점을 더 잘 판별 할 수 있도록하는 것이 중요합니다. 이는 Lambda 함수가 Lambda의 스케일링을 처리하지 못할 수있는 리소스를 네트워크로 호출 할 때 특히 중요합니다.

심사 및 디버깅

조사를 가능하게하는 로깅과 X-Ray를 사용하여 애플리케이션을 프로파일 링하는 것은 운영 심사에 유용합니다. 또한 통합 테스트, 성능 테스트, 디버깅 등과 같은 운영 활동을 나타내는 Lambda 함수 별칭을 작성하는 것을 고려하십시오. 팀이 운영 목적에 맞는 테스트 세트 또는 세그먼트 화 된 애플리케이션 스택을 구축하는 것이 일반적입니다. 이 운영 아티팩트를 빌드하여 별칭을 통해 Lambda 함수와 통합해야합니다. 그러나 별칭은 완전히 별개의 Lambda 함수 컨테이너를 강제하지 않습니다. 따라서 함수 버전 번호 N을 가리키는 PerfTest와 같은 별칭은 버전 N을 가리키는 다른 모든 별칭과 동일한 함수 컨테이너를 사용합니다. 필요한 경우 별도의 컨테이너가 호출되도록 적절한 버전 관리 및 별칭 업데이트 프로세스를 정의해야합니다.

 

비용 최적화 모범 사례

Lambda 요금은 함수 실행 시간과 할당 된 리소스를 기준으로하므로 비용 최적화는이 두 가지 차원을 최적화하는 데 중점을 둡니다.

올바른 크기
'성능 최적화 모범사례'에서 다루는 것처럼, 함수에 사용 가능한 가장 작은 리소스 크기가장 낮은 총 비용을 제공한다고 가정하는 것은 잘못된 생각(안티 패턴)입니다. 함수의 리소스 크기가 너무 작은 경우, 함수가 더 빠르게 완료되도록 하여 더 많은 리소스가 사용가능하다면 긴 실행시간으로 발생하는 비용보다 더 많은 비용을 지불해야할 수도 있습니다.
자세한 내용은 최적 메모리 크기 선택 섹션 을 참조하십시오.

분산 및 비동기 아키텍처

일련의 차단/동기화 API 요청 및 응답을 통해 모든 사용 사례를 구현할 필요는 없습니다. 비동기식으로 애플리케이션을 설계 할 수있는 경우, 아키텍처의 분리 된 각 구성 요소는 동기 요청에 대한 응답을 기다리는 CPU주기를 소비하는 밀접하게 연결된 구성 요소보다 작업 수행에 컴퓨팅 시간이 덜 소요될 수 있습니다. 많은 Lambda 이벤트 소스는 분산 시스템에 적합하며 모듈식 및 분리된 함수를 보다 비용 효율적인 방식으로 통합하는 데 사용할 수 있습니다.

배치 크기

일부 Lambda 이벤트 소스를 사용하면 각 함수 호출시 제공되는 레코드 수(예 : KinesisDynamoDB)의 배치 크기를 정의 할 수 있습니다. 각 배치 크기에 대한 최적의 레코드 수를 테스트하여 각 이벤트 소스의 폴링 빈도가 함수가 태스크를 얼마나 빨리 완료 할 수 있는지 조정해야합니다.

이벤트 소스 선택

Lambda와 통합 할 수있는 다양한 이벤트 소스가 있다는 것은, 요구 사항을 충족하기 위해 다양한 솔루션 옵션을 사용할 수 있음을 의미합니다.
사용 사례 및 요구 사항 (요청 규모, 데이터 양, 지연 시간 필요 등)에 따라, 람다 함수를 둘러싼 구성요소로 선택한 AWS 서비스를 기준으로 아키텍처의 총 비용에는 큰 차이가 없을 수 있습니다.

 

서버리스 개발 모범 사례

Lambda로 애플리케이션을 만들면 이전에는 경험하지 못했던 개발 속도를 실현할 수 있을 것입니다. 강력한 서버리스 애플리케이션을 위해 작성해야하는 코드의 양은 이전에 서버 기반 모델을 작성하는 데 필요한 코드의 비율 보다 훨씬 더 적을 것입니다. 그러나 서버리스 아키텍처를 가능하게하는 새로운 애플리케이션 전달 모델을 사용하게 되면, 개발 프로세스가 결정을 해야하는 새로운 관점과 구성이 있습니다.

Lambda 함수를 염두에 두고 코드 기반을 구성하고, 개발자 랩톱에서 프로덕션 서버리스 환경으로 코드 변경 사항을 옮기고, Lambda 런타임 환경 또는 AWS 외부의 이벤트 소스를 시뮬레이션 할 수없는 경우에도 테스트를 통해 코드 품질을 보장하는 것과 같은 것들. 다음은 서버리스 애플리케이션이 가지고있는 이러한 측면을 통해 작업하는 데 도움이되는 개발 중심의 모범 사례입니다.

 

 

코드 형태의 인프라 – AWS SAM (AWS Serverless Application Model)

인프라를 코드로 표현하면 인프라 생성 및 수정 관리의 감사가능성, 자동화 가능성 및 반복성 측면에서 많은 이점이 있습니다. 서버리스 애플리케이션을 구축 할 때 인프라를 관리 할 필요는 없지만 IAM 역할, Lambda 함수 및 구성, 이벤트 소스 및 기타 종속성과 같은 많은 구성 요소가 아키텍처에서 역할을 합니다. AWS CloudFormation에서 이러한 모든 것을 나타내려면 기본적으로 많은 양의 JSON 또는 YAML이 필요합니다. 대부분의 서버리스 애플리케이션에서 다른 서버리스 애플리케이션으로 거의 동일합니다.

AWS SAM(AWS Serverless Application Model)을 사용하면 서버리스 애플리케이션을 구축 할 때 더 간단한 환경을 경험할 수 있으며 인프라의 이점을 코드로 활용할 수 있습니다. AWS SAM은 AWS CloudFormation 기반의 개방형 사양 추상화 계층입니다. JSON 또는 YAML 라인만으로 전체 서버리스 애플리케이션 스택을 정의하고 Lambda 함수 코드를 함께 패키지 할 수있는 일련의 명령 줄 유틸리티를 제공합니다. 해당 인프라 정의를 사용하여 AWS에 함께 배포하십시오. 서버리스 애플리케이션 환경을 정의하고 변경하려면 AWS SAM을 AWS CloudFormation과 함께 사용하는 것이 좋습니다.

그러나 인프라/환경 수준에서 발생하는 변경과 기존 Lambda 함수 내에서 발생하는 애플리케이션 코드 변경 간에는 차이가 있습니다. Lambda 함수 코드 변경을위한 배포 파이프라인을 구축하는 데 AWS CloudFormation 및 AWS SAM만이 필요한 툴은 아닙니다. Lambda 함수의 코드 변경 관리에 대한 자세한 내용은이 백서 의 CI/CD 섹션 을 참조하십시오 .

 

로컬 테스트 – AWS SAM Local

AWS SAM Local은 AWS SAM과 함께 AWS SAM에 추가할 수 있는 추가 명령줄 도구를 제공하여 AWS에 배포하기 전에 서버리스 함수과 애플리케이션을 로컬로 테스트할 수 있다. AWS SAM Local은 Docker를 사용하여 인기 있는 이벤트 소스(예: Amazon S3, DynamoDB 등)를 사용하여 개발된 람다 함수를 신속하게 테스트할 수 있다. SAM 템플릿에서 정의한 API를 API Gateway에서 만들기 전에 로컬에서 테스트 할 수 있습니다. 생성한 AWS SAM 템플릿의 유효성을 검사할 수도 있습니다. 개발자 워크 스테이션 내에 여전히 존재하는 Lambda 함수에 대해 이러한 기능을 실행하면 로컬에서 로그보기, 디버거에서 코드 단계별 실행 및 AWS에 새 코드 패키지를 배포하지 않고도 변경 사항을 신속하게 반복하는 등의 작업을 수행 할 수 있습니다.


코딩 및 코드 관리 모범 사례

Lambda 함수용 코드를 개발할 때 많은 Lambda 함수를 관리하는 것이 복잡한 작업이되지 않도록 코드를 작성하고 구성하는 방법에 대한 몇 가지 권장 사항이 있습니다.

코딩 모범 사례

 

빌드한 Lambda 런타임 언어에 따라 해당 언어에 대해 이미 설정된 모범 사례를 계속 따르십시오. Lambda를 통해 코드 호출 방식을 둘러싼 환경이 변경되었지만 언어 런타임 환경은 다른 곳과 동일합니다. 코딩 표준 및 모범 사례가 여전히 적용됩니다. 다음 권장 사항은 선택한 언어에 대한 일반적인 모범 사례 이외의 Lambda 용 코드 작성에만 해당됩니다.

(1) 핸들러 외부의 비즈니스 로직

Lambda 함수는 코드 패키지 내에 정의한 핸들러 함수에서 실행을 시작합니다. 핸들러 함수 내에서 Lambda가 제공 한 매개변수를 수신하고 해당 매개 변수를 다른 함수로 전달하여 애플리케이션에 컨텍스트화 된 새 변수/객체로 구문 분석 한 다음 핸들러 함수 및 파일 외부에있는 비즈니스 로직에 도달해야합니다. 이를 통해 Lambda 런타임 환경에서 가능한 한 분리 된 코드 패키지를 만들 수 있습니다. 이렇게하면 생성 한 객체와 함수의 컨텍스트 내에서 코드를 테스트하고 Lambda 외부의 다른 환경에서 작성한 비즈니스 로직을 재사용 할 수 있습니다.

다음 예제 (Java로 작성 됨)는 애플리케이션의 핵심 비즈니스 로직이 Lambda에 밀접하게 결합 된 불량 사례를 보여줍니다. 이 예제에서 비즈니스 로직은 핸들러 메소드 내에 작성되며 Lambda 이벤트 소스 오브젝트에 직접 의존합니다.

 

 

(2) 따뜻한 용기 — 캐싱 / 유지 / 재활용

앞에서 언급 했듯이, 코드를 작성할 때 따뜻한 함수 컨테이너의 이점을 가지도록 해야합니다. 이는 가능한 경우 후속 호출에서 변수 및 해당 내용을 재사용 할 수있는 방식으로 변수 범위를 지정하는 것을 의미합니다. 이는 부트스트랩 구성, 외부 종속성 연결을 열린 상태로 유지 또는 한 호출에서 다음 호출까지 지속될 수있는 대형 객체의 일회성 초기화와 같은 작업에 특히 영향을 줍니다.

 

(3) 컨트롤 의존성

Lambda 실행 환경에는 Node.js 용 AWS SDK 및 Python 런타임과 같은 많은 라이브러리가 포함되어 있습니다. 최신 기능 및 보안 업데이트 세트를 활성화 하기 위해 Lambda가 주기적으로 이러한 라이브러리를 업데이트합니다.

이 업데이트는 Lambda 함수의 동작에 미묘한 변화를 가져올 수 있습니다. 함수가 사용하는 종속성을 완전히 제어하려면 모든 종속성을 배포 패키지로 패키징하는 것이 좋습니다.

 

(4) 잘 정리된종속성

Lambda 함수 코드 패키지는 압축시 최대 50MB, 런타임 환경에서 추출시 250MB까지 허용됩니다. 함수 코드에 큰 종속성 아티팩트를 포함하는 경우 런타임 필수 사항에 포함 된 종속성을 정리해야 할 수도 있습니다. 또한 이것은 콜드 스타트 시에 Lambda 함수 코드를 런타임 환경에서 더 빨리 다운로드하여 설치할 수 있게 합니다.

 

(5) 빠른 실패

전체 Lambda 함수 타임아웃 뿐만 아니라 외부 종속성에 대한 타임아웃 시간을 꽤 짧게 구성하십시오. 의존성이 응답하기를 기다리는 동안 함수가 어쩔 수 없이 회전하도록 허용하지 마십시오. Lambda는 함수 실행 기간에 따라 요금이 청구되므로, 함수 종속성이 응답하지 않을 때 필요한 것보다 많은 비용이 발생되기를 원하지 않을 것입니다.

 

(6) 예외 처리

Lambda의 사용 사례에 따라 예외를 다르게 던지고 처리하도록 결정할 수 있습니다. Lambda 함수 앞에 API Gateway API를 배치하는 경우 API Gateway에 예외를 반환하여 오류가 발생했을 경우, 해당 컨텐츠를 기반으로 해당 HTTP 상태 코드 및 오류 메시지로 변환 될 수 있습니다. 비동기 데이터 처리 시스템을 구축하는 경우 코드베이스 내의 일부 예외가 재 처리를 위해 데드 레터 큐로 이동하는 호출과 동일해야한다고 결정하는 반면, 다른 오류는 로깅되어 데드 레터 큐에 놓을 수 없습니다 . 실패 동작 결정이 무엇인지 평가하고 해당 동작을 달성하기 위해 코드 내에서 올바른 유형의 예외를 생성하고 던지는 지 확인해야합니다. 예외 처리에 대한 자세한 내용은 각 언어 런타임 환경에 대해 예외가 정의되는 방법에 대한 자세한 내용을 보려면 다음을 참조하십시오.

 

코드 관리 모범 사례

 

이제 작성한 Lambda 함수 코드가 모범 사례를 따르는데 그렇다면 해당 코드를 어떻게 관리해야 할까요? Lambda의 개발 속도를 통해 일반적인 프로세스에 익숙하지 않은 속도로 코드 변경을 완료 할 수 있습니다. 서버리스 아키텍처에 필요한 코드의 양이 줄었다는 것은 당신이 작성한 Lambda 함수 코드가 전체 애플리케이션 스택 함수 구성의 상당 부분이라는 것을 의미합니다.  따라서 Lambda 함수 코드의 소스 코드 관리가 우수하면, 안전하고 효율적이며 원활한 변경 관리 프로세스를 보장 할 수 있습니다.

 

(1) 코드 리포지토리 구성

선택한 소스 코드 관리 솔루션 내에서 Lambda 함수 소스 코드를 매우 세분화하도록 구성하는 것이 좋습니다. 이는 일반적으로 Lambda 함수와 코드 리포지토리 또는 리포지토리 프로젝트간1 : 1 관계가 있음을 의미합니다(어휘집은 소스 코드 관리 도구마다 다릅니다). 그러나 동일한 로직 함수의 다른 라이프 사이클 단계에 대해 별도의 Lambda 함수를 작성하는 전략을 따르는 경우 (즉, MyLambdaFunction-DEV 및 MyLambdaFunction-PROD라고 부르는 두 개의 람다 함수를 가지고 있으면) 분리된 Lambda 함수가 하나의 코드 기반을 공유하도록하는 것이 합리적입니다(아마도 개별 릴리스 브랜치에서 배포).

 

이러한 방식으로 코드를 구성하는 주요 목적은 특정 Lambda 함수의 코드 패키지에 기여하는 모든 코드가 독립적으로 버전이 지정되고 커밋되고 자체 종속성 및 해당 종속성 버전을 정의하도록하는 것입니다. 각 Lambda 함수는 배포 될 때와 마찬가지로 다른 Lambda 함수와 소스 코드 관점에서 완전히 분리되어야합니다. 애플리케이션 아키텍처를 모듈화하고 Lambda와 분리하여, 모놀리 식으로 단단히 결합 된 코드 기반으로 남겨 두는 프로세스를 진행하고 싶지 않을 것입니다.

 

(2) 릴리즈 분기

Lambda 함수 배포를 릴리스 분기의 증분 커밋과 연관시킬 수있는 리포지토리 또는 프로젝트 분기 전략을 만드는 것이 좋습니다. 리포지토리 내의 소스 코드 변경과 라이브 람다 함수에 배포된 변경 사항을 자신 있게 연관시킬 수 있는 방법이 없는 경우, 운영 조사는 항상 현재 배포된 코드 베이스의 버전을 식별하기 위한 노력부터 시작할 것이다. Lambda 코드 패키지 생성 및 배포 시간을 해당 Lambda 함수의 릴리스 분기에서 발생한 코드 변경 사항과 연관시킬 수있는 CI/CD 파이프라인(나중에 대한 권장 사항)을 작성해야합니다.

 

 

테스팅

서버리스 아키텍처 내에서 품질을 보장하는 가장 좋은 방법은 코드를 철저히 테스트하는 데 소요되는 시간입니다. 그러나 서버리스 아키텍처는 기존에 사용하던 것보다 더 적절한 단위 테스트 방법을 요구합니다. 많은 개발자들이 단위 테스트 도구와 프레임워크를 사용하여 코드의 종속성을 테스트하는 테스트를 작성합니다. 이것은 단위 테스트와 통합 테스트를 결합한 단일 테스트이지만 성능이 좋지 않습니다.

모든 단위 테스트 사례를 단일 로직 함수 내에서 단일 코드 경로까지 범위를 정하여 업스트림의 모든 입력과 다운 스트림의 출력을 모킹(mocking)하는 것이 중요합니다. 이를 통해 내가 작성한 코드만 테스트 케이스로 분리 할 수 ​​있습니다. 단위 테스트를 작성할 때 코드와 API, 라이브러리 등의 계약을 기반으로 종속성이 올바르게 작동한다고 가정해야합니다.

통합 테스트에서 실제 환경을 모방하는 환경에서 코드의 종속성에 대한 코드 통합을 테스트하는 것도 마찬가지로 중요합니다. 개발자 랩톱 또는 빌드 서버가 다운 스트림 종속성과 통합 될 수 있는지 테스트하는 것은 실제 환경에서 코드가 한 번 성공적으로 통합되는지 완전히 테스트하지는 않습니다. 이는 특히 코드 소스에 이벤트 소스가 전달할 이벤트에 대한 소유권이없고 Lambda 외부에서 Lambda 런타임 환경을 작성할 수있는 Lambda 환경에 해당됩니다.

단위 테스트
앞에서 말씀 드린대로 핸들러 함수 밖의 비즈니스 로직에 거의 중점을 두어 Lambda 함수 코드를 철저히 테스트하는 것이 좋습니다. 또한 함수의 이벤트 소스에 대한 샘플/모의 객체를 구문 분석하는 함수를 단위 테스트해야합니다. 그러나 대부분의 로직 및 테스트는 코드 기반 내에서 완벽하게 제어 할 수있는 모킹된 객체 및 함수에서 발생해야합니다. 핸들러 함수 내에 단위 테스트가 필요한 중요한 것들이 있다고 생각되면 핸들러 함수의 로직을 캡슐화하고 외부화해야한다는 신호일 수 있습니다. 또한 작성한 단위 테스트를 보완하려면 함수 코드의 로컬 엔드 투 엔드 테스트 역할을 할 수 있는 AWS SAM Local을 사용하여 로컬 테스트 자동화를 만들어야 한다(이는 단위 테스트의 대체가 아니라는 점에 유의하십시오).

통합 테스팅
통합 테스트의 경우 CI/CD 파이프라인이 결과를 트리거하고 검사 할 수있는 샘플 이벤트를 통해 코드 패키지가 배포되고 호출되는 Lambda 함수의 수명주기가 낮은 버전을 만드는 것이 좋습니다. 구현은 애플리케이션 및 아키텍처에 따라 다릅니다.

 

 

지속적인  전달

CI/CD 파이프 라인을 통해 모든 서버리스 배포를 프로그래밍 방식으로 관리하는 것이 좋습니다. 그것은 속도 때문인데, Lambda를 사용하면 새로운 기능 개발과 코드를 변경이 훨씬 더 자주 배포 될 수 있기 때문입니다. 자주 배포해야 할 필요성이 있을 경우, 수동 배포는 프로세스에 병목 현상이 발생하고 오류가 발생하기 더 쉽습니다.

AWS CodeCommit, AWS CodePipeline, AWS CodeBuild, AWS SAM 및 AWS CodeStar은 전체적이고 자동화 된 서버리스 CI/CD 파이프라인(관리가 필요한 인프라가 없는 파이프라인)과 기본적으로 결합 할 수 있는 일련의 기능을 제공합니다.

다음은 이러한 각 서비스가 잘 정의 된 지속적인 전달 전략에서 어떤 역할을 수행하는지 보여줍니다.

AWS CodeCommit – 서버리스 소스 코드를 호스팅하고, 권고 사항(아주 세밀한 액세스 제어 포함)을 충족하는 분기 전략을 생성하고, AWS CodePipeline과 통합하여 커밋이 릴리스 브랜치에서 발생했을 때 새로운 파이프라인 실행을 트리거 할 수 있는 호스팅 된 프라이빗 Git 리포지토리를 제공합니다. 

AWS CodePipeline 파이프라인의 단계를 정의합니다. 일반적으로 소스 코드 변경이 발생하면 AWS CodePipeline 파이프라인이 시작됩니다. 그런 다음 빌드 단계를 실행하고 새 빌드에 대해 테스트를 실행하고 실제 환경에 빌드를 배포 및 릴리스합니다. AWS CodePipeline은 이러한 각 단계마다 다른 AWS 서비스와의 기본 통합 옵션을 제공합니다.

AWS CodeBuild파이프라인의 빌드 단계에 사용할 수 있습니다. 이를 사용하여 코드를 작성하고, 단위 테스트를 실행하고, 새로운 Lambda 코드 패키지를 작성하십시오.
그런 다음 AWS SAM과 통합하여 코드 패키지를 Amazon S3로 푸시하고 AWS CloudFormation을 통해 새 패키지를 Lambda로 푸시하십시오.

AWS CodeBuild를 통해 새 버전을 Lambda 함수에 게시 한 후 배포 중심 Lambda 함수를 생성하여 AWS CodePipeline 파이프라인에서 후속 단계를 자동화 할 수 있습니다. 통합 테스트 수행, 함수 별칭 업데이트, 즉각적인 롤백이 필요한지 여부 결정 및 애플리케이션 배치 중에 발생하는 기타 애플리케이션 중심 단계(캐시 플러시, 알림 메시지 등)에 대한 로직을 소유합니다. 이러한 배포 중심 Lambda 함수 각각은 Invoke 작업을 사용하여 AWS CodePipeline 파이프 라인 내에서 단계적으로 순차적으로 호출 할 수 있습니다.

결국 각 애플리케이션과 조직에는 소스 코드를 리포지토리에서 프로덕션으로 이동하기위한 고유한 요구 사항이 있습니다. 이 프로세스에 더 많은 자동화를 도입할수록 Lambda를 사용하여 더 많은 민첩성을 얻을 수 있습니다.


AWS CodeStar 모범 사례를 따르는 서버리스 애플리케이션(및 다른 유형의 애플리케이션)을 만드는 것을 도와주는 통합 된 사용자 인터페이스. AWS CodeStar에서 새 프로젝트를 생성하면, 앞에서 언급 한 AWS CodeCommit, AWS CodePipeline 및 AWS CodeBuild 서비스를 사용하여 완전히 구현되고 통합 된 지속적 제공 툴체인을 자동으로 시작합니다. 또한 팀 구성원 관리, 문제 추적, 개발, 배포 및 운영을 포함하여 프로젝트에 대한 SDLC의 모든 측면을 관리 할 수 있습니다. 

 

결론

AWS에서 서버리스 애플리케이션을 구축 하면 서버를 도입하는 책임과 제약이 해소됩니다. 서버리스 로직 레이어로 AWS Lambda를 사용하면 애플리케이션의 차별화 된 요소를  보다 신속하게 구축하고 개발 노력에 집중할 수 있습니다. 람다 외에도, AWS는 구축 할 수 있도록 추가 서버를 사용하지 않는 강력하고, 성능이 좋은, 이벤트 기반의 보안, 신뢰성, 비용 효율적인 애플리케이션을 제공합니다. 이 백서에 설명 된 기능과 권장 사항을 이해하면 자체 서버리스 애플리케이션을 구축 할 때 성공할 수 있습니다. 관련 항목에 대한 자세한 내용은 서버리스 컴퓨팅 및 애플리케이션을 참조하십시오.

반응형