공부하기싫어
article thumbnail

#AWS Certified Developer Associate

 

 

 

356. AWS SAM - 섹션 소개

SAM 은 애플리케이션이 작동하고 배포되어야 하는 방향에 맞는 YAML 파일과 템플릿 작성을 지원함

cloudformation 실행을 간단히 한 것이지만 개발자 친화적이며 aws 내에서도 주류로 자리잡고 있다고 함

 

 

 

357. SAM (AWS Serverless Apllication Model) 개요

서버리스 애플리케이션 개발 및 배포를 위한 프레임워크

모든 구성은 YAML 형식으로 실행됨

- 간단한 yaml 파일을 통해서 SAM CLI 를 활용한 복잡한 CloudFormation 템플릿을 생성할 수 있음

CloudFormation 과 호환이 가능하므로 모든 CloudFormation 구조를 실시할 수 있음

- outputs, mappings, parameters, resources 등

aws 에 배포하기 위한 2가지 명령

SAM 에서 CodeDeploy 로 람다 함수를 배포하고 버전 간 트래픽이 점진적으로 변하는지 확인 가능

SAM 을 이용해서 람다, api gateway, DynamoDB 를 로컬에서 실행할 수 있으므로 애플리케이션 테스트를 위해 aws 에 배포할 필요가 없음

 

Recipe

Transform 헤더 : 'AWS::Serverless-2016-10-31'

이 헤더는 SAM 템플릿을 나타내며 CloudFormation 은 이 템플릿을 CloudFormation 용 템플릿으로 변환할 수 있음

YAML 파일 내 코드 :

- AWS::Serverless::Function

- AWS::Serverless::Api

- AWS::Serverless::SimpleTable

 

Package & Deploy : (패키징과 배포를 위한 2가지 명령)

- aws cloudformation package / sam package

- aws cloudformation deploy / sam deploy

 

 

SAM - CLI Debugging

SAM CLI 를 통해 로컬에 람다와 같은 실행 환경을 갖출 수 있음

SAM CLI + AWS Toolkits 를 사용해 코드를 천천히 살펴보고 디버깅 하는 방식 사용

- aws 에 배포하는일 없이 lambda 를 사용한 개발을 로컬에서 완료 가능

SAM CLI 를 지원하는 IDE

- Cloud9, VSC, JetBrains, PyCharm, IntelliJ 등

- SAM CLI 와 IDE 를 함께 사용하면 람다 함수를 로컬 컴퓨터에서 실행할 수 있고 디버깅 또한 가능함

 

 

 

358. SAM CLI 설치

개발을 데스크탑에서 주로 하기때문에 window 에 설치해줬다

 

구글에 SAM framwork cli install 검색

https://docs.aws.amazon.com/ko_kr/serverless-application-model/latest/developerguide/install-sam-cli.html

 

AWS SAM CLI 설치 - AWS Serverless Application Model

sam명령을 사용하여AWS SAM CLI를 호출하기 위해 설치 프로그램은 선택한 설치 폴더/usr/local/aws-sam-cli/sam 또는 둘 중 하나 또는 폴더/usr/local/bin/sam 사이에 심볼릭 링크를 자동으로 생성합니다.

docs.aws.amazon.com

사전 설정인 aws cli 를 최신버전으로 업데이트 해주고 진행했다

 

aws 가 버전 1이 아나콘다 파일에 설치되어있어서 pip을 이용해서 제거해주고 최신버전으로 다시 설치해줬다

https://docs.aws.amazon.com/ko_kr/cli/v1/userguide/install-windows.html#awscli-install-windows-pip

 

Windows에서 AWS CLI 버전 1 설치, 업데이트 및 제거 - AWS Command Line Interface

이러한 구성 및 자격 증명 설정은 모든 AWS SDK 및 AWS CLI에서 공유됩니다. 이 폴더를 제거하면 아직 시스템에 있는 AWS SDK에서 액세스할 수 없습니다.

docs.aws.amazon.com

 

aws configure 로 내가 사용하는 2개의 aws 계정을 각각 profile 로 입력해줬다

default 는 프로젝트용, aws-student profile 을 따로 만들었다

 

 

 

 

359. 첫 번째 SAM 프로젝트 생성

먼저 작업 디렉토리를 하나 만들어주고

src 디렉토리를 하나 만들고 그 안에 app.py 를 하나 생성

이후 작업 디렉토리 상단에 template.yaml 파일과 commands.sh 파일을 하나씩 생성해줬다

 

이후 amazon archives 에서 serverless-app-examples 에서 python 예제를 다운받는다고 한다

