AWS CDK로 시작하는 Infrastructure as Code

Andy (Yoon Yong) Shin·2021년 11월 21일
1
post-thumbnail

개요

이번 블로그에는, 제가 현재 공부하고 있는 AWS CDK라는 도구에 대해서 이야기 해보려고 합니다.

AWS CDK (Cloud Development Kit)는 AWS에 2019년 7월에 출시 되었으며, 궁극적으로는 AWS 에 존재하는 모든 service들을 IaC (Infrastructure as Code)의 개념으로 사용할 수 있게 해주는 도구인거 같습니다. 그럼 기존에 AWS service들을 관장해주기 위해 사용되던 CloudFormation이나 OpsWork 또는 AWS SAM은 IaC를 못하느냐라고 물으신다면, 가능은 하지만 불편하다라고 이야기할 수 있을거 같습니다. 사실 기존에 사용되던, CloudFormation과 AWS SAM의 stack 정의는 JSON 또는 YAML을 사용하고, OpsWork에 CookBook은 ruby가 사용됩니다. 운영하는 서비스가 장기적으로 성장하여 infrastructure가 커지면, 더 이상 JSON과 YAML로 관리하기 힘들 만큼 길어지며, 아무리 숙달된 DevOps 개발자라도 1000라인이 넘는 순간 눈이 많이 아퍼질것입니다. (그리고 실수에 빈도도 많이 늘어날수 밖에 없습니다) OpsWork에 Ruby에 대해서는... 침묵하겟습니다 ㅎ

그에 비해, AWS CDK 같은 경우 이미 개발자로서 친숙한 TypeScript, JavaScript, Python, Java, C#/.Net 그리고 Go Lang 까지 지원하며, 해당 language에 사용되는 for loop과 같은 logic을 모두 사용할 수 있으며, AWS CDK 공식 문서에서는 AWS CloudFormation으로 500줄이 필요한 stack 정의가 무려 50줄로 줄어든다고 강조 하고 있습니다. (참고로, AWS CTO Werner Vogels님이 엄청 밀고 있는 듯 한 느낌이...) 사실, 이미 YAML 또는 JSON 같은 data serialization language 가 아닌 programming language로 정의할 수 있다는 거, 자체가 reusability, code scalability, design pattern등 여러가지 측면에서 대폭 기능적 업그레이드라고 생각이 들며, IaC에 적합하다고 생각 합니다.

작동 원리

AWS CDK는 궁극적으로는 CloudFormation이 필요한 YAML 또는 JSON File을 만들어 냅니다. 하여, 만약에 CDK 프로젝트를 구성하였다면, cdk synth 명력어로 해당 cdk 프로젝트가 어떤 결과물로 CloudFormation에 전달되는 지 볼수 있습니다.

AWS CDK는 ployglot을 지원합니다. Polyglot이란 간단하게 정의 하자면, 여러가지 programming language로 코딩이 가능하지면, transfile을 통해 궁극적으로 1개의 language로 변화하여, 적용 되는 기능이라고 볼수 있습니다. 개발자는 TypeScript, JavaScript, Python, Java, C#/.Net 그리고 Go Lang과 같은 language로 코딩을 하지만, 궁극적으로는 JSII라는 도구를 통해 전부 Typesciprt로 변경되며, 해당 Typescript가 cdk로서 적용이 된다고 할 수 있습니다.

전체적인 순서로 보자면, 아래와 같습니다.

개발자가 선택한 Language → JSII (통해 Typescript로 변환) → AWS CDK (Typescript 도구를 통해 JSON으로 변경) → AWS CloudFormation (해당 서비스로 출시)

하지만, 실질적으로 개발자는 IDE에서 CDK로 사용하고 싶은 language와 CDK CLI만 사용하면, 위 모든것이 한번에 적용되게 되어 있습니다.

