클라우드/AWS

[AWS] SAM - hello world Application 배포

dayeonsheep 2023. 10. 31. 18:09

SAM이란?

; Serverless Application Model

서버리스 애플리케이션을 빌드하고 실행하는 개발자 환경을 개선하는 툴킷

Cloud Formation과 마찬가지인 IaC인데, 얘는 서버리스 애플리케이션 관리 도와줌

 

  • 구축가능한 AWS 서비스의 종류
    • Lambda
    • API Gateway
    • DynamoDB

 

AWS SAM의 장점

  • AWS에서 서버리스 시스템을 구성할 때 필요한 CloudFormation 코드가 추상화되어 있어, 좀 더 직관적으로 서버리스를 구성할 수 있다
  • 기존의 CloudFormation 코드와 함께 사용이 가능하다
  • Local 환경에서 SAM 명령어를 통해 Lambda 함수를 테스트해 볼 수 있어 개발에 편리하고 번거로움을 대폭 줄일 수 있다

 

 

사전 서버리스 개념


이벤트 기반 아키텍처
  • 서버리스 애플리케이션은 AWS Lambda 컴퓨팅용 및 데이터베이스 관리용 Amazon DynamoDB와 같은 개별AWS 서비스로 구성되며 각 서비스는 특수한 역할을 수행합니다. 그런 다음 이러한 서비스는 이벤트 기반 아키텍처*를 통해 서로 느슨하게 통합됩니다. 

*이벤트 기반 아키텍처

- 이벤트를 사용하여 분리된 서비스를 서로 트리거하고 통신하며 마이크로서비스로 구축된 현대적 애플리케이션에서는 일반적

 

- 이벤트 생산자, 이벤트 라우터, 이벤트 소비자라는 세 가지 주요 요소로 구성됨

- 이벤트 = 전자상거래 웹 사이트에서 쇼핑 카트에 항목이 추가되는 것과 같은 상태의 변화 또는 업데이트

- 생산자는 라우터에 이벤트를 게시, 라우터는 이벤트를 필터링하여 소비자에 푸시, 생산자 서비스와 소비자 서비스는 서로 분리되므로 독립적으로 확장, 업데이트, 배포됨

 

 

코드형 인프라 (IaC)
  • Infrastructure as Code (IaC) 는 개발자가 코드를 처리하는 것과 동일한 방식으로 인프라를 처리하여 인프라 프로비저닝에도 동일한 엄격한 애플리케이션 코드 개발을 적용하는 방법 = 서버리스 애플리케이션 관리를 도와주는 서비스
  • 템플릿 파일에서 인프라를 정의하고, AWS에 배포하고, AWS는 리소스를 생성해 줍니다. IAC를 사용하면 프로비저닝할 대상을 코드로 정의할 수 있습니다.

 

Hello World 애플리케이션 배포하기

 

API Gateway를 통해 GET 요청을 보내면 Lambda 함수가 호출되고 이 Lambda 함수는 hello world라는 메세지를 반환

 

출처: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started-hello-world.html

 

 

1. AWS SAM CLI 설치

brew tap aws/tap
brew install aws-sam-cli

설치 확인:

$ sam --version
SAM CLI, version 1.35.0

 

 

2. AWS SAM 애플리케이션 다운로드

#Step 1 - 샘플 애플리케이션 다운로드
sam init

#Step 2 - 애플리케이션 빌드
cd sam-app
sam build

#Step 3 - 애플이케이션 배포
sam deploy --guided

 

 

2.1 sam init 

$ sam init
...
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 - Hello World Example With Powertools
    8 - Infrastructure event management
    9 - Serverless Connector Hello World Example
    10 - Multi-step workflow with Connectors
    11 - Lambda EFS example
    12 - DynamoDB Example
    13 - Machine Learning
Template: 1

Use the most popular runtime and package type? (Python and zip) [y/N]: y

