버전 비교

  • 이 줄이 추가되었습니다.
  • 이 줄이 삭제되었습니다.
  • 서식이 변경되었습니다.

...

펼치기
title버전 정보 업데이트

2019-09-25

  • 짧은URL을 만들고, 통계 분석으로 미연에 장애를 인지할 수 있는 환경을 CDK 기반으로 구축

문서 URL: https://cdk.awsdemokrawsdemo.comkr/d2a5b966devops301lab2


미션 1. CDK 서비스를 이용한 짧은 URL 생성 애플리케이션 구축하기

...

해당 앱의 결과물은 다음과 같은 링크를 가지는 것입니다. 여기서는 API를 위한 Custom domain name(cdk.awsdemokrawsdemo.com처럼kr처럼)을 설정하는 방법이 있지만, Route 53에 Domain이 등록되어 있지 않는 것을 가정하고 진행합니다. 미션2는 생략할 수 있습니다.
Demo 테스트 방법: https://cdk.awsdemokrawsdemo.comkr?targetUrl=https://www.amazon.com 과 같이 URL을 호출하면 짧은 URL을 반환해 주는 App입니다. 아래와 같은 결과물이 화면에 출력됩니다.

코드 블럭
languagebash
Created URL: https://cdk.awsdemokrawsdemo.comkr/b44086fd

해당 데모는 bit.ly 사이트처럼 Front-end 페이지를 구축하지는 않습니다.(CDK를 이용하여 Back-end를 구축하는 방법에 집중합니다.)

...

다음 화면에서 Allocate 버튼을 클릭하면 고정 IP를 한 개 할당 받을 수 있습니다.

VPC 생성하기

부하 테스트를 위해서, Docker 이미지를 ECR에 올리고, Fargate를 통해 서버리스 형태로 배포하기 위해서 VPC와 Private subnet 이 필요합니다.
VPC 서비스의 Dashboard 화면에서 Launch VPC Wizard 버튼을 클릭하여 Public subnet과 Private subnet을 포함하고, NAT Gateway를 포함하는 VPC를 생성합니다.

...

코드 블럭
languagepy
themeRDark
title__init__.py
linenumberstrue
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('WALTERSCO_ACCOUNT', '123456789012')
REGION=os.environ.get('WALTERSCO_REGION', 'ap-northeast-1')
VPC_ID = os.environ.get('WALTERSCO_VPC_ID', 'vpc-0e680e107cb16f0c9')
ZONE_NAME = os.environ.get('WALTERSCO_ZONE_NAME', 'awsdemokrawsdemo.comkr')
ZONE_ID = os.environ.get('WALTERSCO_ZONE_ID', 'Z2B54ZGB38V31I')
ZONE_CERT = os.environ.get('WALTERSCO_ZONE_CERT', 'arn:aws:acm:ap-northeast-1:123456789012:certificate/ea3bef71-7d73-4979-bc3d-165931ceb141')

AWS_ENV = Environment(account=ACCOUNT, region=REGION)

class WaltersCoStack(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 waltersco_vpc(self) -> aws_ec2.IVpc:
        """
        :return: The walters co. vpc
        """
        return self._vpc

    def map_waltersco_subdomain(self, subdomain: str, api: aws_apigateway.RestApi) -> str:
        """
        Maps a sub-domain of waltersco.co to an API gateway
        :param subdomain: The sub-domain (e.g. "www")
        :param api: The API gateway endpoint
        :return: The base url (e.g. "https://www.waltersco.co")
        """
        domain_name = subdomain + '.' + ZONE_NAME
        url = 'https://' + domain_name

        cert = aws_certificatemanager.Certificate.from_certificate_arn(self, 'DomainCertificate', ZONE_CERT)
        hosted_zone = aws_route53.HostedZone.from_hosted_zone_attributes(self, 'HostedZone',
                                                                         hosted_zone_id=ZONE_ID,
                                                                         zone_name=ZONE_NAME)

        # add the domain name to the api and the A record to our hosted zone
        domain = api.add_domain_name('Domain', certificate=cert, domain_name=domain_name)

        aws_route53.ARecord(
            self, 'UrlShortenerDomain',
            record_name=subdomain,
            zone=hosted_zone,
            target=aws_route53.RecordTarget.from_alias(aws_route53_targets.ApiGatewayDomain(domain)))

        return url


__all__ = ["WaltersCoStack"]

...

도메인 배포까지 시간이 소요될 수 있습니다. (30분 내외)

https://cdk.awsdemokrawsdemo.comkr/715a930b


미션 3. 부하 테스트 및 모니터링 대쉬보드 작성

...

코드 블럭
languagebash
themeDJango
title1 TPS 테스트 예(도메인 있을 경우)
URL=https://cdk.awsdemokrawsdemo.comkr/715a930b ./ping.sh

테스트를 하면 아래와 같이 1초마다 갱신되는 화면을 URL 정보가 리다이렉트 되는 것을 볼 수 있습니다.

...

코드 블럭
languagebash
themeDJango
titleDorker 이미지 실행
docker run -it -e URL=https://cdk.awsdemokrawsdemo.comkr/715a930b pinger

CDK를 이용한 Fargate 배포 설정

...

코드 블럭
languagepy
themeRDark
titleurl_shrotener_stack.py
linenumberstrue
from aws_cdk import core, aws_dynamodb, aws_lambda, aws_apigateway
from waltersco_common import WaltersCoStack
from traffico import Traffico


class UrlShrotenerStack(WaltersCoStack):

    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)
        
        self.map_waltersco_subdomain("cdk", api)


class TrafficStack(WaltersCoStack):
    
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)
        
        Traffico(self, 'TestTraffic',
            vpc= self.waltersco_vpc,
            url='https://cdk.awsdemokrawsdemo.comkr/715a930b',
            tps=10)
            


app.py 파일을 수정합니다.

...

코드 블럭
languagepy
themeRDark
title url_shrotener_stack.py for cdk-watchful
linenumberstrue
from aws_cdk import core, aws_dynamodb, aws_lambda, aws_apigateway
from waltersco_common import WaltersCoStack
from traffico import Traffico
from cdk_watchful import Watchful

class UrlShrotenerStack(WaltersCoStack):

    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)
        
        self.map_waltersco_subdomain("cdk", api)
        
        wf = Watchful(self, 'monitoring', alarm_email='meelong0@studydev.com')
        wf.watch_scope(self)


class TrafficStack(WaltersCoStack):
    
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)
        
        Traffico(self, 'TestTraffic',
            vpc= self.waltersco_vpc,
            url='https://cdk.awsdemokrawsdemo.comkr/715a930b',
            tps=10)


cdk-watchful 배포

...

다음과 같은 대시보드를 통해서 상태를 확인할 수 있습니다.

트래픽을 증가시켜서 DanamoDB의 DynamoDB의 RCU를 넘기도록 설정합니다. TPS를 10에서 15로 변경하여 트래픽을 절반 더 늘리고, 5분 정도 기다립니다.

...