https://github.com/amazon-archives/serverless-app-examples/tree/master/python

 

GitHub - amazon-archives/serverless-app-examples

Contribute to amazon-archives/serverless-app-examples development by creating an account on GitHub.

github.com

 

여기서 hello-world-python3 로 들어가서

 

lambda_function.py 의 내용을 작업 디렉토리의 app.py 에 붙여넣고

template.yaml 의 내용은 template.yaml 에 붙여넣어줬다

 

app.py , template.yaml

app.py 의 함수 부분은 간단하게 hello world 만 반환하도록 바꿨다

 

template.yaml 파일을 살펴본다고 함

 

맨위에 버전은 cloudformation 템플릿을 나타냄

Transform 을 보면 sam 템플릿을 사용하는 것을 알 수 있다

- 위에서 설명 transform 헤더

Parameters 부분은 실습을 간단히 하기 위해 모두 삭제

 

리소스 부분에서 1개 리소스가 정의되어있는데, 타입으로 서버리스 함수라고 정의되어있다

속성으로 내려가서

람다함수가 핸들러를 갖는다고 나와있다

- 핸들러는 파일이름.함수이름 의 형식을 따라야 한다

런타임은 그대로 두고

CodeUri 는 소스 디렉토리 내에 있으니 src/ 라고 바꿔줌

- CodeUri 는 코드가 있는 로컬 위치를 나타냄

메모리 사이즈와 타임아웃은 그대로 사용함

기존 코드의 정책은 사용하지 않으니 삭제한다고 함

 

실습에 사용할 template.yaml

 

 

360. SAM 프로젝트 배포

먼저 commands.sh 파일로 가서 S3 버킷을 생성한다고 함

 

D:\DEV\General\aws-sam-Training>aws s3 mb s3://yeonwoo-code-sam --profile aws-student
make_bucket: yeonwoo-code-sam

D:\DEV\General\aws-sam-Training>

버킷 생성

이후 패키징을 위해 aws cloudformation package 명령어를 사용할텐데

이를 위한 옵션을 help 로 살펴봤다

 

Synopsis
********

     package
   --template-file <value>
   --s3-bucket <value>
   [--s3-prefix <value>]
   [--kms-key-id <value>]
   [--output-template-file <value>]
   [--use-json]
   [--force-upload]
   [--metadata <value>]
   [--debug]
   [--endpoint-url <value>]
   [--no-verify-ssl]
   [--no-paginate]
   [--output <value>]
   [--query <value>]
   [--profile <value>]
   [--region <value>]
   [--version <value>]
   [--color <value>]
   [--no-sign-request]
   [--ca-bundle <value>]
   [--cli-read-timeout <value>]
   [--cli-connect-timeout <value>]
   [--cli-binary-format <value>]
   [--no-cli-pager]
   [--cli-auto-prompt]
   [--no-cli-auto-prompt]

필수인 버킷 이름과 템플릿 파일을 입력해주고

이후 변환한 파일을 저장할 경로와 파일명을 입력해주고 실행

 

이걸로 코드가 s3 에 업로드 되었다고 한다

로컬에서도 변환된 파일이 저장된것을 확인할 수 있다

 

변환된 템플릿 파일

코드 uri 가 s3 버킷 객체를 가리키고 있다

 

버킷

버킷 안에서도 내용을 확인할 수 있다

 

위 명령 실행의 결과에서 배포를 위해 아래 명령을 실행하라고 나오는데

그대로 실행하면 Requires capabilities : [CAPABILITY_IAM] 라고 나오면서 failed 된다

그래서 명령문에 기능을 추가해줘야 한다

 

D:\DEV\General\aws-sam-Training>aws cloudformation deploy --template-file gen/template-generated.yaml --stack-name hello-world-sam --capabilities CAPABILITY_IAM --profile aws-student

Waiting for changeset to be created..
Waiting for stack create/update to complete

 

이렇게 추가해주면 생성 및 업데이트 단계로 넘어간다

 

강의에선 스택 생성에 성공했지만 나는 실패했다

이벤트를 뜯어보니

 

python 3.6

런타임 버전을 지원안한다고 한다

3.9로 바꿔서 다시 해보자

cloudformation 으로 가서 롤백된 스택을 지워주고 다시 명령어 실행

 

cloudformation stack

 

cloudformation resource

lambda 함수와 iam role 리소스 2개가 잘 생성된 것을 확인할 수 있다

 

 

lambda function

로컬에서 작성했던 app.py 가 잘 들어가있는 것을 확인할 수 있다

 

 

 

(2.26 끝)

 

