【AWS】AWS CDK初心者のわたしが開発を始めるにあたり参考になったサイトまとめ（ちょこっとハンズオン有）

#はじめに
先日AWS CDKを初めて触ってみたのですが、使ってみて想像していたより便利だったのと、AWSの勉強を始めて年月が浅い方向けに解説がされているようなサイトやブログがあまり多くないように感じたので、私がCDKでの開発を始めるにあたり参考になったサイトをまとめて紹介しようと思います。
ついでに簡単なハンズオンを行いつつ、気を付けた方がよいポイントもはさみつつ解説していこうと思います。

#AWS CDKとは
公式サイトを見てみます。

https://aws.amazon.com/jp/cdk/

> AWS クラウド開発キット (AWS CDK) は、使い慣れたプログラミング言語を使用してクラウドアプリケーションリソースを定義するためのオープンソースのソフトウェア開発フレームワークです。

私が使ってみた感覚としては、CloudFormationテンプレートを作成するにはyamlやjsonファイルで独自の文法を利用してテンプレートを作成する必要がありますが、CDKを利用すればいつも使っている言語（私の場合Python）でテンプレートを作成することができるので使いやすい、といったように感じました。

#参考になったサイト
以下2つのサイトを主に参考にしていました。

###①AWS CDK ワークショップ

https://summit-online-japan-cdk.workshop.aws/

CDKで開発する上での前提条件も詳しく記載されており、環境を整備する上ではとても参考になると思います。
各言語ごとのワークショップもあり、その中でcdkコマンドの基本的な使い方も記載されているので、とりあえずハンズオンやってみて学習したいといったときに活用しやすいサイトかと思います。

###②AWS CDK API Reference

https://docs.aws.amazon.com/cdk/api/latest/docs/aws-construct-library.html

CDKでコーディングする際のリファレンスサイトです。
各言語ごとに記載されているのでとても参考になります。
ちなみに画面上部に各言語のリファレンスページに遷移するボタンがあるのですが、
![リファレンス02.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/e67b9fdf-c4c8-c046-8e20-8d82cf212f4f.jpeg)
ここから遷移したリファレンスページはちょっとわかりづらいので、画面左側から作成したいサービスを選んだ方が、コードの記載例も載っていてわかりやすかったです。
![リファレンス04.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/e213835a-c8f9-e01a-e38e-211f18bc53ee.jpeg)
私はpythonでコーディングしていたので以下のページからPythonのコード記載例を参考にしていました。
![リファレンス05.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/7994ac33-c29f-38ac-e119-03f6da4afb48.jpeg)
![リファレンス06.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/18932d2a-26ee-c903-9e63-99203f382f12.jpeg)

#ちょこっとハンズオン
上記のサイトを参考に、ちょこっとハンズオンしていこうと思います。
※ちょこっととありながら説明文多めでボリューミーになってしまいましたがご了承ください。

**ハンズオンの流れ**
以下の流れでハンズオンを行っていきます。