추가로, 1개의 cdk 프로젝트가 1개의 AWS CloudFormation stack과 1:1 mapping이 되기 때문에, 새롭게 정의 된 cdk 프로젝트는 해당 스택에 변경사항들이 적용이 됩니다.

(정황이 없이 의심을 하면 안되지만, 사실 AWS CDK을 사용해보면서, Kubernetes를 AWS에 쉽게 출시할 수 있게 도와주는 도구인 Kops와 매우 유사하게 작동한다고 생각하기에 출시일자를 비교 했을때 많이 AWS CDK가 kops에 많이 영향을 받은거 같다라는 느낌을 감출수가 없네요 ㅎ)

CDK Workshop 정주행 요약

(해당 Section은 https://cdkworkshop.com/에 TypeScript HelloWorld 파트를 요약한 섹션으로 조금 더 자세한 설명이 필요하시면 위 공식 workshop을 방문해주시면, 보다 depth 있게 AWS CDK를 경험 해보실 수 있습니다.)

Typescript로 Workshop을 진행하는 데 필요한 도구들

  • AWS CLI
  • AWS Account
  • NodeJS

프로젝트 설정

mkdir projectName && cd projectName // 프로젝트로 사용할 폴더 생성
cdk init sample-app --language typescript // 프로젝트 생성 

CDK 명령어 요약

// cdk project가 cloudformation으로 적용될 yaml 결과물을 보여준다.
cdk synth 

// cdk 같은 경우 마지막으로 적용된 cloudformation stack 정보를 s3 bucket에 
// 저장하여, diff 등 여러방면으로 사용 되는데, 해당 정보를 저장할 s3 bucket을
// 해당 명령어로를 통해 만들어서, 바로 cdk를 사용할 수 있게 해준다.
cdk bootstrap 

// cdk 프로젝트에 정의된 aws service를 cloudformation에 출시 한다.
cdk deploy

// 기존에 출시된 aws service와 현재 cdk 프로젝트에 정의된 리소스에 변경된 점을 
// output으로 보여줘 새롭게 출시하면 어떤 변화가 일어나는 지 미리 보여준다.
// 통상적으로 cdk diff를 먼저 사용하여, 문제가 없는 지 확인 후 사용하기를 권장
// 한다.
cdk diff

프로젝트 구조
bin: JSII 통해 typescript로 변환 된 결과물이 저장되는 공간 (자동 생성, 건들일 일이 없을 folder)

cdk.out: CloudFormation에 적용될 JSON이 저장되는 공간 (자동 생성, 건들일 일이 없을 folder)

lambda: lambda 서비스 사용할때 해당 lambda source code를 저장하는 장소. 실제로 폴더 이름이 lambda일 필요는 없다. 해당 path는 lib에서 stack 정의 할때 설정가능.

lib: CDK 프로젝트에 메인 폴더 이며, 여기서 code로 infrastructure를 정의한다.

test: 테스트 코드용.

프로젝트 진행

첫 프로젝트로 간단하게 Lambda와 API Gateway를 연결시켜, HTTP API를 서비스로 만드는 것이 목표 입니다. 위 cdk command로 모두 진행 후 아래 2가지 step을 진행 합니다.

  1. lambda folder 만든 후 hello.js 파일에 아래와 동일한 컨텐츠 적기 (lambda 코드는 그냥 hello world 와 요청 url을 돌려주는 코드입니다 ㅎ)

    exports.handler = async function(event) {
      console.log("request:", JSON.stringify(event, undefined, 2));
      return {
        statusCode: 200,
        headers: { "Content-Type": "text/plain" },
        body: `Hello, CDK! You've hit ${event.path}\n`
      };
    };
  2. lib/cdk-workshop-stack.ts에 아래와 같은 code로 변경

    lambda 소스 코드와, API Gateway에 handler가 lambda라는 것을 정의 하는 코드 입니다. 여기서 편리한건, 위 lambda 소스 코드도 cdk bootstrap에서 만들어진 s3로 같이 올라가서, 바로 적용이 됩니다.

    import * as cdk from "@aws-cdk/core";
    import * as lambda from "@aws-cdk/aws-lambda";
    import * as apigw from "@aws-cdk/aws-apigateway";
    
    export class CdkWorkshopStack extends cdk.Stack {
      constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
        super(scope, id, props);
    
        // defines an AWS Lambda resource
        const hello = new lambda.Function(this, "HelloHandler", {
          runtime: lambda.Runtime.NODEJS_14_X, // execution environment
          code: lambda.Code.fromAsset("lambda"), // code loaded from "lambda" directory
          handler: "hello.handler" // file is "hello", function is "handler"
        });
    
        new apigw.LambdaRestApi(this, "Endpoint", {
          handler: hello
        });
    
      }
    }

