[レポート] DEV372 – Infrastructure Is Code with the AWS Cloud Development Kit #reinvent

概要

DEV372 – Infrastructure Is Code with the AWS Cloud Development Kit AWS Cloud Development Kit (AWS CDK) は AWS が提供するオープンソースのフレームワークです。開発者はモダンなプログラミング言語をフル活用して再利用可能なクラウドコンポーネントやアプリケーションをを定義し、AWS CloudFormation を使ってプロビジョンできます。AWS CDK は詳細を定義済みのリッチなクラスライブラリとともに提供されており、アプリケーションの開発に集中することができます。このセッションでは、なぜ私たちが AWS CDK を作ろうと考えたのか、そのコンセプトの概要を解説し、コード作成のライブデモによってAWS CDK があなたの良き友になれることを紹介します。

デモを中心としたAWS CDK機能の紹介のセッションです。

Developer previewとは言えCloudFormationを記述するよりも遥かにプログラマ寄りのとても良いツールのようでした。ちなみにDevelopers.IOではすでに8月に中山さんが記事を執筆しています。 【awslabs探訪】AWS Cloud Development Kit (AWS CDK)を使ってみた

Our infra management journey

Manual実行

  • Good 手動で構築。AWSコンソールから実行できる
  • Good 始めるのが一番かんたん
  • Bad 再現性がない
  • Bad エラーが起こりやすい
  • Bad 時間がかかる
  • Bad テスト、integration, regionとか
  • Bad KinesisとかDynamoDBは特に複雑になりがちでツライ

Scriptを使う

  • Good RubyやShellを使うことができる。コードで表現
  • Bad API Callに失敗したときの動作はどうする?
  • Bad 誰がメンテナンスするの?
  • Bad Resourceができたかどうかをどうやって知る?
  • Bad Rollbackはどうするのか?

Rsource provisioning engines

  • Good TeraformとかCfn
  • Good 自動化簡単
  • Good Reproducible
  • Good Rollbackとかもできるよ
  • Bad Configuration syntaxがつらい
  • Bad 長大なリストになりがち

Document Objet Models(DOMs)

  • Good リアルなコードで記載ができる
  • Good 任意の状態がかける
  • Bad Abstraction is not build in(VPCとか)

そこでAWS Cloud Development Kitの登場

インフラ環境の構造をコードで表現し、アプリケーションとして実行できます。アプリケーションを実行すると、CloudFormationテンプレートを生成しそれらを適用します。変更箇所はChangesetとしてテンプレートが更新され、Resource変化した分だけが更新されます。

現在対応している言語は以下の通り。

  • TypeScript
  • JavaScript
  • C#
  • Java
  • Python(Coming Soon!)

Construct Libraryが各言語用意されていて、インフラのリソース構成をモデル化し、とても柔軟に記述をすることが可能です。AWS CDKはまだDevelopers Previewバージョンです。CloudFormationのテンプレートを生成するだけでなく、コードの変更に伴うResource変更点のDiffや、CloudFormationテンプレートを出力しつつ適用など実行できるコマンドも充実しています。

デモ

Build CDK App

CDKのアプリケーションを作成しどのように動作するのか、CDK CLI WorkflowとCDK Construct Libraryを確認していきます。

このアプリケーションはSQSとLambdaとCloudWatch Logsを使って構築します。SQS QueueからメッセージをDequeueしてLambdaを実行し、Lambda内のコードででCloudwatch Logsにログを記述する単純なアプリケーションです(SQSへのMessage Enqueueは手動)

まずはLanguageを指定し、テンプレートを作成します。今回のデモではTypeScriptを選択しました。

$ mkdir hello-cdk
$ cd hello-cdk
$ cdk init app -l=typescript

EntryPointのコードはbin/hello-cdk.ts に記述されています。

#!/usr/bin/env node
import sqs = require('@aws-cdk/aws-sqs');
import cdk = require('@aws-cdk/cdk');

class HelloCdkStack extends cdk.Stack {
  constructor(parent: cdk.App, name: string, props?: cdk.StackProps) {
    super(parent, name, props);

    new sqs.Queue(this, 'HelloCdkQueue', {
      visibilityTimeoutSec: 300
    });
  }
}

