ちょっと話題の記事

【コードでインフラ定義】CDKという異次元体験をさくっとやるのに便利なAWS公式Workshopの紹介

CDKを最初に試して見るには非常に便利なCDK Workshopの紹介です。ぜひこれでCDKの奥深い新鮮な世界に入門いただければ。
2019.09.26

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

「俺もそろそろ乗らなくては、この、ビッグウェーブに!!」

皆さん、CDK触っていますか?DevelopersIOにも、CDK | 特集カテゴリー で、既に20以上のブログがあがっていたり、その人気はうなぎのぼりです。

CDKとは一口で言えば「コードでインフラを定義する」ものです。「いやぁ、これ楽。素晴らしい」という声を同僚からよく聞くので、自分も早速試してみようとしたところ、CDK Workshopなるものを発見し、手を動かして学ぶには凄くわかりやすく良い教材だったので、その内容を紹介します。

  • CDK実行するための環境定義
  • LambdaとAPI Gatewayを利用した簡単なサービスの公開
  • モジュールの作り方
  • クラス構造の解説
  • デバッグ方法
  • モジュールの利用方法
  • 関連リソースの一括削除

これらをおよそ2時間ほどで体験できるので、まずはサクッと手を動かして、この新鮮な感覚をぜひ皆さんに味わってもらいたいなと思います。