(2.28 시작)

361. SAM API Gateway

간단히 sam 파일에 api gateway stage 를 추가하는 실

함수 전에 api gateway 를 설정한다고 한다

다시 예제 github 로 가서 api gateway 예제를 찾아서 붙여넣는다고 함

 

https://github.com/amazon-archives/serverless-app-examples/tree/master/python/microservice-http-endpoint-python3

 

GitHub - amazon-archives/serverless-app-examples

Contribute to amazon-archives/serverless-app-examples development by creating an account on GitHub.

github.com

 

먼저 여기서 lambda_function.py 를 작업 디렉토리의 app.py 로 붙여넣기 하고 필요한 부분만 사용한다고 함

 

수정한 app.py

import boto3
import json
import os

print('Loading function')


# 오류나 결과를 반환하는 함수
# 양식 자체도 api gateway 에서 사용하는 양식
def respond(err, res=None):
    return {
        'statusCode': '400' if err else '200',
        'body': err.message if err else json.dumps(res),
        'headers': {
            'Content-Type': 'application/json',
        },
    }


def lambda_handler(event, context):
    print("Received event: " + json.dumps(event, indent=2))
    return respond(None, res="hello world!")

 

이제 template.yaml 에 api gateway 정보를 붙여넣어준다고 함

 

수정된 template.yaml

# SAM FILE
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: A starter AWS Lambda function.
Resources:
  helloworldpython3:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: app.lambda_handler
      Runtime: python3.9
      CodeUri: src/
      Description: A starter AWS Lambda function.
      MemorySize: 128
      Timeout: 3
      Events:
        HelloWorldSAMAPI:
          Type: Api
          Properties:
            Path: /hello
            Method: GET

 

기존 코드에 아래 events 항목을 더해줬다

 

이제 cloudformation package 를 실행해서 아티팩트를 업로드하고 생성된 탬플릿을 업데이트 되도록 명령을 다시 실행한다

 

cloudformation package 명령

aws cloudformation package --s3-bucket yeonwoo-code-sam --template-file template.yaml --output-template-file gen/template-generated.yaml --profile aws-student

 

위 명령을 실행하면 template-generated.yaml 이 업데이트 된다

 

업데이트된 template-generated.yaml

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: A starter AWS Lambda function.
Resources:
  helloworldpython3:
    Type: AWS::Serverless::Function
    Properties:
      Handler: app.lambda_handler
      Runtime: python3.9
      CodeUri: s3://yeonwoo-code-sam/843f6e0aedc039e25757d2c06f0c6357
      Description: A starter AWS Lambda function.
      MemorySize: 128
      Timeout: 3
      Events:
        HelloWorldSAMAPI:
          Type: Api
          Properties:
            Path: /hello
            Method: GET

생성된 템플릿을 보면

s3 uri 가 자동으로 업데이트 된 것을 확인할 수 있다

 

이제 cloudformation deploy 명령어를 실행한다고 함

 

위 명령을 실행하면 changeset 이 생성되도록 잠깐 기다린 다음 생성이 끝나면

본 cloudformation 에 실행될 것

 

 

업데이트가 완료되면 새로 생성된 리소스들을 확인할 수 있음

 

cloudformation resources

코드에서의 조금의 변화로 많은 리소스를 새로 생성할 수 있음

SAM 의 장점

- cloudformation 에서 실행되는 복잡한 템플릿과 다른 여러 모든 항목을 자동으로 생성해줌

 

api gateway

event 로 생성해준 api gateway 를 확인할 수 있다

실행하면 오류가 나는데 위 코드에서 return 을 추가안해줘서 에러가 났다 *(나중에 추가해줌)

 

 

 

362. SAM DynamoDB

SAM 파일에 서버리스 db 인 dynamoDB 테이블 추가 실습

 

api gateway 에서 썻던 예제 github 파일을 보면 dynamoDB 테이블이 추가되어있음

이전 실습에선 해당 코드를 제거하고 사용했었음

 

코드에서 클라이언트를 핸드러 밖에 선언해주는데

lambda 챕터에서 배웠듯이 가장 좋은 방법이다

그리고 코드를 조금 추가해줘야 하는데 바로 리전이다

dynamoDB 를 생성할 리전을 정해줘야 하는데 새로운 환경변수를 생성해서 전달해준다고 한다

 

그리고 함수에 dynamoDB 를 활용한 작업을 추가한다고 함

람다 핸들러에 db 테이블을 스캔한 후 결과를 저장하고 리턴하도록 코드를 수정했다

 

 

수정된 app.py

import boto3
import json
import os

