연습: Lambda 지원 사용자 지정 리소스로 AMI ID 조회 - AWS CloudFormation

연습: Lambda 지원 사용자 지정 리소스로 AMI ID 조회

이 연습에서는 Lambda와 사용자 지정 리소스를 사용하여 CloudFormation 템플릿에서 Amazon Machine Image(AMI) ID를 동적으로 조회하는 방법을 보여줍니다. 이는 CloudFormation 템플릿에서 AMI ID를 업데이트하는 방법을 간소화하는 데 도움이 될 수 있습니다.

CloudFormation 템플릿을 생성하여 Amazon EC2 인스턴스를 시작하는 경우 AMI ID를 지정해야 합니다. AMI ID는 인스턴스에 설치될 운영 체제 및 소프트웨어에 대한 템플릿과 같습니다. 올바른 AMI ID는 인스턴스 유형과 인스턴스를 시작하는 AWS 리전에 따라 다릅니다. ID는 정기적으로 변경할 수 있습니다(예: 소프트웨어 업데이트로 AMI가 업데이트되는 경우).

대체로 AMI ID를 특정 인스턴스 유형 및 리전에 매핑하는 매핑 섹션에서 AMI ID를 지정합니다. 따라서 ID를 업데이트하려면 각 템플릿에서 ID를 수동으로 변경해야 합니다. 하지만 사용자 지정 리소스 및 Lambda를 사용하여 인스턴스 유형의 최신 AMI ID와 사용 중인 리전을 가져오는 함수를 생성할 수 있습니다. 이렇게 하면 스택 템플릿의 AMI ID, 인스턴스 유형 및 리전 간의 매핑을 수동으로 유지할 필요가 없습니다.

이 연습에서는 사용자 지정 리소스를 생성하고 AMI ID를 조회하기 위해 이러한 리소스와 Lambda 함수를 연결하는 방법을 보여줍니다. 여기에서는 사용자 지정 리소스 및 Lambda 함수에 대해 잘 알고 있다고 가정합니다. 사용자 지정 리소스의 소개와 작동 방식은 사용자 정의 리소스 섹션을 참조하세요. Lambda에 대한 자세한 내용은 AWS Lambda 개발자 안내서를 참조하세요.

참고

CloudFormation은 무료 서비스이지만 스택에 포함한 AWS 리소스(예: Lambda 함수 및 EC2 인스턴스)에 대해 각각 현재 환율로 비용이 청구됩니다. AWS 요금에 대한 자세한 내용을 알아보려면 http://aws.amazon.com의 제품별 세부 정보 페이지를 참조하세요.

개요

다음 단계에서는 이 구현의 개요를 제공합니다.

  1. Lambda 함수 코드가 포함된 샘플 패키지를 EC2 인스턴스를 생성하려는 AWS 리전과 동일한 리전에 있는 Amazon S3 버킷에 저장합니다.

  2. 샘플 템플릿을 사용하여 사용자 지정 리소스, Lambda 함수, EC2 인스턴스 및 Lambda에서 Amazon EC2를 호출하는 데 사용하는 IAM 역할을 포함하는 스택을 생성합니다.

  3. 스택은 Lambda 함수를 사용자 지정 리소스와 연결합니다. 스택이 생성되면 CloudFormation은 함수를 호출하여 요청 유형, 입력 데이터, 사전 서명된 Amazon S3 URL 등의 정보를 전송합니다.

  4. Lambda 함수는 입력 데이터를 사용하여 최신 AMI ID를 조회하고 미리 서명된 URL에 대한 응답으로 이 AMI ID를 전송합니다.

  5. CloudFormation이 미리 서명된 URL 위치에서 응답을 받고 계속해서 스택 생성을 진행합니다. CloudFormation이 인스턴스를 생성할 때 Lambda 함수에서 제공하는 AMI ID를 사용하여 최신 AMI를 포함하는 EC2 인스턴스를 생성합니다.

템플릿 연습

전체 샘플 템플릿을 보려면 다음 템플릿을 참조하십시오.

다음 코드 조각은 샘플 템플릿의 관련 부분을 설명하여 Lambda 함수를 사용자 지정 리소스와 연결하는 방법과 이러한 함수의 응답을 사용하는 방법을 이해하도록 돕습니다.