(祭) ∧ ∧
 Y  ( ゚Д゚)
 Φ[_ソ__y_l〉     CDKマツリダワッショイ
    |_|_|
    し'´J

「CDK」とは

What Is the AWS CDK? - AWS Cloud Development Kit (AWS CDK)

「コードでインフラを定義する」ものです。従来から提供されているCloudFormationは、基本JSONやYAMLといった構造化ファイルでリソースを定義していたのですが、CDKでは、いわゆるひとつのアプリケーションコード(TypeScript、JavaScript、Python、Java、C#/.NET)を利用できるのが大きな違いと言えます。

「CDK Workshop」とは

こちらからアクセスできます。

AWS CDK Intro Workshop :: AWS Cloud Development Kit (AWS CDK) Workshop

AWSのWorkshopは他にもありますが、基本的には「手を動かしながらその分野を学ぶための材料がまとめられたWebサイト」という認識で良いです。

CDKは、JavaScript, TypeScript, Python, Java, .NETに対応していますが、Workshopで対応しているのはTypeScriptとPythonのみです。

このWorkshopを終了すると、以下を達成できるとのこと。CDKについての基礎は学べそうです。

  • Create new CDK applications.
  • Define your app’s infrastructure using the AWS Construct Library
  • Deploy your CDK apps to your AWS account
  • Define your own reusable constructs
  • Consume constructs published by other people

今回、ハマコーは独断と偏見でTypeScriptを使ってみます。

Prerequisites(環境セットアップ、前提の確認)

最初に環境セットアップとして、以下を順に実施していきます。

  • AWS CLI
  • AWS Account and User
  • Node.js
  • IDE for your programming language
  • AWS CDK Toolkit
  • Python

ただ、実施内容はほぼほぼこちらのドキュメントと同じなので、どちらかを参照しながらできれば良いと思います。

Workshopでは、IAMユーザーの作成から全て丁寧に教えてくれるので、AWS自体の経験が少ない方は、WorkShopを参照されることをオススメします。

IDEの設定

ここは、Workshopならではのところ。以下のIDEが推奨されていて、一番オススメはVSCodeとのことです。

  • VSCode (recommended)
  • AWS Cloud9
  • Atom with the atom-typescript plugin
  • vim with tsuquyomi
  • WebStorm
  • Emacs with the tide mode
  • PyCharm

自分の普段利用エディタはVSCodeなので、VSCodeにTypeScriptの環境を作っておきましょう。自分は事前に、VSCodeオフィシャルのこちらのドキュメントみて、一通り実行してみました。あわせて、TypeScriptの初歩の初歩の感触をつかむのにも有用です。

CDKのインストール

本丸、CDKのセットアップです。下のコマンドを叩くだけ。簡単。

$ npm install -g aws-cdk

インストールが完了したら、バージョンを確認します。

$ cdk --version
1.8.0 (build 5244f97)

TypeScriptによるCDK Workshopの体験

いよいよ、Workshopを進めながらCDK体験していきます。Workshopは以下の章立てで構成されています。

  • New Project
  • Hello, CDK!
  • Writing constructs
  • Using construct libraries
  • Clean up

以降、各章について、内容を紹介していきます。

New Project(プロジェクトの新規作成)

New Project :: AWS Cloud Development Kit (AWS CDK) Workshop

基礎の学習

一番最初にCDKプロジェクトを作成しつつ、CDKの基本をおさらいしていきます。

npm run watchを使った、.ts(typescript)から自動で.js(JavaScript)を生成する設定が紹介されたのち、CDKプロジェクトの各ファイルの役割の説明があります。ここは必見です。

Project structure :: AWS Cloud Development Kit (AWS CDK) Workshop

といっても、最初はあまりピンとこない部分が多いと思うので、さらっと説明を読んで一覧しつつ、メインファイルのエントリポイントと、アプリケーション用ファイルが何なのかを理解します。

  • エントリーポイント
  • bin/cdk-worksho.ts
  • 基本的には変更する必要なし
  • アプリケーションのメインファイル
  • lib/cdk-workshop-stack.ts
  • アプリケーションの構築で利用するファイルは主にこちら

lib/cdk-workshop-stack.ts

import sns = require('@aws-cdk/aws-sns');
import subs = require('@aws-cdk/aws-sns-subscriptions');
import sqs = require('@aws-cdk/aws-sqs');
import cdk = require('@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));
  }
}

このコードだけで、以下の4つのリソースが作成されます。これ凄いな。

  • AWS::SQS::Queue
  • AWS::SNS::Topic
  • AWS::SNS::Subscription
  • AWS::SQS::QueuePolicy

cdk synthによるCloudFormationテンプレートの作成

CDKプロジェクト内、以下のコマンドでCDKよりCloudFormationのテンプレートが標準出力されます。

$ cdk synth

CDKは裏側では、AWSのAPIを直接叩いているわけではなく、一度CloudFormationのテンプレートとスタックが作成されて、そこからAWSの各種リソースが作成される仕組みというのがここから実感できます。

リソースのデプロイ

いよいよリソースをAWS環境に作ります。

最初に、CDK toolkitのオペレーションに必要なS3バケットを作成します。

$ cdk bootstrap

そうすると、CloudFormationが動いて専用のS3バケットが作成されます。関係ないけど、CDKのコマンドは結果が非常にカラフルで見た目わかりやすくて良い.

Webコンソールを確認すると、しっかりCDKToolkitというスタックとS3バケットが生成されていることがわかります。

この前処理が終わったら、いよいよリソース作成していきます。

$ cdk deploy

このコマンドを実行すると、途中で「ほんとにやっていいの?大丈夫?」的な確認を求められます。ここらへん、terraformと似てますね。

yを押すと無事、リソースが作成されます。

Do you wish to deploy these changes (y/n)? y
CdkWorkshopStack: deploying...
CdkWorkshopStack: creating CloudFormation changeset...
 0/6 | 06:28:12 | CREATE_IN_PROGRESS   | AWS::SNS::Topic        | CdkWorkshopTopic (CdkWorkshopTopicD368A42F) 
 0/6 | 06:28:12 | CREATE_IN_PROGRESS   | AWS::CDK::Metadata     | CDKMetadata 
 0/6 | 06:28:13 | CREATE_IN_PROGRESS   | AWS::SQS::Queue        | CdkWorkshopQueue (CdkWorkshopQueue50D9D426) 
 0/6 | 06:28:13 | CREATE_IN_PROGRESS   | AWS::SNS::Topic        | CdkWorkshopTopic (CdkWorkshopTopicD368A42F) Resource creation Initiated
 0/6 | 06:28:13 | CREATE_IN_PROGRESS   | AWS::SQS::Queue        | CdkWorkshopQueue (CdkWorkshopQueue50D9D426) Resource creation Initiated
 1/6 | 06:28:14 | CREATE_COMPLETE      | AWS::SQS::Queue        | CdkWorkshopQueue (CdkWorkshopQueue50D9D426) 
 1/6 | 06:28:14 | CREATE_IN_PROGRESS   | AWS::CDK::Metadata     | CDKMetadata Resource creation Initiated
 2/6 | 06:28:14 | CREATE_COMPLETE      | AWS::CDK::Metadata     | CDKMetadata 
 3/6 | 06:28:23 | CREATE_COMPLETE      | AWS::SNS::Topic        | CdkWorkshopTopic (CdkWorkshopTopicD368A42F) 
 3/6 | 06:28:25 | CREATE_IN_PROGRESS   | AWS::SNS::Subscription | CdkWorkshopQueue/CdkWorkshopStackCdkWorkshopTopicD7BE9643 (CdkWorkshopQueueCdkWorkshopStackCdkWorkshopTopicD7BE96438B5AD106) 
 3/6 | 06:28:26 | CREATE_IN_PROGRESS   | AWS::SQS::QueuePolicy  | CdkWorkshopQueue/Policy (CdkWorkshopQueuePolicyAF2494A5) 
 3/6 | 06:28:26 | CREATE_IN_PROGRESS   | AWS::SQS::QueuePolicy  | CdkWorkshopQueue/Policy (CdkWorkshopQueuePolicyAF2494A5) Resource creation Initiated
 3/6 | 06:28:26 | CREATE_IN_PROGRESS   | AWS::SNS::Subscription | CdkWorkshopQueue/CdkWorkshopStackCdkWorkshopTopicD7BE9643 (CdkWorkshopQueueCdkWorkshopStackCdkWorkshopTopicD7BE96438B5AD106) Resource creation Initiated
 4/6 | 06:28:26 | CREATE_COMPLETE      | AWS::SQS::QueuePolicy  | CdkWorkshopQueue/Policy (CdkWorkshopQueuePolicyAF2494A5) 
 5/6 | 06:28:26 | CREATE_COMPLETE      | AWS::SNS::Subscription | CdkWorkshopQueue/CdkWorkshopStackCdkWorkshopTopicD7BE9643 (CdkWorkshopQueueCdkWorkshopStackCdkWorkshopTopicD7BE96438B5AD106) 
 6/6 | 06:28:28 | CREATE_COMPLETE      | AWS::CloudFormation::Stack | CdkWorkshopStack 

 ✅  CdkWorkshopStack

Stack ARN:
arn:aws:cloudformation:ap-northeast-1:123456789012:stack/CdkWorkshopStack/303a18f0-df12-11e9-9e06-0e8a9cd56576

WebコンソールのCloudFormationからも、作成されたリソースを確認できます。

ここまでで、CDKの基本的な動作の確認は完了です。

Hello, CDK!(CDKを始める)

Hello, CDK! :: AWS Cloud Development Kit (AWS CDK) Workshop

前章で基礎の基礎を学んだあと、ここでは、より実践的なアプリケーションを作成していきます。Lambda functionとAPI Gatewayのエンドポイントを作成し、アクセスすると、ハートウォーミングなメッセージが表示されるとのこと。どんなんやそれ。

サンプルリソースの削除

もともとのサンプルには、SNSとSQSのリソースを入れていたけれど、これは特に使う予定がない(!)ということで、最初にこれらリソース削除します。対象ファイルから、関連リソースのコードを削除したのち、以下のコマンドで、クライアントのStackをリモートにデプロイした時に実施されるリソースの変更を事前に確認できます。CloudFormationにおけるChangeset、TerraformにおけるPlanみたいなものすね。

$ cdk diff

そうすると、こんなグラフィカルな感じで、変更差分を出力してくれます。dstroyされる部分が、赤文字で表示されるのは非常にわかりやすいです。正直、CloudFormationのChangesetより300万倍わかりやすいかと。

この結果が問題なければ、再度cdk deployすることで、上で表示されたリソースが無事削除されます。

LambdaをCDKで書いてみる

いよいよ、実践編。LambdaをCDKで構築してみます。Lambdaで利用するコードは、CDKプロジェクトの中にCDKのコードとは別で格納します。

lambda/hello.js

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`
  };
};

AWS Lambda construct libraryのインストール

CDKでは、AWSの各リソースに対応したモジュールをAWS Construct Libraryとして提供しています。インストール方法は簡単。以下のようにnpm installを利用します。

$ npm install @aws-cdk/aws-lambda

Typescriptの威力をもろに感じるのがここらへんですね。コード中インポートしたモジュールから利用するクラスの自動補完が効きまくるので非常にコーディングが楽です。こんな感じ。

是非、サンプルコードについては、コピペするのではなく、実際にタイピングしてみて、その補完の効き具合に感動してみるのをオススメします。

その後は、cdk diffからのcdk deployで、いつものLambdaが作成されることを確認します。

API Gatewayの構築

似たような手順で、API Gatewayも構築していきます。API GatewayのモジュールをLambdaと同様の手順でインストールした後、cdk-workshop-stack.tsを編集、cdk diffからcdk deployにより、API Gatewayが作成されます。

作成されたAPI Gatewayのエンドポイントにcurlを投げてみて、無事以下のレスポンスが返ってくればOKです。

$ curl https://ozn9heg0s6.execute-api.ap-northeast-1.amazonaws.com/prod/
Hello, CDK! You've hit /

Writing Constructs(モジュールの作成)

Writing constructs :: AWS Cloud Development Kit (AWS CDK) Workshop

ここでは、簡単なカウンターアプリを作成しながら、自作モジュールの作成方法や権限周辺のトラブルシュートを習得します。

ヒットカウンターモジュールの作成、Lambdaコードの作成

内容としては、最初にヒットカウンターのモジュールを作っていくんですが、このWorkshopの良い点は、各ソースコードについて、それぞれの構造のポイントがシンプルに記載されている点。

このコードに対して。

lib/hitcounter.ts

import cdk = require('@aws-cdk/core');
import lambda = require('@aws-cdk/aws-lambda');

export interface HitCounterProps {
  /** the function for which we want to count url hits **/
  downstream: lambda.IFunction;
}

export class HitCounter extends cdk.Construct {
  constructor(scope: cdk.Construct, id: string, props: HitCounterProps) {
    super(scope, id);

    // TODO
  }
}

こんな解説が都度ついてきます。

このあたりの解説ですが、そもそものTypeScriptそのものの最低限の知識が無いとよくわからないと思うので、事前に言語そのものの知識を習得しておくことをオススメします。このコードだとTypeScriptにおけるInterfaceの使われ方をしっておいたほうがピンとくると思います。

自分は、こちらの記事(Typescriptのinterfaceの使い方 - Qiita)を参考にしました。

CloudWatch Logsによるデバッグ

実際にコードして動かしてみるのですが、エラーになります。このWorkshopでは意図的にエラーとなるコードが仕組まれていて、「わお!エラーがでましたね。でも落ち着いてデバッグしていきましょ〜」的なのりで、CloudWatch Logsの画面を確認します。

このあたりは、Lambdaのデバッグでよくやる内容なので、慣れている人はわかりやすいかと思います。主に、権限が足りていないところをデバッグしてコードを修正していきます。

最後の動作確認

これらコードの修正をして、最終的にGETリクエストを投げると、DynamoDBのパス付きでリクエストされた回数がカウントされるアプリケーションが構築されます。あとは、好きにコードをカスタマイズしながら、理解を深めてみれば良いんじゃないでしょうか。

Using construct libraries(ライブラリーの利用)

Using construct libraries :: AWS Cloud Development Kit (AWS CDK) Workshop

ここでは、npmでインストールできるライブラリーを利用して、さらにアプリケーションを拡張していきます。利用するライブラリーはこちら。

引数で与えたDynamoDBのテーブル内容を表示するモジュールです。利用方法は簡単。npm installでモジュールをインストールしたのち、cdk-workshop-stack.tsに、TableViewerという名前でモジュールを追加。クラス生成するときに必要なDynamoDBのテーブル名をhitcounter.tsでパブリック指定した変数から取得するようにコードを修正します。

改めて、cdk deployすることで、簡単に画面を追加することができました。API GatewayのエンドポイントにGETリクエストを投げたときのパス別に集計されたDynamoDBテーブルの内容が、一覧できます。

Clean Up(作成したリソースの削除)

ここまでもろもろ作成したリソースの削除もIaCならではの簡単一発。cdk destroyだけ。

$ cdk destroy
Are you sure you want to delete: CdkWorkshopStack (y/n)? y

CDKという異次元体験を2時間で体験できる最良のWorkshop

自分これで初めてCDK触ってたんですが、CloudFormationで細かくYAMLとリソースのプロパティを書いていたときとは全く異なるレイヤーで、インフラやサービスそのものを定義できるのには驚きました。デフォルトでCDK側で設定されるプロパティが多いためか、APIレベルでの指定必須項目をほぼほぼ省略できるため、コード量が非常に少なくなります。

自分はブログを書きながら試してみましたが、このWorkshop、内容は非常にコンパクトに纏まっていて、CDKが持つその威力と基本的な考え方は十分このWorkshopで体験することができます。

特にトラブルがなければ2時間程度で終了するボリュームなので、「最近、めっちゃアツいと噂のCDK、体験してみたいなぁ」という人で、TypeScriptにある程度馴染みがあるかたは、まずはこのWorkshopを実施してみることをオススメします。

また、同じWorkshop内にはPython版もほぼ同じ内容で存在するので、文法的にPythonが馴染みがあるかたは、ぜひこちらも試してみていただければと思います。

それでは、今日はこのへんで。濱田(@hamako9999)でした。

(おまけ)他のWorkshopもあり、初学にオススメ

AWSからは、他にも様々なWorkshopが提供されています。弊社園部治が、下記記事にまとめているので、是非こちらもご参照ください。