cdk 공식 문서 : docs.aws.amazon.com/cdk/latest/guide/home.html
workshop : cdkworkshop.com/
왜 terraform, serverless가 아닌 AWS CDK를 쓰려고 하는가?
우선 기존의 aws cli는 간단한 동작을 편하게 작업할 수 있지만 aws cli만으론 인프라 전체를 관리하기에는 어렵고 무엇보다 IaC라기에는 편의성이 떨어진다. cloudformation도 좋은 선택이긴 한데 yml 작성하기가 불편하기도하고, designer로 직접 그리는 것은 직관적이지만 'code'가 아니다.
IaC라는 관점에선 terraform은 좋은 선택이지만 HCL 언어를 별도 학습해야하고 필요하고 (물론 벤더 silo가 없다는 것이 장점입니다). serverless 프레임워크도 좋지만 이는 serverless에 한정된 인프라만 다룰 수 있었습니다.
멀티 벤더를 쓴다면 terraform이 좋은 선택이지만, AWS만을 쓸 것이라면 aws cli + aws CDK를 이용하는 것이 좋을 것 같다.
(7개월이 지난 후 회사에 입사하고보니 terraform을 쓰는게 더 낫다고 생각이 바뀌었다. 안녕)
게다가 HCL 언어가 아닌 익숙한 TypeScript, JavaScript, Python, Java, C#로 작성할 수 있다고 한다.
The AWS CDK supports TypeScript, JavaScript, Python, Java, and C#/.Net.
게다가 추가적으로, AWS Solutions Constructs라고 하여 이미 설계된 아키텍쳐를 가져다 쓸 수 있도록 AWS측에서 만들어 놓은 것들을 사용할 수 있습니다. AWS Solutions Constructs란 CDK를 위한 오픈 소스 확장 라이브러리로서 고유한 솔루션을 구축하는 데 도움이 되는 Well-Architected 패턴을 제공합니다. 아키텍쳐도 레고 블록처럼 뚝딱이 가능해진다는 거죠~
aws-cdk, @aws-dck/core 설치
yarn add aws-cdk -D // cdk를 cli로 활용하기 위함
yarn add @aws-cdk/core // 추가적으로 설치해주자
* cdk를 cli로 사용 가능하게 해줍니다.
* @aws-cdk/core의 버전은 cdk의 버전과 같아야 합니다. 가급적 고정 버전으로 설치해버립시다.
* 공식 문서에서는 글로벌하게 설치해서 사용하라고는 하는데 협업시 버전이 다르면 문제가 생길 수 있으므로 로컬에 설치한 후 npx를 통해서 사용할 수 있습니다. 물론 저는 항상 최신 버전을 사용할 예정이라서 그냥 글로벌리하게 설치했습니다.
npx cdk --version // 로컬 설치 후 사용할 때 현재 1.90.1 버전임
cdk --version // 글로벌 설치 후 사용할 때
cdk 명령어로는 다음과 것들이 있습니다. 다들 많이 사용됩니다.
dry-run(실제 반영 없이 예비 실행 + AWS CloudFormation 템플릿 생성) : cdk synth
스택 생성 및 배포 : cdk deploy
cdk를 이용한 배포 전에 필요한 자산을 저장하는 데 사용되는 S3 버킷을 생성 : cdk bootstrap
생성된 스택 제거 : cdk destroy
물론~ cdk를 전역에 설치하지 않았다면 npx를 사용해야 합니다.
cdk docs | Access the online documentation |
cdk init | Start a new CDK project (app or library) => 디렉토리가 비어었어야만 가능함. 직접 cdk를 구성하는게 마음 편할 수 있음. |
cdk list | List stacks in an application |
cdk synth | Synthesize a CDK app to CloudFormation template(s) |
cdk diff | Diff stacks against current state |
cdk deploy | Deploy a stack into an AWS account |
cdk destroy | Deletes a stack from an AWS account |
cdk bootstrap | Deploy a toolkit stack to support deploying large stacks & artifacts |
cdk doctor | Inspect the environment and produce information useful for troubleshooting |
쉽게 시작하기 위해 보일러 플레이트를 제공하고 있긴한데
이 방법은 완전히 빈 경로에서만 사용가능하기 때문에 직접 구성하여 사용하는 경우도 있습니다.
그래도, 공부 목적으로 아래 명령어를 입력한 후 어떻게 구성이 되어 있는지 확인해보는 것이 좋습니다.
AWS에서 만들어 준 베스트 케이스니깐요.
실제로도 그냥 바로 사용해도 아무 문제가 없는 코드들입니다. 급하면 cdk init --language typescript를 사용하셔도 아무 문제 없습니다. 여튼 지금 바로 살펴볼까요?
cdk init --language typescript
보일러 플레이트 살펴보기
* cdk는 '스택'이라는 이름으로 인프라를 관리합니다. 스택은 다른 스택을 포함할 수 있으며 (계층) 다른 스택과 연결될 수도 있습니다. cloudFormation에서 스택 생성할 때 보셨던 그 스택과 같은 개념입니다.
* @aws-cdk/... 꼴을 import할 때는 아래와 같은 컨벤션을 이용합니다. 워낙 @aws-cdk 스코프아래 있는 패키지가 많다보니 이렇습니다.
import * as s3 from "@aws-cdk/aws-s3"
* 해당 보일러 플레이트에서 구현한 인프라는 다음과 같습니다.
폴더 구조 중 핵심만 잡자면
./bin/src.ts, ./lib/src-stack.ts, ./cdk.json 입니다.
./lib/src-stack.ts
스택을 표현하는 코드의 뼈대입니다. 그러니까. Stack을 만드는 클래스입니다.
일반적으로 아래처럼 extends로 확장하여 사용합니다.
import * as cdk from '@aws-cdk/core';
export class SrcStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// The code that defines your stack goes here
}
}
여러분들의 프로젝트에 적합하게 @aws-cdk/aws-s3, @aws-cdk/aws-dynamodb, @aws-cdk/aws-ec2, @aws-cdk/aws-lambda, @aws-cdk/aws-apigateway 등등 사용하고자 하는 리소스를 설치하면 됩니다. 이 때, 버전은 cdk의 버전과 동일한 버전으로 설치해야 합니다.
예를 들어 cdk가 1.19.0이면 @aws-cdk/aws-ec2도 1.19.0을 설치해야 합니다.
그리고 VPC는 별도로 분리되어 있지 않고 ec2에 통합되어 있습니다.
보일러 플레이트는 다음과 같이 stack을 만들었습니다.
여러분들이 프로젝트를 만드려고 할 때도 이렇게 만들면 됩니다.
import * as sns from '@aws-cdk/aws-sns';
import * as subs from '@aws-cdk/aws-sns-subscriptions';
import * as sqs from '@aws-cdk/aws-sqs';
import * as cdk from '@aws-cdk/core';
export class CdkWorkshopStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const queue = new sqs.Queue(this, 'CdkWorkshopQueue', {
visibilityTimeout: cdk.Duration.seconds(300)
});
const topic = new sns.Topic(this, 'CdkWorkshopTopic');
topic.addSubscription(new subs.SqsSubscription(queue));
}
}
./bin/src.ts
이제 위에 정의한 스택을 기반으로 실제 리소스를 만들면 됩니다.
aws-cdk/core에서 cdk 인스턴스를 생성해준 다음, 아래와 같이 stack을 생성해주면 됩니다. 쉽죠?
#!/usr/bin/env node
import * as cdk from '@aws-cdk/core';
import { CdkWorkshopStack } from '../lib/cdk-workshop-stack';
const app = new cdk.App();
new CdkWorkshopStack(app, 'anyNameYouWant'); // 정의한 stack의 인스턴스
./cdk.json
cdk를 실행할 때 동작을 설정하는 파일입니다. 진입점 파일과 실행 명령, 환경변수 등을 설정할 수 있습니다.
{
"app": "npx ts-node --prefer-ts-exts bin/src.ts",
"context": {
"@aws-cdk/core:enableStackNameDuplicates": "true",
"aws-cdk:enableDiffNoFail": "true",
"@aws-cdk/core:stackRelativeExports": "true",
"@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true,
"@aws-cdk/aws-secretsmanager:parseOwnedSecretName": true,
"@aws-cdk/aws-kms:defaultKeyPolicies": true,
"@aws-cdk/aws-s3:grantWriteWithoutAcl": true
}
}
정리하자면 이렇습니다.
cdk.json으로 cdk 관련 설정 => Stack을 생성하는 코드 => index.ts든 어이든 해당 코드를 cdk 인스턴스와 함께 사용하여 구성 => cdk synth => cdk boilerplate(최초 실행때만) || cdk diff(수정시) => cdk deploy
cdk synth
cdk synth
chk.out 폴더가 생기면서 지정한 이름으로 anyNameYouWant.template.json 이라는 json 파일이 하나 생깁니다.
대략 아래와 같이 생겼습니다.
AWS::CDK::Metadata는 aws 측에서 분석을 위해 달아둔 것이므로 신경쓰지 않아도 됩니다.
{
"Resources": {
"CdkWorkshopQueue50D9D426": {
"Type": "AWS::SQS::Queue",
"Properties": {},
"Metadata": {}
},
"CdkWorkshopQueuePolicyAF2494A5": {
"Type": "AWS::SQS::QueuePolicy",
"Properties": {
"PolicyDocument": {},
"Queues": []
},
"Metadata": {}
},
"CdkWorkshopQueuewhatCdkWorkshopTopicEDA64C1F3BCFF65A": {
"Type": "AWS::SNS::Subscription",
"Properties": {},
"Metadata": {}
},
"CdkWorkshopTopicD368A42F": {
"Type": "AWS::SNS::Topic",
"Metadata": {}
},
"CDKMetadata": {
"Type": "AWS::CDK::Metadata",
"Properties": {},
"Metadata": {},
"Condition": "CDKMetadataAvailable"
}
},
"Conditions": {
"CDKMetadataAvailable": {
"Fn::Or": [... 매우 긴 내용]
}
}
}
cdk bootstrap
cdk를 이용한 배포 전에 필요한 자산을 저장하는 데 사용되는 S3 버킷을 생성합니다.
에셋이 없는 경우에도 하면 좋다고 합니다.
bootstrap 명령은 Amazon Simple Storage Service(S3) 버킷을 생성합니다. 이 버킷은 AWS CDK에서 배포 시에 필요한 자산을 저장하는 데 사용됩니다. 이 예에서는 자산을 사용하지 않으므로 이 단계를 건너뛸 수 있습니다. 하지만 처음부터 환경을 부트스트랩하는 것이 좋습니다. 즉, 자산을 사용하도록 선택하면 나중에 배포 오류가 발생하지 않습니다.
- 출처 : aws.amazon.com/ko/blogs/korea/aws-cloud-development-kit-cdk-java-and-net-are-now-generally-available/
bootstrap 결과 s3에 버킷이 생성된 것을 확인할 수 있습니다.
cdk deploy
말 그대로, 배포합니다. cdk는 cloudformation을 통해 배포됩니다.
CloudFormation에 직접 가져 확인해보면 다음 같습니다.
기존 배포 지우기 => 코드 수정 후 재 배포
물론 cloudformation을 지워도 되긴합니다만, 그렇다면 IaC 코드와 실제 인프라간의 차이가 생기기 마련입니다. 따라서, 우리는 cdk stack을 정의한 부분의 코드를 지우고, cdk diff를 통해 차이점을 확인한 후 재배포하면 됩니다. 쉽죠?
import * as cdk from '@aws-cdk/core';
export class CdkWorkshopStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// 모두 지워버렷!
}
}
cdk deploy
참고)
musma.github.io/2019/11/28/about-aws-cdk.html