...
프로젝트 시작점인 app.py를 열어 봅니다. 직접 Cloud 9 UI의 네비게이션에 있는 파일을 직접 클릭 해서 열 수 있고, npm install -g c9 과 같이 패키지를 설치한 후에 c9 open app.py 와 같은 형태로 terminal에서도 바로 열 수 있습니다.
소스 코드 중에 UrlShortStack 클래스 정의로 커서를 이동하고, 함수 정의로 이동을 위해서 F3를 누릅니다.
새로운 탭에 url_short_stack.py 파일이 열립니다. 이제 이 스택에 리소스를 하나씩 만들어 나가겠습니다.
리소스 작성
DynamoDB 테이블 리소스 정의
...
코드 작성이 완료 되면 아래와 같이 코드가 만들어졌을 것이고 저장합니다.
CDK deploy로 DynamoDB 테이블 배포
...
코드 블럭 | ||||||
---|---|---|---|---|---|---|
| ||||||
cdk deploy |
Lambda 함수 코드 작성
Lambda 함수를 개발하기 위하여 폴더를 하나 생성합니다. UI에서 lambda라는 폴더를 만들고, 폴더 하단에 handler.py 파일을 생성합니다. (terminal에서 cmd로 만드셔도 됩니다.)
handler.py 파일은 Short URL을 생성하거나, Short URL이 들어올 경우 원래 URL로 Redirect 하는 기능을 제공하는 함수입니다.
다음과 같은 코드를 함수에 넣습니다. 코드를 한 번 읽어보면서 동작되는 원리를 살펴 봅니다.
...
코드 블럭 | ||||||
---|---|---|---|---|---|---|
| ||||||
function = aws_lambda.Function(self, "backend", runtime=aws_lambda.Runtime.PYTHON_3_7, handler="handler.main", code=aws_lambda.Code.asset("./lambda")) |
Lambda 함수 리소스 배포
배포 Lambda 함수 확인
배포한 Lambda 함수 콘솔에 들어가서 확인이 가능합니다.
Lambda 함수에 DynamoDB Table로의 접근 권한 부여
...
코드 블럭 | ||||||
---|---|---|---|---|---|---|
| ||||||
cdk diff |
IAM 설정이 변경된 것을 볼 수 있으며, DDB mapping에 대한 Lambda 함수에 정책이 추가된 것을 볼 수 있습니다. backend라는 Lambda 함수가 이 정책을 쓰는 주체가 되는 것을 알 수 있습니다.
Lambda 함수가 수정된 것을 볼 수 있으며, 환경 변수 값이 추가되었고 새롭게 만들어진 정책이 적용된 것을 볼 수 있습니다.
...
코드 블럭 | ||||||
---|---|---|---|---|---|---|
| ||||||
cdk deploy |
API Gateway 리소스 정의
...
생성된 URL을 입력할 경우, 정상적으로 Redirect 되는지 확인해 봅시다. (본인의 프로젝트에서 생성된 URL을 이용하여 테스트 하세요.)
https://vp8tpwdmd4.execute-api.ap-northeast-2.amazonaws.com/prod/7c9b02b8
잘 동작하는 것을 볼 수 있습니다.
미션 2.
...
부하 테스트 및 모니터링 대시보드 작성
보스는 당신의 실력을 절대적으로 신임합니다. 하지만 성공적인 마케팅을 위해서는 성능을 보장할 수 있는 지표를 알아야 합니다.
...
코드 블럭 | ||||||
---|---|---|---|---|---|---|
| ||||||
URL=https://cdk.awsdemo.kr/715a930b7c9b02b8 ./ping.sh |
테스트를 하면 아래와 같이 1초마다 갱신되는 화면을 URL 정보가 리다이렉트 되는 것을 볼 수 있습니다.
...
코드 블럭 | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
from aws_cdk import core, aws_dynamodb, aws_lambda, aws_apigateway, aws_ec2 import os from traffic import Traffic # we need default values here since aws-cdk-examples build synthesizes the app ACCOUNT= os.environ['CDK_DEFAULT_ACCOUNT'] REGION = os.environ['CDK_DEFAULT_REGION'] VPC_ID = os.environ.get('TESTENV_VPC_ID', 'vpc-07aa21d32b2df894f') AWS_ENV = core.Environment(account=ACCOUNT, region=REGION) class UrlShortStack(core.Stack): def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, env=AWS_ENV, **kwargs) # The code that defines your stack goes here table = aws_dynamodb.Table(self, "mapping", partition_key = aws_dynamodb.Attribute(name="id",type=aws_dynamodb.AttributeType.STRING)) function = aws_lambda.Function(self, "backend", runtime=aws_lambda.Runtime.PYTHON_3_7, handler="handler.main", code=aws_lambda.Code.asset("./lambda")) table.grant_read_write_data(function) function.add_environment("TABLE_NAME", table.table_name) api = aws_apigateway.LambdaRestApi(self, "api", handler=function) class TrafficStack(core.Stack): def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, env=AWS_ENV, **kwargs) # lookup our pre-created VPC by ID vpc_env = aws_ec2.Vpc.from_lookup(self, "vpc", vpc_id=VPC_ID) Traffic(self, 'TestTraffic', vpc= vpc_env, url="https://vp8tpwdmd4.execute-api.ap-northeast-2.amazonaws.com/prod/7c9b02b8", tps=10) |
...
코드 블럭 | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
import os from aws_cdk import core, aws_dynamodb, aws_lambda, aws_apigateway, aws_ecs, aws_ec2 from traffic import Traffic from cdk_watchful import Watchful # we need default values here since aws-cdk-examples build synthesizes the app ACCOUNT= os.environ['CDK_DEFAULT_ACCOUNT'] REGION = os.environ['CDK_DEFAULT_REGION'] VPC_ID = os.environ.get('TESTENV_VPC_ID', 'vpc-07aa21d32b2df894f') AWS_ENV = core.Environment(account=ACCOUNT, region=REGION) class UrlShortStack(core.Stack): def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, env=AWS_ENV, **kwargs) # The code that defines your stack goes here table = aws_dynamodb.Table(self, "mapping", partition_key = aws_dynamodb.Attribute(name="id",type=aws_dynamodb.AttributeType.STRING)) function = aws_lambda.Function(self, "backend", runtime=aws_lambda.Runtime.PYTHON_3_7, handler="handler.main", code=aws_lambda.Code.asset("./lambda")) table.grant_read_write_data(function) function.add_environment("TABLE_NAME", table.table_name) api = aws_apigateway.LambdaRestApi(self, "api", handler=function) wf = Watchful(self, 'monitoring', alarm_email='scv@studydev.com') wf.watch_scope(self) class TrafficStack(core.Stack): def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, env=AWS_ENV, **kwargs) # lookup our pre-created VPC by ID vpc_env = aws_ec2.Vpc.from_lookup(self, "vpc", vpc_id=VPC_ID) Traffic(self, 'TestTraffic', vpc= vpc_env, url="https://7vzqf6htubvp8tpwdmd4.execute-api.ap-southeastnortheast-12.amazonaws.com/prod/2a3c26e07c9b02b8", tps=10) |
cdk-watchful 배포
...
트래픽을 증가시켜서 DynamoDB의 RCU를 넘기도록 설정합니다. TPS를 10에서 15로 변경하여 트래픽을 절반 더 늘리고, 5분 정도 기다립니다.
코드 블럭 | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
import os
from aws_cdk import core, aws_dynamodb, aws_lambda, aws_apigateway, aws_ecs, aws_ec2
from traffic import Traffic
from cdk_watchful import Watchful
# we need default values here since aws-cdk-examples build synthesizes the app
ACCOUNT= os.environ['CDK_DEFAULT_ACCOUNT']
REGION = os.environ['CDK_DEFAULT_REGION']
VPC_ID = os.environ.get('TESTENV_VPC_ID', 'vpc-07aa21d32b2df894f')
AWS_ENV = core.Environment(account=ACCOUNT, region=REGION)
class UrlShortStack(core.Stack):
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
super().__init__(scope, id, env=AWS_ENV, **kwargs)
# The code that defines your stack goes here
table = aws_dynamodb.Table(self, "mapping",
partition_key = aws_dynamodb.Attribute(name="id",type=aws_dynamodb.AttributeType.STRING))
function = aws_lambda.Function(self, "backend",
runtime=aws_lambda.Runtime.PYTHON_3_7,
handler="handler.main",
code=aws_lambda.Code.asset("./lambda"))
table.grant_read_write_data(function)
function.add_environment("TABLE_NAME", table.table_name)
api = aws_apigateway.LambdaRestApi(self, "api", handler=function)
wf = Watchful(self, 'monitoring', alarm_email='scv@studydev.com')
wf.watch_scope(self)
class TrafficStack(core.Stack):
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
super().__init__(scope, id, env=AWS_ENV, **kwargs)
# lookup our pre-created VPC by ID
vpc_env = aws_ec2.Vpc.from_lookup(self, "vpc",
vpc_id=VPC_ID)
Traffic(self, 'TestTraffic',
vpc= vpc_env,
url="https://vp8tpwdmd4.execute-api.ap-northeast-2.amazonaws.com/prod/7c9b02b8",
tps=15)
|
코드 블럭 | ||||||
---|---|---|---|---|---|---|
| ||||||
cdk deploy "*" |
DynamoDB Console에서도 동일한 메트릭 정보를 확인할 수 있습니다. RCU가 부족한 현상이 발생합니다.
...