Would you like to enable X-Ray tracing on the function(s) in your application?  [y/N]: 

Would you like to enable monitoring using CloudWatch Application Insights?
For more info, please view https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch-application-insights.html [y/N]: 

Project name [sam-app]:

 

출력 예제:

 -----------------------
 Generating application:
 -----------------------
 Name: sam-app
 Runtime: python3.7
 Dependency Manager: pip
 Application Template: hello-world
 Output Directory: .

 Next steps can be found in the README file at ./sam-app/README.md

 

 

AWS SAM이 하는 것: 입력한 프로젝트 이름으로 디렉터리 생성

$ cd sam-app

$ tree

sam-app/
   ├── README.md
   ├── events/
   │   └── event.json
   ├── hello_world/
   │   ├── __init__.py
   │   ├── app.py            #Contains your AWS Lambda handler logic.
   │   └── requirements.txt  #Contains any Python dependencies the application requires, used for sam build
   ├── template.yaml         #Contains the AWS SAM template defining your application's AWS resources.
   └── tests/
       └── unit/
           ├── __init__.py
           └── test_handler.py

(참고: 이 샘플은 Python runtime에 Hello World Example을 선택한 경우)

  • template.yaml : 애플리케이션 인프라 코드가 들어있는 AWS 리소스를 정의하는 AWS SAM 템플릿입니다.
  • hello_world/app.py : 실제 Lambda 함수를 포함합니다.
  • hello_world/requirements.txt : sam build시에 사용할 애플리케이션에 필요한 모든 파이썬 종석성을 관리합니다. (노드로 선택한 경우 package.json)
  • samconfig.toml : AWS SAM CLI에서 사용하는 기본 파라미터를 저장하는 애플리케이션의 구성 파일입니다. 

 

3. 애플리케이션 빌드

$ sam build

sam build 명령어는 애플리케이션을 .aws-sam/build 폴더 아래에 압축하고 Lambda에 업로드 할 수 있도록 합니다.

 

출력 예제:

 Build Succeeded

 Built Artifacts  : .aws-sam/build
 Built Template   : .aws-sam/build/template.yaml

 Commands you can use next
 =========================
 [*] Invoke Function: sam local invoke
 [*] Deploy: sam deploy --guided

 

CLI에서 생성한 .aws-sam 디렉토리의 축약된 AWS SAM 예:

.aws-sam
├── build
│   ├── HelloWorldFunction //HelloWorldFunction은 app.py와 써드파티 종속성이 포함된 디렉토리 입니다. 
│   │   ├── __init__.py
│   │   ├── app.py
│   │   └── requirements.txt
│   └── template.yaml
└── build.toml

.aws-sam 폴더 아래에 위와 같은 구조로 표기됩니다.

 

AWS SAM이 하는 것:

종속성 관리를 위한 추상화된 Lambda 함수가 제공하며, 패키징과 배포를 위해서 모든 소스코드들을 스테이징 폴더에 복사해둡니다. 

 

 

4. AWS 클라우드에 애플리케이션 배포하기

$ sam deploy --guided

 

 

AWS SAM CLI 대화형 흐름에 따라 애플리케이션 설정 구성해야할 것

sam-app sam deploy --guided

Configuring SAM deploy
======================

    Looking for config file [samconfig.toml] :  Found
    Reading default arguments  :  Success

    Setting default arguments for 'sam deploy'
    =========================================
    Stack Name [sam-app]:
    AWS Region [us-west-2]:
    #Shows you resources changes to be deployed and require a 'Y' to initiate deploy
    Confirm changes before deploy [Y/n]: n
    #SAM needs permission to be able to create roles to connect to the resources in your template
    Allow SAM CLI IAM role creation [Y/n]: 
    #Preserves the state of previously provisioned resources when an operation fails
    Disable rollback [y/N]: 
    HelloWorldFunction may not have authorization defined, Is this okay? [y/N]: y
    Save arguments to configuration file [Y/n]: 
    SAM configuration file [samconfig.toml]:
    SAM configuration environment [default]:

 

  1. AWS CloudFormation 스택 이름 
  2. AWS 리전
  3. 배포하기 전에 변경 사항 확인
  4. IAM 역할 생성 허용
  5. 롤백 비활성화
  6. 승인 HelloWorldFunction 없이 허용 정의 
  7. 구성 파일에 인수 저장 
  8. 기본 구성 파일 이름을 선택
  9. 기본 구성 환경을 선택

 

