aws-cdk的Hello World ~cdk環境構築~ aws-cdk#1

# はじめに
AWS環境をaws-cdkを使って構築するようになったので
そのキャッチアップも兼ねて共有していこうと思います。

こちらの記事を参考に進めていく中で、自分なりに気づいたところを書いていきます。
https://dev.classmethod.jp/author/tanaka-keisuke/

### AWS-CDKとは
AWS環境の構築を使い慣れたプログラミング言語で記述してしまおう！！という試みです。
IaCの一種ですね

>TypeScriptで書いたソース
>↓
>`cdk deploy`を実行
>↓
>CloudFormationのテンプレートに自動で変換
>↓
>CloudFormationのAPIからそのままデプロイ

やることは**コードを書く＋`cdk deploy`を実行**だけ！！
これだけでAWSのコンソールぽちぽちから解放されるのです！！
まあ、コードを書くのがしんどいのですが。。

##### -参考- AWS-SDK
似たようなツールにAWS-SDKがあります。
名前も似ている上に、これもプログラミング言語でAWSを操作できるというからややこしい。。。
ただこっちはプログラミング言語を使って**APIを直接叩きに行っている**というところがミソです。

CDKがCfnテンプレートを作って構築するのと比較するとわかりやすいですね。
Cfnのロールバックやスタックごとに管理するという機能を使えないのがSDKの弱点ですね。

# 環境構築
以下のような環境で構築していきます。
```
% node -v
v14.16.0

% aws --version
aws-cli/2.4.18 Python/3.8.8 Darwin/21.3.0 exe/x86_64 prompt/off

% cdk --version
1.142.0
```


# プロジェクト作成
### aws-cdkインストール
aws-cdkがインストールされていない場合は以下のコマンドでインストールします。
実行ディレクトリを`aws`とします。
```
//バージョンを指定する場合は@以下で指定します。
aws % npm install "aws-cdk@1.142.0"
..略
+ aws-cdk@1.142.0
added 212 packages from 231 contributors and audited 212 packages in 12.086s
..略

aws % cdk --version
1.142.0
//想定通りのバージョンがインストールされていることを確認します。
```
インストールが完了すると実行ディレクトリ配下に以下のようなファイルが作成されます。
```
aws % ls -l
drwxr-xr-x  4 private  staff    128  3 11 21:47 node_modules
-rw-r--r--  1 private  staff  79198  3 11 21:47 package-lock.json
```

### プロジェクト作成
いよいよcdkプロジェクトの作成です。
ここで作成するディレクトリが**プロジェクトディレクトリ**となります
```
aws % mkdir cdk && cd cdk

//下記コマンドで初期ファイルを自動で作成・配置します。
cdk % cdk init app --language typescript
..略
✅ All done!
*************************************************************************************************************************************************
*** Newer version of CDK is available [2.15.0]                                                                                                ***
*** Information about upgrading from version 1.x to version 2.x is available here: https://docs.aws.amazon.com/cdk/v2/guide/migrating-v2.html ***
*** Upgrade recommended (npm install -g aws-cdk)                                                                                              ***
*************************************************************************************************************************************************
//新バージョンの2.15.0に上げろと言ってきますが無視します。
```
aws-cdk V2は別の機会に検証しようと思います。

cdk配下には以下のようなファイル、ディレクトリが作成されます。
```
cdk % ls -l
-rw-r--r--    1 private  staff     543  3 11 22:00 README.md
drwxr-xr-x    3 private  staff      96  3 11 22:00 bin
-rw-r--r--    1 private  staff    1256  3 11 22:00 cdk.json
-rw-r--r--    1 private  staff     157  3 11 22:00 jest.config.js
drwxr-xr-x    3 private  staff      96  3 11 22:00 lib
drwxr-xr-x  361 private  staff   11552  3 11 22:00 node_modules
-rw-r--r--    1 private  staff  269154  3 11 22:00 package-lock.json
-rw-r--r--    1 private  staff     530  3 11 22:00 package.json
drwxr-xr-x    3 private  staff      96  3 11 22:00 test
-rw-r--r--    1 private  staff     650  3 11 22:00 tsconfig.json
```
### ファイル説明
重要な（だと思う）ファイルについてここで軽く触れます

##### bin/cdk.ts
このファイルでスタックを記述し、Cfnのテンプレートにしていく
初期状態の内容はこんな感じ（コメントは省略してます）
```
import 'source-map-support/register';
import * as cdk from '@aws-cdk/core';
import { CdkStack } from '../lib/cdk-stack';

const app = new cdk.App();
new CdkStack(app, 'CdkStack', {
  //ここにコードを追記していく
});
```

##### lib/cdk-stack.ts
ここでbin/cdk.tsに記述するスタックのclassを記述していく。
初期状態はこう(コメントは省略してます)
```
import * as cdk from '@aws-cdk/core';

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

     });
  }
}

```

