아마존 클라우드

[클라우드] Amazon Lamda에 Application배포하기

트리스탄1234 2023. 7. 29. 06:03
728x90
반응형

Amazon의 Lamda 서비스는 EC2와 같이 항상 운용이 되는 서버가 아니고, 함수나 이벤트로 호출 되어서 컨테이너나 EC2 형태로 구동이 되고, 함수 호출이 끝나면 종료가 되는... 즉 함수 호출이 있을때만 비용을 지불 하기 때문에 EC2보다 더 저렴한 운용비용이 듭니다

Lamda의 동작 방식 순서는 아래와 같습니다.

Lambda 함수를 최대 크기 10GB의 컨테이너 이미지로 패키징하고 배포할 수 있고 그러면 머신러닝 또는 데이터 집약적 워크로드처럼 큰 종속성에 의존하는 대규모 워크로드를 구축하고 배포할 수 잇습니다.

컨테이너 이미지로 배포된 함수는 ZIP 아카이브로 패키징된 함수와 동일한 수준의 운영 간편성, 오토스케일링, 고가용성 및 많은 서비스와의 네이티브 통합된 기능을 이용을 할 수 있습니다.

그럼 이제 Lamda를 이용해 Application을 어떻게 사용을 하는지 그 절차를 살펴 보겠습니다.

먼저 로컬 개발 환경 IDE로 Amazon에서 제공하는 Cloud9을 이용하여 개발 환경을 만듭니다.

Amazon 서비스 콘설 검색창에서 Clou9을 검색 합니다.

기존에 만들어 두었던 Cloud9환경에서 Cloud9 IDE를 클릭 하면 아래와 같은 화면이 나옵니다.

Welcome Tab을 닫고, 아래 CLI창에서 아래 명령을 실행하여 필요한 패키지가 설치 되어 있는지 확인 합니다.

사용명령어: aws --version && sam --version && docker --version && node --version && npm --version

그럼 이제 새로운 sam( Serverless Application Model)을 이용하여 함수를 생성해 봅시다.

SAM은 서버리스 어플리케이션을 구축하는데 사용하는 오픈 소스 프레임 워크 입니다.

어플리케이션을 빠르게 작성, 테스트 디버깅 하는 기능을 제공 하고, Lamda 함수관리, 구축, 배포의 기능도 제공을 해줍니다. 이제 아래의 명령을 사용해서 SAM을 초기화 합니다.

아래의 명령을 실행하고, 아래의 값처럼 선택을 합니다.

WSLabsUser-iDzejQkKV36rpUnTDYJvGZ:~/environment $ sam init
SAM CLI now collects telemetry to better understand customer needs.
You can OPT OUT and disable telemetry collection by setting the
environment variable SAM_CLI_TELEMETRY=0 in your shell.
Thanks for your help!
You can preselect a particular runtime or package type when using the `sam init` experience.
Call `sam init --help` to learn more.
Which template source would you like to use?
1 - AWS Quick Start Templates
2 - Custom Template Location
Choice: 1
Choose an AWS Quick Start application template
1 - Hello World Example
2 - Multi-step workflow
3 - Serverless API
4 - Scheduled task
5 - Standalone function
6 - Data processing
7 - Infrastructure event management
8 - Serverless Connector Hello World Example
9 - Multi-step workflow with Connectors
10 - Lambda EFS example
11 - Machine Learning
Template: 1
Use the most popular runtime and package type? (Python and zip) [y/N]: N
Which runtime would you like to use?
1 - aot.dotnet7 (provided.al2)
2 - dotnet6
3 - dotnet5.0
4 - dotnetcore3.1
5 - go1.x
6 - go (provided.al2)
9 - java11
10 - java8.al2
11 - java8
12 - nodejs18.x
13 - nodejs16.x
14 - nodejs14.x
15 - nodejs12.x
16 - python3.9
17 - python3.8
18 - python3.7
19 - ruby2.7
20 - rust (provided.al2)
Runtime: 15
What package type would you like to use?
1 - Zip
2 - Image
Package type: 2
Based on your selections, the only dependency manager available is npm.
We will proceed copying the template using npm.
Would you like to enable X-Ray tracing on the function(s) in your application? [y/N]: N
Would you like to enable monitoring using CloudWatch Application Insights?
Project name [sam-app]: getletter
-----------------------
Generating application:
-----------------------
Name: getletter
Base Image: amazon/nodejs12.x-base
Architectures: x86_64
Dependency Manager: npm
Output Directory: .
Next steps can be found in the README file at ./getletter/README.md
 