const app = new cdk.App();

new HelloCdkStack(app, 'HelloCdkStack');

app.run();

HelloCdkStackはSingle Stackとして定義されています。コードはTop-Downで適用されるため、SQS Queueの作成、Topicの作成、TopicのSubscribeするQueueとして先程作成したQueueが定数に代入されているので、Queueの実体が入った定数を引数として指定します。

SQSのCDK Construct LibraryをImportします。

import sqs = require('@aws-cdk/aws-sqs');
  • Javaではmaven, JavaScript, TypeScriptではnpmなど環境に応じた依存解決ツールが利用されます。

  • cdk synth でコードからCloudFormationテンプレートを標準出力で表示します。

  • cdk deploy で生成したCloudFormationテンプレートを生成し適用します。
  • Lambda, Lambda Resource Eventを追加していきます。
  • DeployしなおすとCFnのチェンジセットが作成されて適用されます。
  • cdk diff を実行するとコード変更によるResourceの変更点をプレビューしてみることができます。

Write Construct

続いてDynamoDBテーブルへの書き込みを追加します。ここでは Write Construct という言葉が出てきています。こちらを参照

  • コンストラクタの中で考える
  • PermissionはリソースオブジェクトのGrant APIを呼び出す
  • Writing runtime configuration

ここから先程作成したSQS -> Lambda -> CloudWatch Logsの構成を変更していきます。

  • 新たなクラス QueueRecorder extends cdk.Constructを空で作成
  • 先程記述したLambdaをQueueに紐付ける箇所のコードを新たに作成した QueueRecorderクラスのコンストラクタへ移動
    • Lambdaを生成するコードもコンストラクタ内に追記
  • interfaceを公開。コンストラクタ引数でSQS Queueを取得するように変更
    • LambdaのEventSourceの対象のSQS Queueを引数でとってきた値を指定する
    • リソースオブジェクトの生成と目的に対しての設定の変更を分離してモデル化できた
  • 元のEntryPointのクラスの中で生成したSQS Queueリソースオブジェクトを定数に代入して QueueRecorderをインスタンス化するコードの引数に指定する

さらにDynamoDBへ書き込むコードへ変更

  • DynamoDB TableのConstruct LibraryをImportして、Tableを新規作成
  • DynamoDB Clientを作成
    • Recordsをforで回してItemに登録。Promiseで非同期実行し、await で結果を取得。
  • LambdaのプロパティにEnviroment変数を追加して、先程の手順で作成したDynamoDB Tableの名前を追加する
  • cdk diff でリソースの差分確認

最後にcdk-tweet-queueを利用したリソースをDeploy

CloudWatch Eventを利用してLambdaをキックし、LambdaがTweetの特定のハッシュのStreamを取得。取得したメッセージのStreamをSQSへEnqueue。あとは今まで作成したリソースの通り、LambdaがメッセージをDequeueしてDynamoDBのTableへ書き込みを実行しています。

Lambdaのコードとともにリソースの構築のコードも同時に記述されており、今までではCloudFormationでリソース作成とは別にLambdaをDeployするものを用意する必要がありましたが、そういったものがいらなくなっていました。すごい。

対応しているリソース

こちらがCDKで対応しているリソースのReferenceになります。

まとめ

まだまだDeveloper Previewで発展途上のツールですが様々なリソースに対応しています。ライブデモを見て主要な機能を見ることができ、非常に好感が持てるツールを知ることができました。

インフラのリソースStackをプログラム上でモデルとして表現しながら記述することができるため、リソースの生成とリソースへの設定やリンクといったコードを見ることでよりプログラム的に考えることができるようになりそうです。CloudFormationテンプレートを中間生成してCloudFormationによってResourceを変更することができるため、ツールに依存せずに既存の環境にも容易に導入が可能ではないかと感じました。

Infrastracture as a codeとはよく言われていますが、このツールはまさにInfrastracture is codeだと思いました。今後の開発にとても期待です。

参照