# AWSアカウント設定
aws-cdk がスタックをデプロイする際にAWSアカウントの認証情報が必要になる。
以下の通り設定する。
※AWSCLIのインストールがまだの場合は[こちら](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html)
※IAMコンソールからAWSアカウントのAccessKeyとSeacretKeyは取得する。
```
//profile名は任意で指定してください。
% aws configure --profile test
AWS Access Key ID [None]:1111111111
AWS Secret Access Key [None]:AAAAAAAAAAAA
Default region name [None]:ap-northeast-1
Default output format [None]:
%
//credentialsファイルが作成され、中身にAccessKeyとSeacretKeyが設定されていること
% cd ~
~ % ls .aws
-rw-------  1 private  staff   39  3  8 21:29 config
-rw-------  1 private  staff  113  3  8 21:29 credentials
```

# やっとスタック作成
今回は初回なのでS3バケットが作成されることを確認して完了としようと思います。

### ライブラリインストール
[リファレンス](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-s3-readme.html)を見ながら必要なパッケージをインストール。
```
//パッケージのバージョンはcdkのバージョンと揃える！
cdk % npm install "@aws-cdk/aws-s3@1.142.0"
..略
+ @aws-cdk/aws-s3@1.142.0
added 28 packages from 15 contributors and audited 240 packages in 8.435s 
```
##### 参考までに。。。
package.jsonを確認すると、インストールされたパッケージが自動的に記録されます。
```
..略
"dependencies": {
    "@aws-cdk/aws-s3": "^1.142.0", //追加されてますね
    "@aws-cdk/core": "1.142.0",
    "source-map-support": "^0.5.16"
  }
```
今後もライブラリを追加するたびにこのファイル（とpackage-lock.json）は自動的に更新されます。

###### ちなみに、、
`npm install`を実行するとpackage.jsonに記述されたとおりに(バージョンも含めて)インストールされるので
一気にインストールしたい時などは、このファイルを更新してから`npm install`がおすすめです。

### スタック作成
##### lib/cdk-stack.ts
 まずはこちらから編集していきます。
ここでは`CdkStack`クラスを設定していきます。
このクラスを実際に記述するのはbin/cdk.tsです。
``` diff_typescript
import { Bucket } from "@aws-cdk/aws-s3";
+import * as cdk from "@aws-cdk/core";

export class CdkStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
+    new Bucket(this, "FirstBucket");
  }
}
```
これだけ、これだけでS3Bucketが作成されます。
とはいえ寂しいので名前だけでもつけてみます。
```diff_typescript
import { Bucket } from "@aws-cdk/aws-s3";
import * as cdk from "@aws-cdk/core";

export class CdkStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
-    new Bucket(this, "FirstBucket");
+    new Bucket(this, "FirstBucket", {
+      bucketName: "myfirstbucket220311",
+    });
  }
}
```
[リファレンス](https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-s3.Bucket.html)を見るとデフォルト暗号化(encryption)やライフサイクルポリシー(lifecycleRules)も設定できそうですがまたの機会とします。

##### bin/cdk.ts
実はこのファイルは何も書かなくてもデフォルトの状態でAWS上にデプロイできてしまうんです。
というのも
```
import "source-map-support/register";
import * as cdk from "@aws-cdk/core";
import { CdkStack } from "../lib/cdk-stack";

const app = new cdk.App();
new CdkStack(app, "CdkStack", {});
```
先ほど書いたCdkStackが既に記述されているからです。便利！！

### Stackデプロイ
それではいよいよ`cdk deploy`をしていきたいと思います！
が、デプロイの前にどんな変更がAWSにされるのかを確認します。
```
cdk % cdk diff CdkSack --profile test
..略
Resources
[+] AWS::S3::Bucket FirstBucket FirstBucket8E7B2622 
```
`cdk diff`で現状のAWS上のスタックとの差異を確認できます。
`cdk diff [Stack名] --profile [profile名]`が構文です。

想定通り、S3が作成されるという結果だったのでデプロイしていきます。
構文は`cdk deploy [Stack名] --profile [profile名]`です。
```
cdk % cdk deploy CdkStack --profile test
✨  Synthesis time: 2.13s

CdkStack: deploying...
CdkStack: creating CloudFormation changeset...






 ✅  CdkStack

✨  Deployment time: 37.44s

Stack ARN:
arn:aws:cloudformation:ap-northeast-1:527985513840:stack/CdkStack/4f083290-a147-11ec-910a-06d813364df5

✨  Total time: 39.57s
```
無事デプロイできたようです。
```
% aws s3 ls --profile test
2022-03-11 23:27:11 myfirstbucket220311
```
##### 必要に応じて
必要に応じて`cdk destroy --profle test`にてスタックを削除します。
今回はオブジェクトが入っていないので無課金ですが、思わぬ課金対象にお金を取られないように気をつけてください！

# 最後に
長くなりましたが、aws-cdkのHello World的初期作業でした。
AWSアカウントのクレデンシャルなんかはハマりポイントでしたね。`--profile`指定に苦しみました。

これで終わりというわけではなく、実施した検証は都度#2.3...と続けていきたいなと思います。
[次回](https://qiita.com/KbSota/items/3d38f5e000696a47e38d)