* [前提条件の整理](#前提条件の整理)
* [CDK開発環境の作成](#cdk開発環境の作成)
    * [プロジェクトディレクトリの作成](#プロジェクトディレクトリの作成)
    * [Virtualenvのアクティブ化](#virtualenvのアクティブ化)
    * [Pythonモジュールのインストール](#pythonモジュールのインストール)
    * [IDEで開く](#ideで開く)
* [実際にコードを書いて実行してみる](#実際にコードを書いて実行してみる)
    * [S3モジュールのインストール](#s3モジュールのインストール)
    * [リファレンスを表示する](#リファレンスを表示する)
    * [コードを書いてみる](#コードを書いてみる)
    * [実行してみる](#実行してみる)

###前提条件の整理
[ワークショップの前提条件](https://summit-online-japan-cdk.workshop.aws/15-prerequisites.html)をもとにまずは環境を整えます。
私はWindowsで開発を行ったので、以下のような条件で環境を整えました。

* AWS CLI : Ver1
    * 上記のサイト上でVer1をインストールするような流れになっていますが、今後CDKとは関係なくCLIを利用するのであればVer2をインストールしておいた方がよいと思います。（[Ver2インストール](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2-windows.html)）
* Node.js : 12.18.3
    * Windowsに古いバージョンのNode.jsがインストール済みなことがあるので、上記サイト上のリンクから10.3.0以降のバージョンにアップデートしておきます。
* Python : 3.8.5
    * 3.6以降のバージョンである必要があります。

AWSアカウントとユーザーは会社で保有している検証用アカウントと管理者に払い出してもらったIAMユーザーを、IDEはVSCodeを利用しました。
上記の環境が整ったらAWS CDKツールキットのインストールを行いますが、Node.jsのインストールが完了しnpmコマンドが問題なく利用できる必要がありますのでご注意ください。

前提条件の整理ができたところで、さっそくハンズオンに入っていきましょう。

##CDK開発環境の作成
ここからは[Pythonのワークショップ](https://summit-online-japan-cdk.workshop.aws/30-python.html)を参考にハンズオンを進めていきます。

###プロジェクトディレクトリの作成
CDKプロジェクトを格納するための空のディレクトリを作成します。
私の場合は「C:\Users\user\Documents\aws_cdk」というディレクトリを予め作業用に作成しておき、その配下でCDKプロジェクト用に空ディレクトリ「temp-hands-on」を作成しました。

```
> mkdir temp-hands-on && cd temp-hands-on
```

このとき作成するディレクトリ名がそのままCloudFormation時のスタック名となります。

作成したディレクトリ配下に移動し、```cdk init```コマンドを実行して、CDKプロジェクトを作成します。

```
cdk init sample-app --language python
```

以下のような出力がされたら成功です。

```
>cdk init sample-app --language python
Applying project template sample-app for python

# Welcome to your CDK Python project!

You should explore the contents of this project. It demonstrates a CDK app with an instance of a stack (`temp_hands_on_stack`)
(~~中略~~)
To add additional dependencies, for example other CDK libraries, just add to
your requirements.txt file and rerun the `pip install -r requirements.txt`
command.

## Useful commands

 * `cdk ls`          list all stacks in the app
 * `cdk synth`       emits the synthesized CloudFormation template
 * `cdk deploy`      deploy this stack to your default AWS account/region
 * `cdk diff`        compare deployed stack with current state
 * `cdk docs`        open CDK documentation

Enjoy!
(~~中略~~)
Please run 'python -m venv .venv'!
Executing Creating virtualenv...
✅ All done!
```

###Virtualenvのアクティブ化
上記の```cdk init```コマンドでディレクトリ内に仮想環境も作成してくれているので、以下のコマンドでvirtualenvをアクティブにします。これは```cdk init```コマンド実行後にコマンドライン上に出力されたログにも記載されています。

```
> source .venv/bin/activate
```

コマンドプロンプトが以下のように変わっていたらvirtualenvのアクティブ化に成功しています。

```
(.venv) >
```

###Pythonモジュールのインストール
必要なPythonモジュールをインストールします。

```
pip install -r requirements.txt
```

私が実行したときは以下のようなエラーになってしまいました。

```
(~~中略~~)
ERROR: jsii 1.30.0 has requirement attrs~=20.1, but you'll have attrs 21.2.0 which is incompatible.
(~~中略~~)
WARNING: You are using pip version 20.1.1; however, version 21.1.2 is available.
You should consider upgrading via the 'c:\users\user\documents\aws_cdk\temp-hands-on\.venv\scripts\python.exe -m pip install --upgrade pip' command.
```

pipコマンドをアップグレードしなさいとのことなので、ログに記載されているコマンドをそのまま実行します。

```
> c:\users\user\documents\aws_cdk\temp-hands-on\.venv\scripts\python.exe -m pip install --upgrade pip
```

アップグレードが正常に終了したあとに、もう一度```pip install -r requirements.txt```を実行してみると、以下のようにモジュールのインストールが成功したことを確認できました。

```
> pip install -r requirements.txt
(~~中略~~)
Installing collected packages: attrs, temp-hands-on
  Attempting uninstall: attrs
    Found existing installation: attrs 21.2.0
    Uninstalling attrs-21.2.0:
      Successfully uninstalled attrs-21.2.0
  Attempting uninstall: temp-hands-on
    Found existing installation: temp-hands-on 0.0.1
    Uninstalling temp-hands-on-0.0.1:
      Successfully uninstalled temp-hands-on-0.0.1
  Running setup.py develop for temp-hands-on
Successfully installed attrs-20.3.0 temp-hands-on-0.0.1
```

###IDEで開く
ここまでできたらVSCodeでプロジェクトの格納されているディレクトリを開いてみます。

VSCodeを開き「フォルダーを開く」をクリックします。
![test_001_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/8dc70e81-c186-38b9-bf81-75054336a7b0.jpeg)

作成した「C:\Users\user\Documents\aws_cdk\temp-hands-on」を開きます。
![test_003.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/086b53f6-b667-1311-0434-cea3d61bc524.jpeg)

開発用にインストールされた内容がVSCodeからも閲覧できることが確認できればOKです。各ファイルについての説明は[プロジェクト構造](https://summit-online-japan-cdk.workshop.aws/30-python/20-create-project/300-structure.html)に記載されていますのでこちらご確認ください。
![test_004_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/816fcc02-eafd-5b0e-8ba6-515adc8532ee.jpeg)

##実際にコードを書いて実行してみる
ワークショップでこのあとに続く[CDK SYNTH](https://summit-online-japan-cdk.workshop.aws/30-python/20-create-project/400-synth.html)からは、あらかじめ用意されているPythonコードを利用してSQSとSNSの構築をしているので、まずはcdkでコーディングされたものをデプロイしてみたいという方は参考にしてみてください。

私はリファレンスサイトから、ワークショップには記載のなかったサービスを作成するときにどのようなコードの書き方をするのか試してみたかったので、実際にS3バケット作成用のコードを書いて実行してみました。

###S3モジュールのインストール
以下コマンドを実行し、S3モジュールをインストールしておきます。

```
> pip install aws-cdk.aws-s3
```

エラーにならず、コマンドが正常終了していればOKです。

###リファレンスを表示する
以下にリファレンスサイトのページ遷移の仕方を書いていますが（手順一つでも変えるとわかりづらいページに飛ばされてしまうので）、面倒くさい方は[ここ](https://docs.aws.amazon.com/cdk/api/latest/python/aws_cdk.aws_s3/README.html)からページ遷移しておいてください。

[リファレンス](https://docs.aws.amazon.com/cdk/api/latest/docs/aws-construct-library.html)サイトから「@aws-cdk/aws-s3」を探して矢印ボタンをクリックし、「Overview」をクリックします。
![test_009_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/05acae8f-414a-886a-b89b-e6c7502405d1.jpeg)

Pythonをクリックして、Python用リファレンスページに遷移します。
![test_009_02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/9f7b8c4d-587b-a9fe-ea07-4d89f54bc46d.jpeg)
![test_010_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/ebd711ec-43d2-aae1-417b-0a3d6fcfce01.jpeg)


###コードを書いてみる
VSCodeに移動し、「C:\Users\user\Documents\aws_cdk\temp-hands-on\temp_hands_on\temp_hands_on_stack.py」を開きます。ここでコーディングを行っていきます。

もともと記載されていたSQSとSNS構築用のコードが記載されているので、すべて削除し、以下のコードに書き換えます。

```python:temp_hands_on_stack.py
from aws_cdk import (
    core,
    aws_s3 as s3,
)

class TempHandsOnStack(core.Stack):

    def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        ## S3バケットを"TempHandsOnBucket"という名前で作成
        my_bucket = s3.Bucket(self, "TempHandsOnBucket")
```

とても単純な、S3バケットを作成するだけのコードを作成してみました。

###実行してみる
####デプロイのその前に、、、
初めてデプロイを行う際は、「Bootstrapスタック」を構築する必要があるため、以下コマンドを実行します。

```
> cdk bootstrap
```

以下の出力がされたらコマンド成功です。

```
>cdk bootstrap
 ⏳  Bootstrapping environment aws://{アカウントID}/ap-northeast-1...
 ✅  Environment aws://{アカウントID}/ap-northeast-1 bootstrapped (no changes).
****************************************************
*** Newer version of CDK is available [1.110.0]  ***
*** Upgrade recommended (npm install -g aws-cdk) ***
****************************************************
```

####差分確認
以下コマンドで更新前のファイルとの差分確認をしておきます。

```
> cdk diff
```

以下のような出力になると思います。

```
>cdk diff
Stack temp-hands-on
Conditions
[+] Condition CDKMetadata/Condition CDKMetadataAvailable: {"Fn::Or":[{"Fn::Or":[{"Fn::Equals":[{"Ref":"AWS::Region"},"af-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-east-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-northeast-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-northeast-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-southeast-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-southeast-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ca-central-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"cn-north-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"cn-northwest-1"]}]},{"Fn::Or":[{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-central-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-north-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-west-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-west-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-west-3"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"me-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"sa-east-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-east-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-east-2"]}]},{"Fn::Or":[{"Fn::Equals":[{"Ref":"AWS::Region"},"us-west-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-west-2"]}]}]}

Resources
[+] AWS::S3::Bucket TempHandsOnBucket TempHandsOnBucketE0675BCE
```

####いざ、デプロイ
以下コマンドでデプロイします。

```
> cdk deploy
```

以下が出力されます。

```
>cdk deploy
temp-hands-on: deploying...
temp-hands-on: creating CloudFormation changeset...
  0/3 |18:06:00 | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | temp-hands-on User Initiated
  0/3 |18:06:06 | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | temp-hands-on User Initiated
  0/3 |18:06:10 | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata)
  0/3 |18:06:10 | CREATE_IN_PROGRESS   | AWS::S3::Bucket    | TempHandsOnBucket (TempHandsOnBucketE0675BCE)
  1/3 |18:06:11 | CREATE_IN_PROGRESS   | AWS::S3::Bucket    | TempHandsOnBucket (TempHandsOnBucketE0675BCE) Resource creation Initiated
  1/3 |18:06:12 | CREATE_IN_PROGRESS   | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
  1/3 |18:06:12 | CREATE_COMPLETE      | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata)
  3/3 |18:06:32 | CREATE_COMPLETE      | AWS::S3::Bucket    | TempHandsOnBucket (TempHandsOnBucketE0675BCE)
  3/3 |18:06:33 | CREATE_COMPLETE      | AWS::CloudFormation::Stack | temp-hands-on

Failed resources:

 ✅  temp-hands-on

Stack ARN:
arn:aws:cloudformation:ap-northeast-1:{アカウントID}:stack/temp-hands-on/8f97abd0-d594-11eb-923e-0e3c24a4d9b9
```

無事成功です！
AWSのマネジメントコンソールの方でも確認してみましょう。
![test_011_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/cd251107-7dfc-0154-79de-cb57dac98a47.jpeg)
プロジェクトディレクトリ名でスタックが作成されています。


![test_012_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/f123e983-20b2-ac0e-c76d-ece5277a9b87.jpeg)
イベントも問題ありません。


![test_013_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/bf5f5406-1ea8-e880-ab1a-bda05721e61a.jpeg)
S3バケットも無事作成されています！

以上でハンズオンは終了です。


#おわりに
今回はCDKを始めるにあたっての参考になったサイトのまとめと、参考サイトをもとに簡単なハンズオンをやってみました。
特にリファレンスサイトなんかは私のググり力が足りず、上司にも相談して引っ張ってきてもらったものです。
CDKのようなIaC系のツールは、今後どんどん使う人や仕事でも求められるケースが多くなってくるのかなと思いますので、本記事が私のようなCDK使うのが初めてという方の一助になれば幸いです。