Commands you can use next
=========================
[*] Create pipeline: cd getletter && sam pipeline init --bootstrap
[*] Validate SAM template: cd getletter && sam validate
[*] Test Function in the Cloud: cd getletter && sam sync --stack-name {stack-name} --watch
SAM CLI update available (1.90.0); (1.72.0 installed)
AWSLabsUser-iDzejQkKV36rpUnTDYJvGZ:~/environment $

그럼 이제 아래 그림과 같이 왼쪽 탐색창에 getletter이라는 디렉토리가 표시가 됩니다.

화살표를 클릭을 해보면 폴더의 내용을 아래와 같이 확인할 수 있습니다.

반응형

프로젝트에서 template.yaml파일을 열고,, 아래의 코드내용을 template.yaml파일의 내용과 바꿉니다.

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
getletter
SAM Template for our letter writer
Globals:
Function:
Timeout: 5
Resources:
GetLetter:
Type: AWS::Serverless::Function
Properties:
PackageType: Image
Role: !Sub 'arn:aws:iam::${AWS::AccountId}:role/lambda-execution-role'
Metadata:
DockerTag: nodejs12.x-v1
DockerContext: ./hello-world
Dockerfile: Dockerfile
Outputs:
GetLetter:
Description: "Letter Writer Lambda Function ARN"
Value: !GetAtt GetLetter.Arn

Hello-world폴더 옆의 화살표를 클릭하고 app.js파일을 엽니다. 파일의 기존코드를 아래와 코드로 바꿉니다..

const PDFDocument = require('pdfkit');
const faker = require('faker');
const getStream = require('get-stream');
exports.lambdaHandler = async (event) => {
const doc = new PDFDocument();
const randomName = faker.name.findName();
// const letterdate = new Date(faker.date.past()).toLocaleDateString('en-us');
doc.text(randomName, { align: 'right' });
doc.text(faker.address.streetAddress(), { align: 'right' });
doc.text(faker.address.secondaryAddress(), { align: 'right' });
doc.text(faker.address.zipCode() + ' ' + faker.address.city(), { align: 'right' });
doc.moveDown();
// doc.text(letterdate, { align: 'left' });
// doc.moveDown();
doc.text('Dear ' + randomName + ',');
doc.moveDown();
for(let i = 0; i < 3; i++) {
doc.text(faker.lorem.paragraph());
doc.moveDown();
}
doc.text(faker.name.findName(), { align: 'right' });
doc.end();
pdfBuffer = await getStream.buffer(doc);
pdfBase64 = pdfBuffer.toString('base64');
const response = {
statusCode: 200,
headers: {
'Content-Length': Buffer.byteLength(pdfBase64),
'Content-Type': 'application/pdf',
'Content-disposition': 'attachment;filename=test.pdf'
},
isBase64Encoded: true,
body: pdfBase64
};
return response;
};

이 코드는 PDF형식으로 가상의 편지를 생상하면 나중에 LAMDA에 배포를 합니다.

이제 cd hello-world 명령어로 디렉토리를 변경 합니다.

아래의 명령으로 터미널에서 필요한 패키지를 설치 합니다.

npm init -y && npm install pdfkit faker get-stream