AWS::Lambda::Function 리소스 AMIInfoFunction

AWS::Lambda::Function 리소스는 함수의 소스 코드, 핸들러 이름, 런타임 환경 및 실행 역할 Amazon 리소스 이름(ARN)을 지정합니다.

  • Code 속성은 샘플 패키지를 업로드한 Amazon S3 위치(버킷 이름 및 파일 이름)를 지정합니다. 샘플 템플릿은 입력 파라미터("Ref": "S3Bucket""Ref": "S3Key")를 사용하여 버킷 및 파일 이름을 설정하므로 스택을 생성할 때 이름을 지정할 수 있습니다. 마찬가지로, .zip 패키지의 소스 파일(JavaScript 파일)의 이름에 해당하는 핸들러 이름 역시 입력 파라미터("Ref": "ModuleName")를 사용합니다. 소스 파일이 JavaScript 코드이므로 실행 시간이 nodejs18.x으로 지정됩니다.

  • 이 연습에 사용되는 코드의 경우 함수 실행 시간이 기본값인 3초를 초과하므로 시간 제한이 30초로 설정됩니다. 시간 제한을 충분히 길게 지정하지 않으면 Lambda에서는 함수를 완료하기 전에 시간 제한이 발생할 수 있습니다. 그러면 스택 생성에 실패합니다.

  • Role 속성은 Fn::GetAtt 함수를 사용하여 템플릿의 다른 위치에 선언된 LambdaExecutionRole 실행 역할의 ARN을 가져옵니다.

JSON

"AMIInfoFunction": { "Type": "AWS::Lambda::Function", "Properties": { "Code": { "S3Bucket": { "Ref": "S3Bucket" }, "S3Key": { "Ref": "S3Key" } }, "Handler": { "Fn::Join" : [ "", [{ "Ref": "ModuleName" },".handler"] ] }, "Runtime": "nodejs18.x", "Timeout": "30", "Role": { "Fn::GetAtt" : ["LambdaExecutionRole", "Arn"] } } }

YAML

AMIInfoFunction: Type: AWS::Lambda::Function Properties: Code: S3Bucket: !Ref S3Bucket S3Key: !Ref S3Key Handler: !Sub "${ModuleName}.handler" Runtime: nodejs18.x Timeout: 30 Role: !GetAtt LambdaExecutionRole.Arn

AWS::IAM::Role 리소스 LambdaExecutionRole

실행 역할은 로그를 AWS로 전송하고 EC2 DescribeImages API를 호출하는 Lambda 함수 권한을 부여합니다.

JSON

"LambdaExecutionRole": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": {"Service": ["lambda.amazonaws.com"]}, "Action": ["sts:AssumeRole"] }] }, "Path": "/", "Policies": [{ "PolicyName": "root", "PolicyDocument": { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": ["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"], "Resource": "arn:aws:logs:*:*:*" }, { "Effect": "Allow", "Action": ["ec2:DescribeImages"], "Resource": "*" }] } }] } }

YAML

LambdaExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Path: "/" Policies: - PolicyName: root PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: arn:aws:logs:*:*:* - Effect: Allow Action: - ec2:DescribeImages Resource: "*"

Custom::AMIInfo 리소스 AMIInfo

Linux 및 Windows 템플릿 둘 다의 경우 사용자 지정 리소스는 자신과 연결된 Lambda 함수를 호출합니다. 함수를 사용자 지정 리소스와 연결하려면 Fn::GetAtt 내장 함수를 사용하여 ServiceToken 속성에 대해 함수의 ARN을 지정합니다. CloudFormation은 사용자 지정 리소스 선언에 포함된 추가 속성(예: RegionArchitecture)을 Lambda 함수에 입력으로 전송합니다. Lambda 함수는 이러한 입력 속성에 대해 올바른 이름 및 값을 확인합니다.

JSON

"AMIInfo": { "Type": "Custom::AMIInfo", "Properties": { "ServiceToken": { "Fn::GetAtt" : ["AMIInfoFunction", "Arn"] }, "Region": { "Ref": "AWS::Region" }, "Architecture": { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } } }

YAML

