AWS CDK v2を触ってみた

# 初めに

私は大卒でITとは無縁の田舎の会社で６年間営業を経験→SESでエンジニア1年ほど(現在)
開発言語はJs、C#
そんなに学歴はないです。

# なぜ書こうと思ったか
ただ、オンラインでハンズオンしているだけでは意味がないと思い
アウトプット目的として書く事にした。

# 内容について
タイトル通りAWS CDK v2を触ってみました。
内容としてAWS公式のワークショップだったと思います。（曖昧ですみません）

# そもそものAWS CDKとは(座学)
AWS Cloud Development Kit (AWS CDK) v2 は
いわゆるインフラのコード化することができるツールキットです。
コードで定義し、CloudFormation でプロビジョニングすることができます。

対応言語はTypeScript、JavaScript、Python、Java、C#

# 触ってみた

1.Cloud9の起動します。設定値はデフォルト。

2.CDK v2の動作確認
Cloud9はCDKやCDKの実行に必要なモジュールなどがあらかじめインストールされています。
また、Cloud９は起動時にマネジメントコンソールにログインしているIAMアカウント情報をもとに一時的に払い出された権限で動作するが、別IDE環境を用いる場合、別途IAMアカウントの作成と設置(aws configure等)も必要です。
```
cdk --version
// 2.22.0 (build 1db4b16)
```
3.作業ディレクトリを作成
```
cdk init app --language javascript
```
4.JavaScript 用に CDK を初期化し、[ALL done!]と表示されれば成功
```
const cdk = require('aws-cdk-lib');
const s3 = require('aws-cdk-lib/aws-s3');

class HelloCdkStack extends cdk.Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    new s3.Bucket(this, 'MyFirstBucket', {
      versioned: true
    });
  }
}

module.exports = { HelloCdkStack }
```
*定義されているスタックの一覧確認
```
cdk ls
```

5.lib/hello-cdk-stack.js内を以下に変更
```
const cdk = require('aws-cdk-lib');
const s3 = require('aws-cdk-lib/aws-s3');

class HelloCdkStack extends cdk.Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    new s3.Bucket(this, 'MyFirstBucket', {
      versioned: true
    });
  }
}
```
6.以下を実行すると行なった作業がローカルのCDK環境に反映され、CloudFormationTemplate が生成されます。
このハンズオンで用いているのは L2 と言われている上位レイヤです。
レイヤについては他にて記事にします。
```
cdk synth
```
7.CDKの初期設定（必須）。リージョンごと、言語ごとに必ず初回作業時の実行が必要
実行後にCloudFormationを確認するとCDKToolkitとというスタックが生成されており
これはCDKが動作に必要とする情報を保存するS3バケットやIAMロール等を含むCDKの動作環境構築を行うスタックです。
```
cdk bootstrap
```
8.[cdk deploy]を実行すると、CloudFormation 経由で S3 バケットが作成されます。
```
cdk deploy
```
９.lib/hello-cdk.jsの中身を以下に変更
```
const cdk = require('aws-cdk-lib');
const s3 = require('aws-cdk-lib/aws-s3');

class HelloCdkStack extends cdk.Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

new s3.Bucket(this, 'MyFirstBucket', {
  versioned: true,
  removalPolicy: cdk.RemovalPolicy.DESTROY,
  autoDeleteObjects: true
});
  }
}

module.exports = { HelloCdkStack }
```
１０.以下を実行し変更点が出力されます。
```
cdk diff
```
11.再度 cdk deployを実行し、作業実行確認を問われるので[y+Enter]で実行する
スタックがしばらくの間アップデート中となります。
完了したスタックのテンプレートを確認するとYaml CloudFormation テンプレートを確認できます。
```
cdk deploy
[y+Enter]
```
12.cdk destroyを実行して、作業実行確認を問われるので[y+Enter]で実行すると、環境を削除します。
CloudFormationのスタック画面から咲くほど確認できていたスタックが消えていることが確認できます。
S3バケットも、削除されていることも確認できます。
```
cdk destroy
```

 # TypeScript による Lambda の作成
typescript を用いて、Lambda 関数を作成してみます