출력 예제:

 Deploying with following values
    ===============================
    Stack name                 : sam-app
    Region                     : us-east-1
    Confirm changeset          : False
    Deployment s3 bucket       : sam-bucket
    Capabilities               : ["CAPABILITY_IAM"]
    Parameter overrides        : {}

 Initiating deployment
 =====================

 Waiting for changeset to be created..

 CloudFormation stack changeset
 ---------------------------------------------------------------------------------------------------------------------------------------------------
 Operation                                         LogicalResourceId                                 ResourceType
 ---------------------------------------------------------------------------------------------------------------------------------------------------
 + Add                                             HelloWorldFunctionHelloWorldPermissionProd        AWS::Lambda::Permission
 + Add                                             ServerlessRestApiDeployment47fc2d5f9d             AWS::ApiGateway::Deployment
 + Add                                             ServerlessRestApiProdStage                        AWS::ApiGateway::Stage
 + Add                                             ServerlessRestApi                                 AWS::ApiGateway::RestApi
 * Modify                                          HelloWorldFunctionRole                            AWS::IAM::Role
 * Modify                                          HelloWorldFunction                                AWS::Lambda::Function
 ---------------------------------------------------------------------------------------------------------------------------------------------------

 2019-11-21 14:33:24 - Waiting for stack create/update to complete

 CloudFormation events from changeset
 -------------------------------------------------------------------------------------------------------------------------------------------------
 ResourceStatus                       ResourceType                         LogicalResourceId                    ResourceStatusReason
 -------------------------------------------------------------------------------------------------------------------------------------------------
 UPDATE_IN_PROGRESS                   AWS::IAM::Role                       HelloWorldFunctionRole               -
 UPDATE_COMPLETE                      AWS::IAM::Role                       HelloWorldFunctionRole               -
 UPDATE_IN_PROGRESS                   AWS::Lambda::Function                HelloWorldFunction                   -
 UPDATE_COMPLETE                      AWS::Lambda::Function                HelloWorldFunction                   -
 CREATE_IN_PROGRESS                   AWS::ApiGateway::RestApi             ServerlessRestApi                    -
 CREATE_COMPLETE                      AWS::ApiGateway::RestApi             ServerlessRestApi                    -
 CREATE_IN_PROGRESS                   AWS::ApiGateway::RestApi             ServerlessRestApi                    Resource creation Initiated
 CREATE_IN_PROGRESS                   AWS::ApiGateway::Deployment          ServerlessRestApiDeployment47fc2d5   Resource creation Initiated
                                                                          f9d
 CREATE_IN_PROGRESS                   AWS::Lambda::Permission              HelloWorldFunctionHelloWorldPermis   Resource creation Initiated
                                                                          sionProd
 CREATE_IN_PROGRESS                   AWS::Lambda::Permission              HelloWorldFunctionHelloWorldPermis   -
                                                                          sionProd
 CREATE_IN_PROGRESS                   AWS::ApiGateway::Deployment          ServerlessRestApiDeployment47fc2d5   -
                                                                          f9d
