BLOG

Amazon ECS용 AWS Cloud Development Kit 시작하기
작성일: 2019년 1월 7일

AWS CDK(AWS Cloud Development Kit)는 클라우드 인프라를 코드로 정의하고 AWS CloudFormation을 통해 프로비저닝하는 오픈소스 소프트웨어 개발 프레임워크입니다. AWS CDK는 AWS 서비스와 완벽하게 통합되며 AWS 리소스를 필수적으로 정의하기 위해 보다 높은 수준의 개체 지향 추상화를 제공합니다.

 

인프라 구성의 AWS CDK 라이브러리를 사용하면 인프라 정의에 AWS 모범 사례를 쉽게 캡슐화하고 표준 문안 논리에 대해 걱정하지 않고 공유할 수 있습니다. AWS CDK는 최신 프로그래밍 언어의 기능을 사용하여 AWS 인프라를 예측 가능하고 효율적인 방식으로 정의하기 때문에 엔드 투 엔드 개발 환경을 개선합니다. AWS CDK는 현재 TypeScript, JavaScript, Java 및 .NET에서 사용할 수 있습니다.

 

이제 AWS CDK에는 ECS 리소스의 구조가 포함되어 있어, 몇 줄의 간단하고 읽기 쉬운 코드로 AWS에서 완전히 작동하는 컨테이너형 애플리케이션 환경을 구축할 수 있습니다. 어떻게 작동하는지 보여드리겠습니다.

 

AWS CDK 설치

첫 번째 단계는 개발 시스템에 AWS CDK를 설치하는 것입니다.

 

mkdir greeter-cdk

cd greeter-cdk

npm init -y

npm install @aws-cdk/cdk

npm install -g aws-cdk

 

그런 다음 AWS CDK 라이브러리를 가져오는 JavaScript 코드를 작성하여 모든 리소스를 배치할 수 있는 골격을 정의하십시오.

 

index.js.

 

const cdk = require(‘@aws-cdk/cdk’);

 

class GreetingStack extends cdk.Stack {

constructor(parent, id, props) {

super(parent, id, props);

}

}

 

class GreetingApp extends cdk.App {

constructor(argv) {

super(argv);

new GreetingStack(this, ‘greeting-stack’);

}

}

 

new GreetingApp().run();

 

그런 다음 AWS CDK CLI에 index.js가 애플리케이션 스택을 정의하는 코드라고 알리는 작은 구성 파일을 작성하십시오.

 

cdk.json

 

{

“app”: “node index.js”

}

 

이제 cdk ls –l을 실행하면 AWS CDK가 스택을 찾았고 AWS 계정 ID 및 기본 리전과 같은 개발 시스템 환경에서 스택에 대한 일부 세부 정보를 자동으로 보냅니다.

 

$ cdk ls -l

– name: greeting-stack

environment:

name: 209640446841/us-east-1

account: ‘209640446841’

region: us-east-1

 

ECS 구성 추가

이제 스택에 몇 가지 ECS 구조를 추가해야 할 때 입니다. 이렇게 하려면 먼저 ECS 구성 라이브러리를 설치하십시오. 또한 컨테이너에 연결된 리소스를 설정하는 데 도움이 되는 몇 가지 다른 구성 요소를 설치하십시오.

 

npm install @aws-cdk/aws-ecs

npm install @aws-cdk/aws-ec2

npm install @aws-cdk/aws-elasticloadbalancingv2

 

이제 ECS 구성을 사용하여 애플리케이션 환경을 설정하십시오.

 

const cdk = require(‘@aws-cdk/cdk’);

const ecs = require(‘@aws-cdk/aws-ecs’);

const ec2 = require(‘@aws-cdk/aws-ec2’);

 

class GreetingStack extends cdk.Stack {

constructor(parent, id, props) {

super(parent, id, props);

 

const vpc = new ec2.VpcNetwork(this, ‘GreetingVpc’, { maxAZs: 2 });

 

// Create an ECS cluster

const cluster = new ecs.Cluster(this, ‘Cluster’, { vpc });

 

// Add capacity to it

cluster.addDefaultAutoScalingGroupCapacity({

instanceType: new ec2.InstanceType(‘t3.xlarge’),

instanceCount: 3

});

}

}

 

단 세 번의 호출만으로 모든 애플리케이션 리소스를 저장할 VPC와 3개의 t3.xlarge 인스턴스가 있는 ECS 클러스터를 만들 수 있습니다. AWS CDK에 이 스택을 계정에 자동으로 배포하도록 명령하기만 하면 됩니다.

 

cdk deploy

 