이제까지 SAM CLI를 사용해서 Image 패키지 유형으로 어플리케이션을 초기화 했고, 템플릿이 구성되었고, 컨테이너에 필요한 DockerFile도 생성이 되었습니다.

Dockerfilr을 열고 아래의 내용으로 코드를 변경 합니다.

FROM public.ecr.aws/lambda/nodejs:12

COPY app.js package.json ./

RUN npm install

CMD [ "app.lambdaHandler" ]

이제 아래 명령을 사용하여 새로운 Image를 생성 합니다.

docker build -t getletter .

이제 생성된 이미지 확인을 위해서 아래 명령어를 입력 합니다.

명령어. docker images

이제 Image가 만들어 졌으므로, 테스트를 위해 아래 명령을 이용해 컨테이너를 실행해 봅니다.

docker run -p 9000:8080 getletter:latest

위의 명령을 실행하면 컨테이너가 실행 중이라 터미널이 대기 상태가 됩니다.

위에서 도커 컨테이너 이미지에 Lamda기본 이미지를 사용하도록 지정했고. Lamda기본 이미지에는 Runtime Interface Emulator라는 구성 요소가 포함이 되어 있습니다.

RIE는 Lamda 런타임 API의 Proxy 입니다. 이 이미지는 HTTP 요청을 컨테이너 이미지의 lAMDA 함수에 전달할 json 이벤트로 변환해주는 가벼운 웹서버의 역활을 합니다.

이제 도커 컨테이너가 실행 중이고 기본 이미지에 포함된 Lambda RIE도 실행 중이므로 AWS Lambda 서비스에서 테스트할 필요 없이 로컬에서 함수를 테스트할 수 있습니다.

새 터미널 창을 열고 다음 코드를 실행하여 Lambda RIE를 사용한 테스트 호출을 아래 명령을 통해 실행을 하고 docker를 실행한 터미널에서 로그를 확인 합니다

curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'

curl을 실행 시킨 터미널 창을 닫고

docker - 라는 제목의 이전 터미널 창으로 돌아가서 CTRL + C를 눌러 현재 도커 프로세스를 중단합니다.

다음 명령을 사용하여 getletter 디렉터리로 이동하고 AWS SAM을 사용하여 컨테이너 이미지를 다시 빌드합니다

cd /home/ec2-user/environment/getletter

sam build

다음 명령을 사용하여 AWS SAM CLI로 함수를 테스트할 수도 있습니다.

sam local invoke GetLetter

이제 ECR Rrpogitory에 이미지를 푸쉬를 해보겠습니다.

아래의 명령으로 ECR을 생성을 합니다.

aws ecr create-repository \

--repository-name getletter \

--image-scanning-configuration scanOnPush=true

ECR에 Push를 하기 위해 이미지에 tag를 아래의 명령을 이용해 답니다.

docker tag getletter:latest <repositoryUri> ==> uri는 앞에서 설정한 값으로 변경 하여 실행 합니다.

아래 명령을 이용해서 AWS ECR에 로그인을 합니다.

aws ecr get-login-password \

| docker login \

--username AWS \

--password-stdin <repositoryUri>

Login Succeded라는 메세지가 나옵니다.. ECR에 정상적으로 로그인을 했고. 이제 이미지를 Push하기 위해 아래 명령을 입력 합니다.

docker push <repositoryUri>:latest

이미지가 정상적으로 업로드 되었습니다.

SAM을 사용하여 위에서 진행한 작업을 한번에 할수 도 있습니다.

sam deploy \

--stack-name getletter \

--s3-bucket labstack-5e53b9c2-49e0-4900-804d-generatedbucket-gnbcuntf5pjn \

--capabilities CAPABILITY_NAMED_IAM CAPABILITY_AUTO_EXPAND \

--image-repository 521783210047.dkr.ecr.us-east-1.amazonaws.com/getletter

이제 LAMDA 함수에 API GATEWAY 트리거 추가해 보겠습니다.