CREATE_COMPLETE                      AWS::ApiGateway::Deployment          ServerlessRestApiDeployment47fc2d5   -
                                                                          f9d
 CREATE_IN_PROGRESS                   AWS::ApiGateway::Stage               ServerlessRestApiProdStage           -
 CREATE_IN_PROGRESS                   AWS::ApiGateway::Stage               ServerlessRestApiProdStage           Resource creation Initiated
 CREATE_COMPLETE                      AWS::ApiGateway::Stage               ServerlessRestApiProdStage           -
 CREATE_COMPLETE                      AWS::Lambda::Permission              HelloWorldFunctionHelloWorldPermis   -
                                                                          sionProd
 UPDATE_COMPLETE_CLEANUP_IN_PROGRES   AWS::CloudFormation::Stack           sam-app                              -
 S
 UPDATE_COMPLETE                      AWS::CloudFormation::Stack           sam-app                              -
 -------------------------------------------------------------------------------------------------------------------------------------------------

 Stack sam-app outputs:
 ---------------------------------------------------------------------------------------------------------------------------------------------------
 OutputKey-Description                                                     OutputValue
 ---------------------------------------------------------------------------------------------------------------------------------------------------
 HelloWorldFunctionIamRole - Implicit IAM Role created for Hello World     arn:aws:iam::123456789012:role/sam-app-
 function                                                                  HelloWorldFunctionRole-104VTJ0TST7M0
 HelloWorldApi - API Gateway endpoint URL for Prod stage for Hello World   https://0ks2zue0zh.execute-api.us-east-1.amazonaws.com/Prod/hello/
 function
 HelloWorldFunction - Hello World Lambda Function ARN                      arn:aws:lambda:us-east-1:123456789012:function:sam-app-
                                                                          HelloWorldFunction-1TY92MJX0BXU5
 ---------------------------------------------------------------------------------------------------------------------------------------------------

 Successfully created/updated stack - sam-app in us-east-1

 

5. 애플리케이션 실행

API 엔드포인트에 GET 요청을 보내고 Lambda 함수 출력을 확인 단계

 

API 엔드포인트 값 가져오기

5.1.1  이전 단계에서 표시된 AWS SAM CLI 정보에서 Outputs 섹션을 찾습니다.

->  HelloWorldApi 리소스를 찾아 HTTP 엔드포인트 값을 찾기

 

출력 예제:

----------------------------------------------------------------------------------------------------------------------------------------------
Outputs
----------------------------------------------------------------------------------------------------------------------------------------------
...
Key                 HelloWorldApi
Description         API Gateway endpoint URL for Prod stage for Hello World function
Value               https://ets1gv8lxi.execute-api.us-west-2.amazonaws.com/Prod/hello/
...
----------------------------------------------------------------------------------------------------------------------------------------------

 

5.1.2  명령어 사용해서 가져오기

$sam list endpoints --output json

2023-03-15 12:39:19 Loading policies from IAM...
2023-03-15 12:39:25 Finished loading policies from IAM.
[
  {
    "LogicalResourceId": "HelloWorldFunction",
    "PhysicalResourceId": "sam-app-HelloWorldFunction-yQDNe17r9maD",
    "CloudEndpoint": "-",
    "Methods": "-"
  },
  {
    "LogicalResourceId": "ServerlessRestApi",
    "PhysicalResourceId": "ets1gv8lxi",
    "CloudEndpoint": [
      "https://ets1gv8lxi.execute-api.us-west-2.amazonaws.com/Prod",
      "https://ets1gv8lxi.execute-api.us-west-2.amazonaws.com/Stage"
    ],
    "Methods": [
      "/hello['get']"
    ]
  }
]

 

5.2  함수 호출하기

$ curl https://ets1gv8lxi.execute-api.us-west-2.amazonaws.com/Prod/hello/
{"message": "hello world"}

 

6. AWS 클라우드에서 Lambda 함수 호출

 

6.1 sam-app 프로젝트 디렉터리에서 실행하기

$ sam remote invoke HelloWorldFunction --stack-name sam-app

 

6.2 AWS SAM CLI 호출하고 응답을 반환하기

출력 예제:

$ sam remote invoke HelloWorldFunction --stack-name sam-app