AMIInfo: Type: Custom::AMIInfo Properties: ServiceToken: !GetAtt AMIInfoFunction.Arn Region: !Ref "AWS::Region" Architecture: Fn::FindInMap: - AWSInstanceType2Arch - !Ref InstanceType - Arch

Windows의 경우 사용자 지정 리소스는 Lambda 함수에 인스턴스의 아키텍처 대신 Windows 버전을 제공합니다.

JSON

"AMIInfo": { "Type": "Custom::AMIInfo", "Properties": { "ServiceToken": { "Fn::GetAtt": ["AMIInfoFunction", "Arn"] }, "Region": { "Ref": "AWS::Region" }, "OSName": { "Ref": "WindowsVersion" } } }

YAML

AMIInfo: Type: Custom::AMIInfo Properties: ServiceToken: !GetAtt AMIInfoFunction.Arn Region: !Ref "AWS::Region" OSName: !Ref "WindowsVersion"

CloudFormation이 Lambda 함수를 호출하면 이 함수는 AWS 리전 및 인스턴스 아키텍처 또는 OS 이름을 사용하여 이미지 목록을 필터링하는 EC2 DescribeImages API를 호출합니다. 그런 다음 이 함수는 날짜별로 이미지 목록을 정렬하고 최신 AMI ID를 반환합니다.

최신 AMI ID 반환 시 이 함수는 응답 객체Data 속성에 있는 미리 서명된 URL로 반환된 ID를 전송합니다. 다음 예에 표시된 것처럼 데이터는 이름-값 페어로 구성됩니다.

"Data": { "Id": "ami-02354e95b3example" }

AWS::EC2::Instance 리소스 SampleInstance

다음 코드 조각은 Lambda 함수에서 데이터를 가져오는 방법을 보여줍니다. 이 함수는 Fn::GetAtt 내장 함수를 사용하여 사용자 지정 리소스의 이름 및 가져오려는 값의 속성 이름을 제공합니다. 이 연습에서 사용자 지정 리소스의 이름은 AMIInfo이고 속성 이름은 Id입니다.

JSON

"SampleInstance": { "Type": "AWS::EC2::Instance", "Properties": { "InstanceType" : { "Ref": "InstanceType" }, "ImageId": { "Fn::GetAtt": [ "AMIInfo", "Id" ] } } }

YAML

SampleInstance: Type: AWS::EC2::Instance Properties: InstanceType: !Ref InstanceType ImageId: !GetAtt AMIInfo.Id

사전 조건 

스택을 생성하는 단계를 완료하려면 먼저 Amazon S3 버킷을 준비해야 합니다. Lambda 함수를 사용해 스택을 생성하면 이 함수의 소스 코드가 포함된 Amazon S3 버킷의 위치를 지정해야 합니다. 버킷은 스택을 생성할 AWS 리전과 동일한 리전에 위치해야 합니다. 버킷 생성에 대한 자세한 내용을 알아보려면 Amazon Simple Storage Service 사용 설명서버킷 생성을 참조하세요.

해당하는 서비스(예: Lambda, Amazon EC2 및 CloudFormation)를 모두 사용하려면 IAM 권한도 있어야 합니다.

1단계: Amazon S3에 샘플 Lambda 패키지 저장

이 단계에서는 Amazon S3 버킷에 샘플 Lambda 패키지(.zip 파일)를 업로드합니다.

이 패키지에는 Lambda 함수 및 필수 라이브러리에 대한 소스 코드가 포함되어 있습니다. 이 연습의 경우 함수에 추가 라이브러리가 필요하지 않습니다.

Amazon S3에 샘플 패키지를 저장하려면
  1. Amazon S3에서 샘플 패키지를 다운로드합니다. 이 파일을 저장할 때 샘플 amilookup.zip 또는 amilookup-win.zip과 동일한 파일 이름을 사용합니다.

  2. https://console.aws.amazon.com/s3/home에서 Amazon S3 콘솔을 엽니다.

  3. 화면 상단의 탐색 모음에서 Amazon S3 버킷을 생성한 AWS 리전을 선택합니다.

  4. 버킷 목록에서 버킷의 이름을 선택합니다. 스택을 생성할 때 이 버킷을 사용할 것이므로 버킷 이름을 기록해 두세요.

  5. 업로드를 선택합니다.

  6. 업로드파일 및 폴더에서 샘플 패키지를 버킷에 업로드합니다. 자세한 내용은 Amazon Simple Storage Service 사용 설명서의 객체 업로드를 참조하세요.