1.ディレクトリの作成
```
cd
mkdir cdk-workshop && cd cdk-workshop
```
２.TypeScript 用に init を実行します。今度は TypeScript をベースとして先程とほぼ同じフォルダ構造とファイルが展開されています
```
cdk init sample-app --language typescript
```
3.TypeScript は JavaScript へ変更される必要があります。ファイルを変更するたびにそれがリアルタイムで行われるよう以下を実行します。
```
npm run watch
```
4.上記実行したターミナルは閉じずに、+ボタンで別のターミナルを開きます。（New Terminal)(（cdk-workshop のディレクトリに必ず移動して下さい）
lib/cdk-workshop-stack.tsを確認すると先ほどs3を指定していた箇所にデフォルトでSQS,SNSが設定されていることがわかります。
5.生成されるCloudFormationテンプレートとCDK v2設定ファイルを見比べてください
```
cdk synth
```
6.プロジェクトごとに行う必要はありませんが今回は言語を変更したため実行が必要です。
```
cdk bootstrap
```
7.実行を行うか確認されますので[y + Enter]を押します。
CFnスタックが生成されていますので、完了を待ちます。
```
cdk deploy
y + Enter
```
8.実行が完了したら、SQS / SNS ができていることを確認します。
[lib/cdk-workshop-stack.ts]ファイル内を以下に変更します。
保存した際に、先程実行した watch のターミナルが存続していれば自動で js ファイルも書き換わります。
```
import * as cdk from 'aws-cdk-lib';

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

    // nothing here!
  }
}
```
9.差分をとります。中身は何も定義されていませんので、実行すると SNSや SQS が Destroy されると表示されています。
```
cdk diff
```
10.今回の deploy は、最初に作成したものを削除するコマンドと同意義になります。
```
cdk deploy
```
11. lambda 関数を作成していきます。まず bin や lib と同じ階層に[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`
  };
};
```
12.差分を確認します。新しく Lambda 関数と IAM ロールが追加されることがわかります。
```
cdk diff
```
13.[cdk deploy]で実行します。確認が求められますので[y + Enter]をおします
```
cdk deploy
```
14.Lambda 関数ができていますので、クリックし、テストタブからテスト実行をしてみてください。
15.[hello.js]の中身を以下に変更します。
```
exports.handler = async function(event) {
  console.log("request:", JSON.stringify(event, undefined, 2));
  return {
    statusCode: 200,
    headers: { "Content-Type": "text/plain" },
    body: `Good Afternoon, CDK! You've hit ${event.path}\n`
  };
};
```
16.デプロイが先ほどよりかなり高速に終了していることがわかります。
```
cdk deploy --hotswap
```
17.Lambda 関数を呼び出せる API Gateway を作成します。
[lib/cod-workshopstack.ts]の中身を以下に変更
```
import * as cdk from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as apigw from 'aws-cdk-lib/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"
    });

    // defines an API Gateway REST API resource backed by our "hello" function.
    new apigw.LambdaRestApi(this, 'Endpoint', {
      handler: hello
    });

  }
}
```
18.差分を確認します
```
cdk diff
```
19.. [cdk deploy]を実行します。途中確認が求められますので[y + Enter]をおします
```
cdk deploy
y + Enter
```
20.生成された URL をブラウザで開くと Lambda のテストメッセージが出てきていることを確認します。
21.環境の削除
```
cdk destroy
```

# AWS CDKのレイヤについて
CDKには2種類のレイヤが存在し、今回のハンズオンではL2と呼ばれる上位レイヤでした。
もう１つはレイヤ1と呼ばれる下位レイヤになります。

レイヤ１はCloudFromationを書くのと同等のパラメータ設定が必要になります。
レイヤ２はCloudFromationの様々なパラメーターが抽象化されておりより少ない設定で作業を行うことができます。
ただし、CloudFormation で設定可能なすべてのパラメーターを設定できないケースがあり、その場合Ｌ1 レイヤという下位レイヤを用いることで設定が可能になります。

# CDKで使う基本コマンド
今回のハンズオンで色々とコマンドを実行したので改めて紹介します。

CDKコードに含まれるCDK スタックの一覧を表示
```
cdk ls
```
CDKコードに含まれたCDKスタックから、CloudFormationテンプレートを生成・表示
スタックを指定することも可能
```
cdk synth[スタック名]
```
CDKで定義したAWSリソースをデプロイする前に、次のコマンドでCDKデプロイ環境を構築
実行すると、CDKToolkitというCloudFormation Stackが作成され、S3バケットcdktoolkit-stagingbucket-[random]が作成される
```
cdk bootstrap
```
CDKコードで定義したAWSリソースをデプロイ
スタックを指定することも可能
```
cdk deploy[スタック名]
```
デプロイされたスタックまたはローカルテンプレートファイルと比較し、違いが見つかった場合は差分を返す。
スタック名を指定しないと全ての差分を返す。
```
cdk diff[スタック名]
```
CDKデプロイされたリソースを削除
```
cdk destroy [スタック名]
```
# 参考
[クラスメソッドさん](https://dev.classmethod.jp/articles/cdk-practice-26-version-2/)
[AWS公式](https://docs.aws.amazon.com/ja_jp/cdk/?id=docs_gateway)