AWS CDKまとめ、TIPS

# 概要

2019年7月にAWS CDKがGA(generally available)になり、気になっている方も多いのではないかと思います。私は最近AWS CDKをがっつり使い始めたので、入門知識から勘所までまとめていきたいと思います。周りのエンジニアの感想をきてみても「めちゃめちゃいい」という意見が多かったので、是非みなさん一度試してみてください。

ちなみに、個々のリソースの記述方法に関しては色々な記事が出ているので省略し、本記事は概観とTIPSを記載します。

# AWS CDKとは

- AWSインフラをコード化するツール
- 真の意味で抽象化されたIaCが実現可能
- 基本的にTypeScriptで記述します。Pythonなどでも記述できますが、内部的にはnode.jsを起動しています。
- CDKの実行時は、コードからCloudFormationテンプレートを作成して実行しますので、動作がブラックボックス化しにくいのも魅力です。
- その他AWS DevDayの資料などによくまとめて頂いています。
  - [セッション資料・動画一覧 - AWS DevDay Tokyo 2019 \| AWS](https://aws.amazon.com/jp/about-aws/events/2019/devday/doc/) の B-3

# hello world


```
$ npm i -g aws-cdk // cdkコマンドをインストール
$ mkdir hello-cdk
$ cd hello-cdk
$ cdk init sample-app --language=typescript
```

これでアプリの雛形が生成されました。

# ファイル階層

結構シンプルです。

helle-cdk
  |-- bin libで定義したスタックを読み込んで初期化します
  |-- lib スタックごとにファイルを分けて定義を記載します。
  |-- test 
  |-- cdk.json
  |-- tsconfig.json 
  |-- jest.config.js
  
cdk.jsonにはdeploy時の動作が記載されています。

```json
{
  "app": "npx ts-node bin/hello.ts"
}
```
ts-nodeというtscやwebpackなどでコンパイルせずに'node'のように実行するツールを使用して、bin/hello.tsを実行しています。

# デプロイ

```
$ cdk deploy
```

また

```
$ cdk synth
```

でCloudFormationテンプレートを生成します

# 開発

開発の進め方を説明します。

## 前提知識

### コンストラクタ

最初の生成されたlib/hello-stack.tsはこんな感じです。

```ts:lib/hello-stack.ts
export class HelloStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const queue = new sqs.Queue(this, 'HelloQueue', {
      visibilityTimeout: cdk.Duration.seconds(300)
    });

    const topic = new sns.Topic(this, 'HelloTopic');

    topic.addSubscription(new subs.SqsSubscription(queue));
  }
}
```

例えば、SNS Queueは```new sqs.Queue...```で生成しています。コンストラクタの引数は基本的に 1 this(cdk.Stack), 2 id: string, 3 パラメータです。ちなみに、この時に動かすコンストラクタをhight-levelコンストラクトと言います。これは、オールインワンパッケージのようなもので、デフォルトの設定とか、普通そうするだろうというベストプラクティス設定とか、デフォルトのIAMポリシーとか諸々を含んだものです。そのため、`visibilityTimeout`しか指定していませんが、しっかりと設定されたSQS::Queueが生成されます。

一方 low-level コンストラクトも存在し、クラス名の先頭に必ず'Cfn'付きます。これはCloudFormationと一対一で対応するプロパティーを提供します。試しにsqs.CfnQueueのパラメータに設定する'visibilityTimeout'の定義をみてみると、以下の通りに記載されており、一対一対応しているCloudFormationテンプレートのプロパティーへのリンクが記載されています。（超親切）

```ts
/**
* `AWS::SQS::Queue.VisibilityTimeout`
* @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sqs-queues.html#aws-sqs-queue-visiblitytimeout
*/
readonly visibilityTimeout?: number;
```

High-levelコンストラクトはlow-levelコンストラクトを組み合わせて実装されています。両者の使いわけとして、基本はhigh-levelの方を使用しますが、対応していない新しいリソースの設定や、細かな設定をする際はやむなくlow-levelコンストラクトを使用する必要がある場合があります。

## ドキュメントの見方

公式のドキュメントを参照します。
[AWS CDK · AWS CDK Reference Documentation](https://docs.aws.amazon.com/cdk/api/latest/)
左ナビにリソースの分類がずらっと並んでいますので、必要な部分を参照します。初めて使用するリソースに関しては 'overview' を確認するとわかりやすく、コードレベルでざっくりと使用方法が書かれています。

![スクリーンショット 2019-11-16 17.45.51.png](:storage/ed56df33-accb-47fd-8e8b-b6fc49c90f7f/330bfd9a.png)

その後、Constructsから必要なリソースの詳細を確認してください。

# TIPS

## 書き方は複数通り存在する

複数のリソース間の依存関係を定義する時は、書き方が複数存在することが多いです。例えば、S3にトリガイベントを設置する時は、S3にトリガイベントを定義することもできるし、S3で呼び出すLambdaのイベントソースにS3を指定することもできます。なので、方法に迷った際はあまりこだわらず、どちらの思考が分かりやすいかをアプリケーションに合わせて判断するのが良いかと思います。

## 必要なリソースは自分で追加する

今回のハンズオンではインストールされていないリソースが多数あります。必要なものは

```
npm i --save @aws-cdk/aws-lambda
```
などで、インストールしてください。
その際、私の環境の問題かもしれませんが、型エラーが発生する場合があります。その場合は以下のコマンドを実行すると解決します。

```
cd node_modules/@aws-cdk
rm -rf */node_modules
```

## バグは多い

まだ2019年7月にgaになったばかりですので、明らかにバグと言える症状には割とすぐに遭遇するし、Issueも多数上がっているのが現状です。
しかし、割と細かい設定まで十分実用的なレベルで非常に使いやすいツールなので、全てをコード上に表現しきりたいという過激派思想とうまく 折り合いをつけながら、できる範囲で使用をしていくのが良いかなと思っています。