Invoking Lambda Function HelloWorldFunction                                       
START RequestId: d5ef494b-5f45-4086-86fd-d7322fa1a1f9 Version: $LATEST
END RequestId: d5ef494b-5f45-4086-86fd-d7322fa1a1f9
REPORT RequestId: d5ef494b-5f45-4086-86fd-d7322fa1a1f9  Duration: 6.62 ms       Billed Duration: 7 ms     Memory Size: 128 MB     Max Memory Used: 67 MB  Init Duration: 164.06 ms
{"statusCode":200,"body":"{\"message\":\"hello world\"}"}%

 

7. 애플리케이션 수정 및 동기화

 

7.1 로컬 변경 내용을 AWS 클라우드에 동기화하기

sam-app 프로젝트 디렉터리에서 다음 명령어 실행

$ sam sync --watch

 

출력 예제:

$ sam sync --watch

The SAM CLI will use the AWS Lambda, Amazon API Gateway, and AWS StepFunctions APIs to upload your code without
performing a CloudFormation deployment. This will cause drift in your CloudFormation stack.
**The sync command should only be used against a development stack**.

Confirm that you are synchronizing a development stack.

Enter Y to proceed with the command, or enter N to cancel:
 [Y/n]: y
Queued infra sync. Waiting for in progress code syncs to complete...
Starting infra sync.
Manifest is not changed for (HelloWorldFunction), running incremental build
Building codeuri: /Users/.../Demo/sam-tutorial1/sam-app/hello_world runtime: python3.9 metadata: {} architecture: x86_64 functions: HelloWorldFunction
Running PythonPipBuilder:CopySource

Build Succeeded

Successfully packaged artifacts and wrote output template to file /var/folders/45/5ct135bx3fn2551_ptl5g6_80000gr/T/tmpq3x9vh63.
Execute the following command to deploy the packaged template
sam deploy --template-file /var/folders/45/5ct135bx3fn2551_ptl5g6_80000gr/T/tmpq3x9vh63 --stack-name <YOUR STACK NAME>


    Deploying with following values
    ===============================
    Stack name                   : sam-app
    Region                       : us-west-2
    Disable rollback             : False
    Deployment s3 bucket         : aws-sam-cli-managed-default-samclisourcebucket-1a4x26zbcdkqr
    Capabilities                 : ["CAPABILITY_NAMED_IAM", "CAPABILITY_AUTO_EXPAND"]
    Parameter overrides          : {}
    Signing Profiles             : null

Initiating deployment
=====================


2023-03-15 13:10:05 - Waiting for stack create/update to complete

CloudFormation events from stack operations (refresh every 0.5 seconds)
---------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus                      ResourceType                        LogicalResourceId                   ResourceStatusReason
---------------------------------------------------------------------------------------------------------------------------------------------
UPDATE_IN_PROGRESS                  AWS::CloudFormation::Stack          sam-app                             Transformation succeeded
CREATE_IN_PROGRESS                  AWS::CloudFormation::Stack          AwsSamAutoDependencyLayerNestedSt   -
                                                                        ack
CREATE_IN_PROGRESS                  AWS::CloudFormation::Stack          AwsSamAutoDependencyLayerNestedSt   Resource creation Initiated
                                                                        ack
CREATE_COMPLETE                     AWS::CloudFormation::Stack          AwsSamAutoDependencyLayerNestedSt   -
                                                                        ack
UPDATE_IN_PROGRESS                  AWS::Lambda::Function               HelloWorldFunction                  -
UPDATE_COMPLETE                     AWS::Lambda::Function               HelloWorldFunction                  -
UPDATE_COMPLETE_CLEANUP_IN_PROGRE   AWS::CloudFormation::Stack          sam-app                             -
SS
UPDATE_COMPLETE                     AWS::CloudFormation::Stack          sam-app                             -
---------------------------------------------------------------------------------------------------------------------------------------------