print('Loading function')

# create the client outside of the handler
region_name = os.environ['REGION_NAME']
dynamo = boto3.client('dynamodb', region_name=region_name)
table_name = os.environ['TABLE_NAME']

# 오류나 결과를 반환하는 함수
# 양식 자체도 api gateway 에서 사용하는 양식
def respond(err, res=None):
    return {
        'statusCode': '400' if err else '200',
        'body': err.message if err else json.dumps(res),
        'headers': {
            'Content-Type': 'application/json',
        },
    }


def lambda_handler(event, context):
    print("Received event: " + json.dumps(event, indent=2))
    scan_result=dynamo.scan(TableName=table_name)
    return respond(None, res=scan_result)

위에서 생성해준 환경변수인 RESION_NAME 과 TABLE_NAME 은 template.yaml 에서 설정해줘야 한다

 

예제 github 파일에서 리소스 하위의 table 코드를 가져와 준다

여기에 추가로 몇가지 속성을 지정해서 과도한 비용이 청구되지 않도록 설정한다고 함

 

https://docs.aws.amazon.com/ko_kr/serverless-application-model/latest/developerguide/sam-resource-simpletable.html

 

AWS::Serverless::SimpleTable - AWS Serverless Application Model

이 페이지에 작업이 필요하다는 점을 알려 주셔서 감사합니다. 실망시켜 드려 죄송합니다. 잠깐 시간을 내어 설명서를 향상시킬 수 있는 방법에 대해 말씀해 주십시오.

docs.aws.amazon.com

 

table 속성

Table:
  Type: AWS::Serverless::SimpleTable
  Properties:
    PrimaryKey:
      Name: greeting
      Type : String
    ProvisionedThroughput:
      ReadCapacityUnits: 2
      WriteCapacityUnits: 2

 

이제 람다 핸들러에 대한 환경변수를 지정해준다고 함

!Ref 함수를 이용해서 CloudFormation 으로 앞서 생성한 simpletable 에 포함되는 함수이다

리전에 관한 환경변수도 생성해주는데 AWS::Region 이라는 의사 매개변수를 사용해준다

- 의사 매개변수란 aws cloudformation 탬플릿에서 직접 제공하는 매개변수

 

환경변수 추가

Environment:
  Variables:
    TABLE_NAME: !Ref Table
    REGION_NAME: !Ref AWS::Region

 

이렇게 환경변수와 아래에 테이블까지 정의해주면

lambda 에서 이 테이블에 접근할 수 있는 액세스 권한도 정의해줘야 한다고 함

이때 정책은 람다 함수에 추가 가능한 IAM 정책을 사용해야 한다고 함

 

수정된 template.yaml

# SAM FILE
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: A starter AWS Lambda function.
Resources:
  helloworldpython3:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: app.lambda_handler
      Runtime: python3.9
      CodeUri: src/
      Description: A starter AWS Lambda function.
      MemorySize: 128
      Timeout: 3
      
      Environment:
        Variables:
          TABLE_NAME: !Ref SAM-Table
          REGION_NAME: !Ref AWS::Region

      Events:
        HelloWorldSAMAPI:
          Type: Api
          Properties:
            Path: /hello
            Method: GET

      Policies:
        - DynamoDBCrudPolicy:
            TableName: !Ref SAM-Table

  Table:
      Type: AWS::Serverless::SimpleTable
      Properties:
        PrimaryKey:
          Name: greeting
          Type : String
        ProvisionedThroughput:
          ReadCapacityUnits: 2
          WriteCapacityUnits: 2

 

이제 sam명령을 통해 sam 파일을 cloudformation 파일로 변환하고 배포해보면

 

cloudformation resources

dynamodb 테이블이 잘 생성된 것을 확인할 수 있다

스캔을 위해 테이블에 몇가지 아이템을 직접 넣고

 

dynamoDB 에 항목 생성

람다함수로 가서 생성된 함수의 환경변수를 확인해보면

 

environment variables

환경변수를 가져오는 함수가 제대로 동작해서 테이블 이름과 배포할 리전의 이름을 잘 가져온것을 확인할 수 있다

 

api gateway 의 resources 의 get 으로 가서 테스트를 해보면

test

status 200 으로 람다가 db에서 정상으로 항목들을 불러와진 것을 확인할 수 있다

유니코드로 반환되는데 반환 타입을 지정해주지 않아서 그런가보다

이제 stage 에서 prod 의 url 로 들어가서 확인해보면

 

prod url

역시 같은 결과를 반환해주는 것을 확인할 수 있다

 

유니코드 디코드