이면에서 AWS CDK는 JavaScript 호출을 CloudFormation 템플릿에 통합합니다. 통합 템플릿에 설명된 리소스를 배포하기 위해 CloudFormation에 문의하십시오. 생성 중인 각 리소스의 라이브 로그와 상태 정보를 볼 수 있습니다. 메시지 스트림 왼쪽에 있는 숫자에서 알 수 있듯이, AWS CDK 스택에 추가된 세 가지 간단한 명령이 자동으로 AWS 계정에 생성될 하위 수준의 원시 리소스 32개로 확장되었습니다.

AWS CDK 배포가 완료되면 서비스를 실행할 수 있는 새로운 ECS 클러스터가 준비됩니다. 다음으로 이 클러스터에 간단한 마이크로서비스 스택을 구축하십시오. 어플리케이션은 간단한 인사 서버가 될 것입니다. 프런트엔드 greeter 서비스는 두 백엔드 서비스에서 임의의 인사말과 이름을 가져옵니다. 이 애플리케이션에는 프런트엔드와 백엔드라는 두 가지 계층이 있습니다. 네트워크는 다음과 같은 다이어그램처럼 보일 것입니다.

로드 밸런서가 두 개가 있는데, 그 중 하나는 인터넷 상의 모든 사람이 여러분의 greeter 서비스와 대화할 수 있게 해줍니다. 다른 하나는 내부적인 것으로, greeter 서비스가 다른 인사말과 이름 서비스와 대화할 수 있도록 설계되었습니다.

 

전체적으로 AWS CDK 애플리케이션에 2개의 로드 밸런서 및 3개의 서비스라는 5개의 상위 구성을 추가해야 합니다.

 

새 ECS 서비스 추가

애플리케이션 스택에 새로운 ECS 서비스를 추가하는 것은 쉽습니다. 작업 정의를 정의하고 여기에 컨테이너를 추가한 후 AWS CDK에 작업 정의를 서비스로 전환하도록 지시하십시오.

 

// Name service

const nameTaskDefinition = new ecs.Ec2TaskDefinition(this, ‘name-task-definition’, {});

 

const nameContainer = nameTaskDefinition.addContainer(‘name’, {

image: ecs.ContainerImage.fromDockerHub(‘nathanpeck/name’),

memoryLimitMiB: 128

});

 

nameContainer.addPortMappings({

containerPort: 3000

});

 

const nameService = new ecs.Ec2Service(this, ‘name-service’, {

cluster: cluster,

desiredCount: 2,

taskDefinition: nameTaskDefinition

});

 

// Greeting service

const greetingTaskDefinition = new ecs.Ec2TaskDefinition(this, ‘greeting-task-definition’, {});

 

const greetingContainer = greetingTaskDefinition.addContainer(‘greeting’, {

image: ecs.ContainerImage.fromDockerHub (‘nathanpeck/greeting’),

memoryLimitMiB: 128

});

 

greetingContainer.addPortMappings({

containerPort: 3000

});

 

const greetingService = new ecs.Ec2Service(this, ‘greeting-service’, {

cluster: cluster,

desiredCount: 2,

taskDefinition: greetingTaskDefinition

});

 

이와 마찬가지로 Docker Hub에서 공용 이미지를 로드하여 실행하는 두 가지 다른 ECS 서비스를 정의하였습니다. 다음 단계는 로드 밸런서를 생성하고 여기에 서비스를 추가하는 것입니다.

 

// Internal load balancer for the backend services

const internalLB = new elbv2.ApplicationLoadBalancer(this, ‘internal’, {

vpc: vpc,

internetFacing: false

});

 

const internalListener = internalLB.addListener(‘PublicListener’, { port: 80, open: true });

 

internalListener.addTargetGroups(‘default’, {

targetGroups: [new elbv2.ApplicationTargetGroup(this, ‘default’, {

vpc: vpc,

protocol: ‘HTTP’,

port: 80

})]

});

 

internalListener.addTargets(‘name’, {

port: 80,

pathPattern: ‘/name*’,

priority: 1,

targets: [nameService]

});

 

internalListener.addTargets(‘greeting’, {

port: 80,

pathPattern: ‘/greeting*’,

priority: 2,

targets: [greetingService]

});

 

이 구성에서 코드는 포트 80에 단일 수신기가 있는 단일 로드 밸런서를 정의하지만 그 뒤에 두 개의 다른 서비스를 추가합니다. 요청 경로가 /name과 비슷하면, 해당 요청은 귀하의 이름 서비스로 보내집니다. 만약 그것이 /greeting처럼 보인다면, 그것은 인사 서비스로 요청을 보냅니다.

 