그리고 바로 cdk deploy를 하면, 아래와 같이 이 모든 AWS 서비스들이 CloudFormation으로 바로 셋팅이 됩니다.


출시 성공 후, API gateway 결과로 돌아온 url을 사용해보면,

✅  CdkWorkshopStack

Outputs:
CdkWorkshopStack.Endpoint8024A810 = https://nob2gib6p1.execute-api.ap-northeast-2.amazonaws.com/prod/

Stack ARN:
arn:aws:cloudformation:ap-northeast-2:706547749505:stack/CdkWorkshopStack/7b8624c0-4aa9-11ec-b716-065616440ec0

아래와 같이 잘 작동하는 것을 확인할 수 있습니다.

이제 테스트는 완료 했으니 다 사용한 리소스는 모두 지워야 겟죠?

가장 간단한 방법은 AWS CloudFormation에서 출시된 stack을 지우면, 모든 리소스가 사라집니다. 저 같은 경우 'CDKWorkshopStack' 입니다.

하지만, 저같은 경우 추후 계속 CDK를 가지고 놀려고 했기에.. 간단하게 'lib/cdk-workshop-stack.ts'를 아래와 같이 변경 후 출시 하였습니다.

import * as cdk from "@aws-cdk/core";
import * as lambda from "@aws-cdk/aws-lambda";
import * as apigw from "@aws-cdk/aws-apigateway";

export class CdkWorkshopStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // // defines an AWS Lambda resource
    // const hello = new lambda.Function(this, "HelloHandler", {
    //   runtime: lambda.Runtime.NODEJS_14_X, // execution environment
    //   code: lambda.Code.fromAsset("lambda"), // code loaded from "lambda" directory
    //   handler: "hello.handler" // file is "hello", function is "handler"
    // });
    //
    // new apigw.LambdaRestApi(this, "Endpoint", {
    //   handler: hello
    // });

  }
}

'cdk diff' 를 해보면, 아래와 같이 나오네요 (다 지운다 머 이런 내용이겟죠?)

'cdk deploy' 후 확인 해보니, API Gateway와 Lambda 모두 깔끔하게 지워 졋습니다 ㅎ

끝으로

기존에 AWS CloudFormation은 너무 높은 learning curve와 많은 yaml 정의를 외워야지만, 사용가능 했더라면, AWS CDK 같은 경우, IDE에 도움으로 제공되는 auto complete과 JSDoc의 도움말 그리고 programming language로 공유가 가능한 https://cdkpatterns.com/patterns/ 등 제공되는 게 되게 풍부 하다보니, 보다 쉽게 접근할 수 있었던거 같습니다. 한가지 아쉬운점은 CDK를 배우는 순간 약간 AWS에서 밖에 사용할수 없다라는 종속성이 생긱는 기분인거 같네요 ㅎ Data engineer로서 추후에 AWS CDK를 사용하여, severless data pipeline을 한번 구축해보면은 참 재밌을거 같다라는 생각을 하였습니다. 이상 AWS CDK에 대한 글을 마치겠습니다. 🙂

2개의 댓글

comment-user-thumbnail
2022년 1월 6일

좋은 글 감사합니다. 잘보고 갑니다!

1개의 답글