CloudFormation outputs from deployed stack
----------------------------------------------------------------------------------------------------------------------------------------------
Outputs
----------------------------------------------------------------------------------------------------------------------------------------------
Key                 HelloWorldFunctionIamRole
Description         Implicit IAM Role created for Hello World function
Value               arn:aws:iam::012345678910:role/sam-app-HelloWorldFunctionRole-15GLOUR9LMT1W

Key                 HelloWorldApi
Description         API Gateway endpoint URL for Prod stage for Hello World function
Value               https://ets1gv8lxi.execute-api.us-west-2.amazonaws.com/Prod/hello/

Key                 HelloWorldFunction
Description         Hello World Lambda Function ARN
Value               arn:aws:lambda:us-west-2:012345678910:function:sam-app-HelloWorldFunction-yQDNe17r9maD
----------------------------------------------------------------------------------------------------------------------------------------------


Stack update succeeded. Sync infra completed.

Infra sync completed.
CodeTrigger not created as CodeUri or DefinitionUri is missing for ServerlessRestApi.

 

애플리케이션 수정하고 동기화하려면

 

1. 선택한 IDE에서 sam-app/hello_world/app.py 파일 열기

2. 메시지 변경하고 저장하기

 

변경 예시

import json
...
def lambda_handler(event, context):
    ...
    return {
        "statusCode": 200,
        "body": json.dumps({
            "message": "hello everyone!",
            ...
        }),
    }

 

3. 변경 내용 확인하기

$ curl https://ets1gv8lxi.execute-api.us-west-2.amazonaws.com/Prod/hello/

{"message": "hello everyone!"}

 

 

 


[SAM - Lambda - Local S3 이용한 프로젝트 추가 공부해보기 내용]

 

  • RIE / RIC - 샘이라는 걸 활용해서 로컬에서 람다서비스를 이용하기 위해 등장하는 단어

 

  • 샘은 내부적으로 어떻게 도커 컨테이너 이미지를 만들 수 있을까? -> 도커 api 찔러서 만든다
  • Aws sam 내장 ric가 포함된 람다 베이스 이미지를 사용함

 

  • Aws sam이 내부적으로 rie를 사용하는 방법: 모방된 api gateway에서 호출하는 rie 엔드포인트

 

  • 어째서 빌드를 강제화 하지?

매번 빌드를 다시해줘야한다는 오류가 문제인데

베이스 이미지가 변경되면 전체 컨테이너 파일도 재빌드 되는 거 아닌가? 라고 예상되는데

내부적으로 이미지 빌드 조건을 다루는 방식이 다르게 되어 있는데

샘 패키지 유형이 이미지일 경우에는 skippullimage를 트루로 할당해서

그 메서드 내부를  베이스 이미지의 변경이 있을 경우 재빌드 플래그 설정하는데

실제 스킵풀이미지를 트루로 할당 되었기 때문에 넘겨버림

그래서 재빌드 플래그가 flase로 설정 되어 있기 때문에 빌드를 생략하게 됨

 

  • Cloudformation YAML 문법을 활용해서 람다함수를 정의할 수 있음
  • sam을 활용해서 RIE라는 에뮬레이터를 통해 로컬에서 람다함수 실행 가능
  • 로컬스택을 활용해서 로컬 환경에 s3를 구축하고 사용가능
  • sam은 내부적으로 플라스크 프레임워크 사용해서 api gateway 모방
  • 람다 함수는 수용가능한 페이로드 크기 한계 오류 메시지 유의
  • 람다 베이스 이미지 활용해서 도커파일로 람다함수 만들 수 있음
  • 람다함수 실행할 때 내부적 재빌드 생략을 유의해야함
  • JSON 객체 형식의 S3 이벤트를 정의하고 이를 통해 람다 함수를 실행할 수 있음 통해 Lambda 함수를 실행할 수
 

 


[참고 문헌]