...
생성된 URL을 입력할 경우, 정상적으로 Redirect 되는지 확인해 봅시다. (본인의 프로젝트에서 생성된 URL을 이용하여 테스트 하세요.)
https://8cqxe1wr4b.execute-api.ap-northeast-1.amazonaws.com/prod/c12778d9
잘 동작하는 것을 볼 수 있습니다.
미션 2.
...
부하 테스트를 위한 배포 환경을 정의
이 미션은 부하 테스트를 하기 위한 배포 환경을 정의 합니다.
아키텍처 소개
배포 환경 정보를 알 수 있도록 TestEnv라는 스택을 하나 생성하고, 해당 스택을 이용하는 형태로 변경하겠습니다
이 미션은 Route 53에 도메인이 등록되어 있고, Tokyo 리전에 ACM을 부여 받아야지 구성을 할 수 있습니다. 또한 구성 후 약 30분 내외의 Domain 경로 전파 시간이 필요합니다.
아키텍처 소개
HTTPS 접속을 위해서 필요한 인증서는 ACM을 통해서 생성합니다. 그리고 Route 53에 해당 도메인을 배포할 수 있는 Stack을 이용해서 배포하도록 하겠습니다.
draw.io Diagram | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
인증서 발급
ACM에서 Custom domain name으로 활용하기 위해서 인증서를 생성하고 확인을 받습니다.
Tokyo 리전에서 서브도메인 cert를 하나 발급받고 인증 받습니다. 해당 cert의 ARN 정보를 메모장에 기록합니다.
|
CDK를 이용한 Custom domain name API 생성
...
코드 블럭 | ||||||
---|---|---|---|---|---|---|
| ||||||
mkdir testenv_common cd testenv_common |
해당 폴더에 __init__.py 이라는 파일을 만들고 아래의 코드를 넣습니다. ACCOUNT부터 ZONE_CERT 까지는 본인의 환경에 맞추어 변경하여 만듭니다.
코드 블럭 | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
import os from aws_cdk.core import Stack, Construct, Environment from aws_cdk import aws_apigateway, aws_route53, aws_route53_targets, aws_certificatemanager, aws_ec2 # we need default values here since aws-cdk-examples build synthesizes the app ACCOUNT= os.environ.get('TESTENV_ACCOUNT', '123456789012') REGION = os.environ.get('TESTENV_REGION', 'ap-northeast-1') VPC_ID = os.environ.get('TESTENV_VPC_ID', 'vpc-0e680e107cb16f0c9') AWS_ENV = Environment(account=ACCOUNT, region=REGION) class TestEnvStack(Stack): """ A base CDK stack class for all stacks defined in our fun little company. """ def __init__(self, scope: Construct, id: str, **kwargs): super().__init__(scope, id, env=AWS_ENV, **kwargs) # lookup our pre-created VPC by ID self._vpc = aws_ec2.Vpc.from_lookup(self, "vpc", vpc_id=VPC_ID) @property def testenv_vpc(self) -> aws_ec2.IVpc: """ :return: The test env vpc """ return self._vpc __all__ = ["TestEnvStack"] |
...
* VPC_ID는 Private subnet을 포함하고 있어야 합니다. 만약 없다면, VPC Wizard를 통해서 생성하고 해당 VPC를 연결합니다.
...
코드 블럭 | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
from aws_cdk import core, aws_dynamodb, aws_lambda, aws_apigateway
from testenv_common import TestEnvStack
class UrlShortStack(TestEnvStack):
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
# The code that defines your stack goes here
table = aws_dynamodb.Table(self, "mapping-table",
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) |
...
부하 테스트는 Docker 이미지를 만들고 Fargate를 이용해서 Task를 배포하여 테스트 합니다.
draw.io Diagram | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
트래픽 생성용 Docker 이미지 작성
트래픽 생성용 Docker 이미지를 작성하기 위하여 load-test 폴더를 하나 만듭니다.
...
코드 블럭 | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
from aws_cdk import core, aws_dynamodb, aws_lambda, aws_apigateway
from testenv_common import TestEnvStack
from traffic import Traffic
class UrlShortStack(TestEnvStack):
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
# The code that defines your stack goes here
table = aws_dynamodb.Table(self, "mapping-table",
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(TestEnvStack):
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
Traffic(self, 'TestTraffic',
vpc= self.testenv_vpc,
url='https://cdk.awsdemokr.com/715a930b',
tps=10)
|
...
draw.io Diagram | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
pypi.org에서 모니터링 관련 cdk를 검색합니다: https://pypi.org/search/?q=aws+cdk+monitoring
...
코드 블럭 | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
from aws_cdk import core, aws_dynamodb, aws_lambda, aws_apigateway
from testenv_common import TestEnvStack
from traffic import Traffic
from cdk_watchful import Watchful
class UrlShortStack(TestEnvStack):
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
# The code that defines your stack goes here
table = aws_dynamodb.Table(self, "mapping-table",
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='meelong0@studydev.com')
wf.watch_scope(self)
class TrafficStack(TestEnvStack):
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
Traffic(self, 'TestTraffic',
vpc= self.testenv_vpc,
url='https://cdk.awsdemokr.com/715a930b',
tps=10)
|
...