마지막으로, 이름 서비스에서 임의의 이름을 가져오고 인사 서비스에서 임의의 인사말을 가져오는 임의의 인사말 문구를 구성하는 프런트엔드 greeter 서비스를 추가하십시오. 이렇게 하려면 다른 두 백엔드 서비스에 대한 요청 방법을 알 수 있도록 greeter 서비스를 구성하십시오.

 

// Greeter service

const greeterTaskDefinition = new ecs.Ec2TaskDefinition(this, ‘greeter-task-definition’, {});

 

const greeterContainer = greeterTaskDefinition.addContainer(‘greeter’, {

image: ecs.ContainerImage.fromDockerHub (‘nathanpeck/greeter’),

memoryLimitMiB: 128,

environment: {

GREETING_URL: ‘http://’ + internalLB.dnsName + ‘/greeting’,

NAME_URL: ‘http://’ + internalLB.dnsName + ‘/name’

}

});

 

greeterContainer.addPortMappings({

containerPort: 3000

});

 

const greeterService = new ecs.Ec2Service(this, ‘greeter-service’, {

cluster: cluster,

desiredCount: 2,

taskDefinition: greeterTaskDefinition

});

 

AWS CDK에는 JavaScript에 입력한 식을 확인하고 정확한 값을 확인하는 CloudFormation 템플릿으로 변환하는 강력한 기능이 있습니다.

 

이 예에서는 로드 밸런서의 DNS 이름에 대한 참조를 생성하고 다음을 할당하려고 합니다.

 

  •  Environment variable = 'NAME_URL'
  •  Value = 'http://' + internalLB.dnsName + '/name'

 

cdk synth를 실행하면 AWS CDK에서 배포 시 로드 밸런서의 올바른 DNS 이름을 동적으로 삽입하는 CloudFormation 템플릿을 생성하는 것을 볼 수 있습니다.

 

Type: ‘AWS::ECS::TaskDefinition’

Properties:

ContainerDefinitions:

– Environment:

– Name: GREETING_URL

Value:

‘Fn::Join’:

– ”

– – ‘http://’

– ‘Fn::GetAtt’:

– internal505AC855

– DNSName

– /greeting

– Name: NAME_URL

Value:

‘Fn::Join’:

– ”

– – ‘http://’

– ‘Fn::GetAtt’:

– internal505AC855

– DNSName

– /name

 

AWS CDK 스택에 추가할 마지막 한가지는 출력입니다. 트래픽을 전송할 수 있도록 서비스의 DNS 이름을 지정하십시오.

 

new cdk.Output(this, ‘ExternalDNS’, { value: externalLB.dnsName });

 

이제 배포 시 추가되는 항목을 확인하십시오. 실제로 배포를 수행하지 않고 새 리소스 또는 수정된 리소스의 미리 보기를 보려면 다음 명령을 입력하십시오.

 

cdk diff

 

추가할 새 리소스 목록이 좋아 보이므로 cdk deploy를 다시 실행하십시오. 다시 한 번 AWS CDK는 CloudFormation 템플릿을 통합하고 AWS 계정에서 배포를 초기화합니다. 그러나 이번에는 총 66개의 리소스를 생성하고 애플리케이션이 호스팅되는 URL 출력을 제공합니다.

애플리케이션이 실행 중인지 확인하고 해당 URL에서 트래픽을 수락하려면 해당 인터넷 ExternalDNS URL을 브라우저에 로드하십시오. 웹 애플리케이션은 다른 두 백엔드 서비스와 대화하여 인사말과 이름을 얻을 수 있었습니다.

결론

이 마이크로서비스 스택을 직접 구축하거나 이를 AWS CDK 스택을 구축하는 기준으로 사용하려면 GitHub에서 전체 AWS CDK 예제 코드를 확인하십시오. NPM에서 Amazon ECS의 AWS CDK 설명서와 공식 AWS CDK 구성을 확인하십시오.

 

원문 URL : https://aws.amazon.com/ko/blogs/compute/getting-started-with-the-aws-cloud-development-kit-for-amazon-ecs/

** 메가존클라우드 TechBlog는 AWS BLOG 영문 게재글중에서 한국 사용자들에게 유용한 정보 및 콘텐츠를 우선적으로 번역하여 내부 엔지니어 검수를 받아서, 정기적으로 게재하고 있습니다. 추가로 번역및 게재를 희망하는 글에 대해서 관리자에게 메일 또는 SNS페이지에 댓글을 남겨주시면, 우선적으로 번역해서 전달해드리도록 하겠습니다.