2단계: 스택 시작

이 단계에서는 샘플 템플릿에서 스택을 시작합니다. 이 스택에는 Lambda 함수, IAM 역할(실행 역할), 이 함수를 호출하는 사용자 지정 리소스 및 해당 함수의 결과를 사용하는 EC2 인스턴스가 포함됩니다.

스택 생성 중 사용자 지정 리소스는 Lambda 함수를 호출해 이 함수가 미리 서명된 Amazon S3 URL로 응답을 전송할 때까지 대기합니다. 호출된 함수는 응답 시 EC2 인스턴스 유형 및 인스턴스를 생성하는 AWS 리전에 해당하는 최신 AMI의 ID를 반환합니다. 함수 응답의 데이터는 EC2 인스턴스의 AMI ID를 지정하는 데 사용되는 사용자 지정 리소스의 속성으로 저장됩니다.

스택을 생성하는 방법
  1. https://console.aws.amazon.com/cloudformation/에서 CloudFormation 콘솔을 엽니다.

  2. 스택 생성을 선택합니다.

  3. 템플릿 섹션에서 Amazon S3 임시 URL 지정을 선택하고 다음 URL을 복사해 텍스트 상자에 붙여 넣습니다.

    Linux 템플릿

    https://s3.amazonaws.com/cloudformation-examples/lambda/LambdaAMILookupSample.template

    Windows 템플릿

    https://s3.amazonaws.com/cloudformation-examples/lambda/LambdaAMILookupSample-win.template

  4. Next(다음)를 선택합니다.

  5. 스택 이름 필드에 SampleEC2Instance을 입력합니다.

  6. 파라미터 섹션에서 자신이 생성한 Amazon S3 버킷의 이름을 지정하고 다음을 선택합니다.

    기타 파라미터의 기본값은 .zip 패키지에서 사용되는 동일한 이름입니다.

  7. 이 연습에서는 태그를 추가하거나 고급 설정을 지정할 필요가 없으므로 다음을 선택합니다.

  8. 스택 이름과 템플릿 URL이 올바른지 확인한 다음 생성을 선택합니다.

CloudFormation에서 스택을 생성하는 데 몇 분 정도 걸릴 수 있습니다. 진행 상황을 모니터링하려면 스택 이벤트를 확인합니다. 자세한 내용은 AWS Management Console에서 AWS CloudFormation 스택 데이터 및 리소스 보기 단원을 참조하십시오.

스택 생성에 성공하면 스택의 모든 리소스(예: Lambda 함수, 사용자 지정 리소스 및 EC2 인스턴스)가 생성된 것입니다. Lambda 함수 및 사용자 지정 리소스를 성공적으로 사용해 EC2 인스턴스의 AMI ID를 지정했습니다. 이 템플릿에서는 AMI ID의 매핑을 생성해 유지할 필요가 없습니다.

EC2 인스턴스를 생성하는 데 사용한 AMI ID CloudFormation을 확인하려면 스택 출력을 살펴봅니다.

Lambda 함수가 오류를 반환하면 CloudWatch Logs 콘솔에서 함수 로그를 확인합니다. 로그 스트림의 이름은 사용자 지정 리소스의 물리적 ID로, 스택의 리소스를 보면 확인할 수 있습니다. 자세한 내용을 알아보려면 Amazon CloudWatch 사용 설명서의 로그 데이터 보기를 참조하세요.

3단계: 리소스 정리

스택을 삭제해 생성한 스택 리소스를 모두 정리하면 불필요한 리소스에 대해 비용이 청구되지 않습니다.

스택을 삭제하려면
  1. CloudFormation 콘솔에서 SampleEC2Instance 스택을 선택합니다.

  2. 작업을 선택한 다음 스택 삭제를 선택합니다.

  3. 확인 메시지에서 예, 삭제를 선택합니다.

생성한 리소스가 모두 삭제됩니다.

이제 CloudFormation에서 Lambda 함수를 생성해 사용하는 방법을 이해했으므로 이 연습의 샘플 템플릿과 코드를 사용하여 기타 스택 및 함수를 빌드할 수 있습니다.

관련 정보