AWS SAM을 사용하게 된 계기를 설명드리고, AWS SAM template이 Cloudformation위에서 운영되기 때문에 Cloudformation에서 사용되는 주요 기능들을 설명합니다. 그리고 Infrastructure as code를 위한 Pipeline을 구축할 때 Cloudformation과 함께 사용할 수 있는 Tool들을 설명합니다. API Gateway, Lambda, SQS, SNS, DynamoDB(경우에 따라서는 VPC 설정과 함께 Elasticache와 RDS)로 구성된 비교적 단순한 시스템에 AWS SAM을 사용한 경험을 바탕으로 준비가 되었습니다. 아주 복잡한 시스템에 AWS SAM을 적용한 것이 아니기 때문에 이부분에서는 내용이 한계가 있을 수 있습니다.
3. 목차
- AWS SAM을 사용한 이유
- Cloudformation 기능 설명
- Pipeline
⚠ API Gateway, Lambda, SQS, SNS, DynamoDB등으로 구성된
간단한 시스템에 AWS SAM이 적용되었습니다.
⚠ AWS SAM과 Cloudformation이 익숙하지 않은 분도 들을 수 있도록
발표자료를 준비하였습니다.
⚠ 발표 예제는 Github(jaemyunlee/2020-aws-community-day-seoul)
에서 확인 할 수 있습니다.
5. 과제
❗API gateway, DynamoDB, SNS, SQS, Lambda로
구성된 서비스 개발이 진행.
❗Infrastructure as code를 통해서 배포를 구성.
❗이미 ECS로 구성된 resources들이 Terraform으로
구성되어 있었음
🤔 Terraform으로 계속 작업???
10. I still ❤ Terraform. However...😝
SAM(Serverless Application Model)은 Serverless를
위한 Tool로 편리하게 Abstraction되어 있습니다.
SAM template에서 Globals로 공통적인
Configuration을 설정할 수도 있고,AutoPublishAlias
옵션으로 쉽게 alias와 versioning을 관리하고, Canary
배포도 간단하게 설정할 수 있었습니다.
😸 저는 서버리스에 있어서는 SAM이 더
직관적이었습니다.
11. SAM template 구조 설명
Transform: "AWS::Serverless-2016-10-31"
Description: "example template"
Globals:
Function:
Runtime: nodejs10.x
Timeout: 10
Resources:
Api:
Type: "AWS::Serverless::Api"
Properties:
StageName: test
TracingEnabled: false
EndpointConfiguration: REGIONAL
ServerlessExample:
Type: "AWS::Serverless::Function"
Properties:
FunctionName: serverless_example_lambda
Handler: main.handler
CodeUri:
Bucket: aws-community-day-example
Key: v1.0.0/example.zip
Events:
PublicApi:
Type: Api
Properties:
Path: /
Method: GET
RestApiId: !Ref Api
공통적인
설정
SAM resource type
SAM resource type
Event source type
12. SAM template 설명
SAM의 Resource type는 아래와 같이 있습니다.
AWS::Serverless::Function
AWS::Serverless::Api
AWS::Serverless::HttpApi
AWS::Serverless::Application
AWS::Serverless::SimpleTable
AWS::Serverless::LayerVersion
🤔 여기에 없는 Resource는 Cloudformation의
Syntax를 그대로 사용하시면 됩니다. (예,
AWS::SQS::Queue)
13. SAM template 설명
SAM의 Event source type는 아래와 같이 있습니다.
S3
SNS
Kinesis
DynamoDB
SQS
Api
Schedule
CloudWatchEvent
EventBridgeRule
CloudWatchLogs
IoTRule
AlexaSkill
Cognito
14. SAM template 설명
아래의 링크를 가시면 SAM Specification을 더 자세히
볼 수 있습니다.
https://github.com/awslabs/serverless-application-model/blob/mas
ter/versions/2016-10-31.md
16. SAM commands
sam deploy
SAM template으로
Stack을 만들고 정의된
AWS resource들이
만들어집니다.
sam build
Lambda code를
build하고 Deployment
artifact 만듭니다.
Python의 경우
requirements.txt에 있는
dependency들을
설치합니다. 기본적으로
.aws-sam/build 폴더에
artifact가 저장됩니다.
sam package
Dependency들이 다
포함된 코드를 zip으로
압축하여 S3에
upload합니다. SAM
Template에서 local
주소를 가리키고 있던
것을 S3 location으로
변경하여 최종 SAM
template를 만듭니다.
31. sam local start-api --docker-network
Amazon API Gateway
RegisterCat
SearchCat
POST
/cat/
GET
/cat/
test-cat-table
test-cat-table
Put Item
Get Item
32. sam local start-api --docker-network
version: '3'
services:
dynamodb:
image: amazon/dynamodb-local
ports:
- "3306:3306"
networks:
- my_network
volumes:
- db-data:/home/dynamodblocal/data
dbsetup:
build: ./
networks:
- my_network
depends_on:
- dynamodb
environment:
- AWS_ACCESS_KEY_ID=foo
- AWS_SECRET_ACCESS_KEY=bar
- AWS_DEFAULT_REGION=ap-northeast-2
volumes:
db-data:
networks:
my_network:
$ docker-compose up
$ sam local start-api
--docker-network=local_dynamodb_my_network
33. sam local start-api --docker-network
session = boto3.client('dynamodb')
if os.getenv('ENV') == 'test':
session = boto3.client('dynamodb', endpoint_url='http://dynamodb:8000')
def lambda_handler(event, context):
logger.debug(event)
body = json.loads(event.get('body'))
cat = Cat(**body)
repository = DynamoDBCatRepository(session, os.environ['TABLE_NAME'])
repository.add(cat)
return {
'statusCode': 201
}
34. 로컬환경에서 테스트
from application import Cat, NewCatMessage, FakeSender
from lambda_logger import logger
from utils import parse_dynamodb_stream_event
def lambda_handler(event, context):
logger.debug(event)
for event in event.get('Records'):
data = parse_dynamodb_stream_event(event)
if data:
cat = Cat(**data)
message = NewCatMessage(cat.name, cat.get_age_level())
sender = FakeSender(message)
sender.send()
test-cat-table SendMessage
sam local generate-event dynamodb update > event.json
sam local invoke --event event.json SendMessage
Stream
event.json
38. Options
Core YAML/JSON Macro/Transform High-level Language Custom Resource
AWS SAM
AWS Cloudformation Macro
AWS CDK Call remote APIs
Resources not supported yet
proxies to external resources
AWS SAM은 AWS::Serverless의 resource들이
Cloudformation이랑 호환될 수 있도록 변환합니다.
Cloudformation에서 지원하는 기능들을 대부분 사용할
수 있습니다.
40. Cloudformation
Parameters
System manager parameter
store에 저장한 값을 쉽게
연동하여 Cloudformation
parameter값으로 사용할 수
있습니다.
Parameters:
Environment:
Type: String
Default: test
AllowedValues:
- test
- beta
- prod
LazyCat:
Type: 'AWS::SSM::Parameter::Value<String>'
Default: theLaziestCat
41. Cloudformation
Mappings
!FindInMap [Config, !Ref Environment, LogLevel]
Key값 별로 미리 value값을
정의해놓고 사용할 수 있습니다.
Mappings:
Config:
test:
LogLevel: DEBUG
TableName: test-cat-table
beta:
LogLevel: INFO
TableName: beta-cat-table
prod:
LogLevel: ERROR
TableName: prod-cat-table
42. Cloudformation
Conditions
조건을 만족하는 경우에만
resource를 생성할 수
있도록 설정할 수 있습니다.
Conditions:
IsLocal: !Equals [!Ref Environment, test]
DoNotCreateOnLocal: !Not [Condition: IsLocal]
Auth:
Type: "AWS::Serverless::Function"
Condition: DoNotCreateOnLocal
Properties:
FunctionName: !Join [ "-", [example, !Ref
Environment, auth]]
CodeUri: authorizer/
43. Cloudformation
Nested Stacks으로 공통된 resource를 정의한
template을 재사용하여 만들 수도 있습니다.
RegisterCatLogGroup:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: ./nestedStack.yaml
Parameters:
LambdaName: !Join ["-", [example, !Ref
Environment, register, cat]]
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
LambdaName:
Type: String
Resources:
LambdaLog:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub "/aws/lambda/${LambdaName}"
RetentionInDays: 3
Main Stack nestedStack.yaml
44. Cloudformation에서 제일 아쉬웠던 점
😑 이미 존재하는 resource들을 Stack에 포함시키고
싶을 때
🔆 resource import 🔆
November 11, 2019
45. Cloudformation Import 기능
🤨 SAM Template은 Tranform되어야 하는 것 때문에
다음과 같은 에러가 발생
This template does not include any resources to import.
😢 아쉽게도 아직 Import를 지원하는 Resource들이
제한적임.
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import-supported-resources.html
46. Stacksets
Stacksets으로 여러 region과 여러 account에 stack
생성하고 관리할 수 있습니다.
Administrator
Stack
Target
Stack
Trust
relationship
AWSCloudFormationStackSetExecutionRole
AWSCloudFormationStackSetAdministrationRole
47. Stacksets (Re:Invent 2019)
Automation of multi-account and multi-region permissions management and
deployment through AWS Organizations
이렇게 target accounts별로 Role들을 설정해줘야 하는데,
Organizations에서 Service-managed permission으로 관리될 수
있을 거라 합니다.
Organization unit별로 stack을 자동으로 배포할 수 있게 됩니다.
OU에 account가 추가되면 자동으로 stack이 배포되고 account가
OU에서 빠지면 자동으로 stack이 지워질 수 있다고 합니다.
48. Stacksets
🤨 SAM Template은 Tranform되어야 하는 것 때문에
다음과 같은 에러가 발생
Templates with transforms are not supported with StackSets
😅 sam validate --debug로 변환된 template를 볼 수
있습니다. Cloudformation stack console에서도 변환된
template를 볼 수가 있습니다. Stackset을 생성할 때는
Transform을 사용할 수 없기 때문에 변환된 template를
사용해야 합니다.
58. Change sets
--no-execute-changeset
옵션으로 바로 change set을
실행하지 않도록 설정 할 수
있습니다.
Stack을 업데이트 하기전에
change set을 확인하고
적용할 수 있습니다.
$ sam deploy
--no-execute-changeset
$ aws cloudformation
execute-change-set
59. Taskcat
Taskcat은 AWS QuickStart team에서 Cloudformation
template를 테스트하기 위해서 만들어진 Tool입니다.
실제 Stack을 만들고 결과리포트를 생성합니다.
$ taskcat test run
62. 요약 정리
🙂 간단한 Application으로 SAM Template를 어떻게
작성하는지 살펴보았습니다.
🙂 sam local command를 활용하여 로컬환경에서
Lambda를 테스트하는 방법을 소개하였습니다.
🙂 Cloudformation의 기능들도 설명하였습니다.
🙂 Pipeline을 구축할 때 활용될 수 있는 cfn-lint와
taskcat을 설명하였습니다.