AWS Console창으로 돌아가서 Lamda를 검색 합니다

Lamda를 클릭 해서 콘솔로 들어 갑니다.

아래 화면과 같이 왼쪽 메뉴에서 어플리케이션을 클릭 합니다.

.

SAM에 의해 생성된 새 애플리케이션인 getletter를 클릭합니다. Overview 페이지 하단으로 스크롤하고 Resources에서 GetLetter를 클릭합니다.

Overview에서 아래로 클릭한 다음 getletter를 클릭 합니다.

아래 화면 처럼 트리거 추가를 클릭 합니다.

소스에서 API Gateway를 선택 합니다.

아래와 같이 설정 후 추가버튼을 클릭 합니다.

구성 텝에서 트리거를 선택하고. API Endpoint를 복사를 합니다.

웹브라우저를 열어서 복사한 API Endpoint를 주소창에 붙여 넣습니다.

10~20초 안에 브라우저가 함수에 의해 생성된 PDF를 다운로드하기 시작하거나 새 창에 PDF를 표시합니다.

PDF를 열어 함수의 출력 파일을 확인합니다. 출력 PDF 파일은 생성된 자리 표시자 텍스트를 포함하며, 편지와 비슷합니다.

이제 어플리케이션 수정을 위해 cloud9 콘솔에서 app.js파일을 아래의 코드로 바꿉니다.

const PDFDocument = require('pdfkit');
const faker = require('faker');
const getStream = require('get-stream');
exports.lambdaHandler = async (event) => {
const doc = new PDFDocument();
const randomName = faker.name.findName();
const letterdate = new Date(faker.date.past()).toLocaleDateString('en-us');
doc.text(randomName, { align: 'right' });
doc.text(faker.address.streetAddress(), { align: 'right' });
doc.text(faker.address.secondaryAddress(), { align: 'right' });
doc.text(faker.address.zipCode() + ' ' + faker.address.city(), { align: 'right' });
doc.moveDown();
doc.text(letterdate, { align: 'left' });
doc.moveDown();
doc.text('Dear ' + randomName + ',');
doc.moveDown();
for(let i = 0; i < 3; i++) {
doc.text(faker.lorem.paragraph());
doc.moveDown();
}
doc.text(faker.name.findName(), { align: 'right' });
doc.end();
pdfBuffer = await getStream.buffer(doc);
pdfBase64 = pdfBuffer.toString('base64');
const response = {
statusCode: 200,
headers: {
'Content-Length': Buffer.byteLength(pdfBase64),
'Content-Type': 'application/pdf',
'Content-disposition': 'attachment;filename=test.pdf'
},
isBase64Encoded: true,
body: pdfBase64
};
return response;
};

함수가 변경되면 업데이트된 컨테이너 이미지를 다시 구축하고, 다시 태깅하고, 다시 배포해야 합니다. AWS SAM을 사용하면 이 작업을 자동으로 처리할 수 있습니다.

다음 명령을 실행하여 수정된 애플리케이션과 컨테이너 이미지를 구축합니다.

sam build

아래 명령을 이용해서 다시 실행 시키고 Lamda 콘솔에서 API Endpoint 값을 복사 후 웹 브라우저의 주소창에 다시 붙여서 변경된 사항이 반영이 되었는지 확인해 봅니다.

sam deploy \

--stack-name getletter \

--s3-bucket <S3Bucket> \

--capabilities CAPABILITY_NAMED_IAM CAPABILITY_AUTO_EXPAND \

--image-repository <repositoryUri>

그럼 변경된 사항이 반영된걸 확인할 수 있습니다.

이상 Lamda 사용 방법에 대해서 마무리 하도록 하겠습니다.

오늘도 도움이 되었다면, 구독과 광고 클릭 ^.^

즐거운 하루 되시고. 행복한 하루 되세요 ^.6

728x90
반응형