AWS CDK公式チュートリアル実況プレイ(VPC編)

AWS CDKに興味があったので公式ドキュメントを見ながら進めて見る。
公式ドキュメントに日本語がないのがちょっと辛いが。。。

## 公式チュートリアル

Clod9にAWS CDKを導入する公式チュートリアルがあったのでまずはそちらを進める。

### AWS CDK CLIのインストール

まずはnpm経由でcliをインストールしてみる

```
npm install -g aws-cdk
```

↓のようなログが流れてインストール完了

```
added 2 packages, and audited 3 packages in 4s

found 0 vulnerabilities
npm notice 
npm notice New minor version of npm available! 8.5.0 -> 8.19.2
npm notice Changelog: https://github.com/npm/cli/releases/tag/v8.19.2
npm notice Run npm install -g npm@8.19.2 to update!
npm notice 
```

↓のコマンドでバージョンが表示されていればおk

```
cdk --version 
2.47.0 (build 3528e3d)
```

### AWS CDK CLIにAWSアカウントを紐付け

公式では「ブートストラップ」って表現が使われているけどまぁ紐付けってことだと思う。

以下のコマンドでaws cliに紐づいている認証情報を取得。
おそらく `~/.aws/credentials` のdefaultって名前のついたプロファイルが使われていそう

```
aws sts get-caller-identity
```

実行結果

```
{
    "UserId": "xxxxxxxxxxxxx",
    "Account": "nnnnnnnnnnnn",
    "Arn": "arn:aws:iam::nnnnnnnnnnn:user/yyyyyyyy"
}
```

んで↓を実行すると紐付けできる

```
cdk bootstrap aws://ACCOUNT-NUMBER/REGION
```

実行結果

```
⏳  Bootstrapping environment aws://nnnnnnnnnnnn/ap-northeast-1...
Trusted accounts for deployment: (none)
Trusted accounts for lookup: (none)
Using default execution policy of 'arn:aws:iam::aws:policy/AdministratorAccess'. Pass '--cloudformation-execution-policies' to customize.
CDKToolkit: creating CloudFormation changeset...
 ✅  Environment aws://nnnnnnnnnn/ap-northeast-1 bootstrapped.
```

おそらくこれで「このユーザーを使ってこのリージョンにリソースを立てられるようにしたよ」ってのが設定できたのかなと思う

### AWS CDKプロジェクトの開始

cdk cliの準備が整ったので早速プロジェクトを作る

```
mkdir cdk-demo
cd cdk-demo
cdk init --language typescript
```

languageのところにはCDKで利用できる言語が使える。一覧は↓に載っている。今回はTypescriptを使う
https://docs.aws.amazon.com/ja_jp/cdk/v2/guide/getting_started.html

↓みたいな感じのログが流れる

```
Applying project template app for typescript
# Welcome to your CDK TypeScript project

This is a blank project for CDK development with TypeScript.

The `cdk.json` file tells the CDK Toolkit how to execute your app.

## Useful commands

* `npm run build`   compile typescript to js
* `npm run watch`   watch for changes and compile
* `npm run test`    perform the jest unit tests
* `cdk deploy`      deploy this stack to your default AWS account/region
* `cdk diff`        compare deployed stack with current state
* `cdk synth`       emits the synthesized CloudFormation template

Initializing a new git repository...
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint: 
hint: 	git config --global init.defaultBranch <name>
hint: 
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint: 
hint: 	git branch -m <name>
bin/cdk-demo.ts:18:  // env: { account: '123456789012', region: 'us-east-1' },

[ERROR] Matched one or more prohibited patterns

Possible mitigations:
- Mark false positives as allowed using: git config --add secrets.allowed ...
- Mark false positives as allowed by adding regular expressions to .gitallowed at repository's root directory
- List your configured patterns: git config --get-all secrets.patterns
- List your configured allowed patterns: git config --get-all secrets.allowed
- List your configured allowed patterns in .gitallowed at repository's root directory
- Use --no-verify if this is a one-time false positive
Unable to initialize git repository for your project.
Executing npm install...
npm WARN deprecated w3c-hr-time@1.0.2: Use your platform's native performance.now() and performance.timeOrigin.
✅ All done!
```

初期ディレクトリは↓のような感じで、サンプルのstackがすでに入っている状態

![作業の開始_—_cdk-demo](/Users/tomolico/Library/Application Support/typora-user-images/作業の開始_—_cdk-demo.png)

各種ディレクトリ・ファイルの意味

- bin...実際にAWSにリソースを作る際の起点になるディレクトリ
- lib...binファイルの中身を決める。基本はここを編集する
- test...テストをかける。サンプルコードを見る限りはリソースの作成やプロパティのチェックができそおう
- cdk.json...CDK全体の設定ファイルにあたるjson

### binファイルにアカウント情報を設定

デフォルトではローカルcliに設定したアカウントとリージョンが使われるが
コメントアウトを外してコード上に記載することで確実に狙ったアカウントとリージョンにデプロイできる

`bin/cdk-demo.ts`

```typescript
const app = new cdk.App();
new CdkDemoStack(app, 'CdkDemoStack', {
  /* If you don't specify 'env', this stack will be environment-agnostic.
   * Account/Region-dependent features and context lookups will not work,
   * but a single synthesized template can be deployed anywhere. */

  /* Uncomment the next line to specialize this stack for the AWS Account
   * and Region that are implied by the current CLI configuration. */
  // env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },

  /* Uncomment the next line if you know exactly what Account and Region you
   * want to deploy the stack to. */
  env: { account: '123456789012', region: 'us-east-1' }, // ここ

  /* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */
});
```

### 実際にスタックを定義してみる

今回はマルチAZのVPCを作成する。
`lib/cdk-demo-stack.ts`　を以下のように編集

```ts
import * as cdk from "aws-cdk-lib";
import { SubnetType, Vpc } from "aws-cdk-lib/aws-ec2"; // 追加
import { Construct } from "constructs";
// import * as sqs from 'aws-cdk-lib/aws-sqs';

export class CdkDemoStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    
    // 追加ここから
    const vpc = new Vpc(this, "MainVpc", {
      // CHANGE: this is where we define how many AZs to use
      maxAzs: 2,

      // CHANGE: We define a single subnet configuration per AZ.
      subnetConfiguration: [
        {
          // CHANGE: this is it's CIDR mask so 255.255.255.0
          cidrMask: 24,

          // CHANGE: a name for each of these subnets
          name: "public-subnet",

          // CHANGE: and the subnet type to be used - here we will have
          // a public subnet. There are other options available here.
          subnetType: SubnetType.PUBLIC,
        },
      ],
    });
    
    // 追加ここまで
  }
}
```

ちなみになぜか公式チュートリアル通りにやると以下のエラーが発生

```
型 'this' の引数を型 'Construct' のパラメーターに割り当てることはできません。
```

結論以下の手順で解決

1. node_modulesとpackage-lock.jsonを削除
2. npm install

なんかバージョン違いとかで型が合わなかった感じかなと思う

### 実際にデプロイする

以下コマンドでデプロイが走る

```
cdk deploy
```

↓のような感じで環境変数を渡すと環境変数つきでデプロイできる(envファイル読む方法はないのかな・・・)
どうやら調べた感じenvファイルを読むならdotenvとか使うのが良さそうなのでやってみる

なんかいろいろつまづいたのでメモ

↓みたいな感じのエラーになった

```
 ❌ Building assets failed: Error: Building Assets Failed: Error: CdkDemoStack: SSM parameter /cdk-bootstrap/hnb659fds/version not found. Has the environment been bootstrapped? Please run 'cdk bootstrap' (see https://docs.aws.amazon.com/cdk/latest/guide/bootstrapping.html)
```

stack名を指定すると解決するよ的な記事がちらほら

https://dailydevsblog.com/troubleshoot/resolved-cdk-deploy-deletes-the-bootstrap-version-ssm-parameter-135956/
https://stackoverflow.com/questions/68643349/cdk-deploy-not-recognizing-my-bootstrap-and-ssm-parameter

結局↓みたいな感じでアプローチした。
awsのcredentialにregionを追加

`~/.aws/credentials`

```
[default]
aws_access_key_id=
aws_secret_access_key=
region=ap-northeast-1
```

deployコマンド実行時にprofile情報を渡す

```
cdk deploy --profile default
```

これで一応デプロイコマンドが走った。

VPC作りすぎでデプロイには失敗した。
どうやら同一アカウントにつきリージョンごとに5つまでしかVPCはつくれないみたい。

次は↓のようなエラーが出てデプロイに失敗

```
"Value (ap-northeast-1b) for parameter availabilityZone is invalid. Subnets can currently only be created in the following availability zones: ap-northeast-1a, ap-northeast-1c, ap-northeast-1d.
```

どうやら1bは使えないおみたい。
`cdk.context.json`　を編集して以下のようにする。利用可能なリージョンしかここには書かないようにした方がいいのかなと思う。

```json
{
  "availability-zones:account=957017051518:region=ap-northeast-1": [
    "ap-northeast-1a",
    "ap-northeast-1c",
    "ap-northeast-1d"
  ]
}
```

どうやらアカウントごとに利用可能なVPCのAZが決まっているみたいなので↓で確認する

```
aws ec2 describe-availability-zones --region region-name
```

実行結果

```
{
    "AvailabilityZones": [
        {
            "State": "available",
            "OptInStatus": "opt-in-not-required",
            "Messages": [],
            "RegionName": "ap-northeast-1",
            "ZoneName": "ap-northeast-1a",
            "ZoneId": "apne1-az4",
            "GroupName": "ap-northeast-1",
            "NetworkBorderGroup": "ap-northeast-1",
            "ZoneType": "availability-zone"
        },
        {
            "State": "available",
            "OptInStatus": "opt-in-not-required",
            "Messages": [],
            "RegionName": "ap-northeast-1",
            "ZoneName": "ap-northeast-1c",
            "ZoneId": "apne1-az1",
            "GroupName": "ap-northeast-1",
            "NetworkBorderGroup": "ap-northeast-1",
            "ZoneType": "availability-zone"
        },
        {
            "State": "available",
            "OptInStatus": "opt-in-not-required",
            "Messages": [],
            "RegionName": "ap-northeast-1",
            "ZoneName": "ap-northeast-1d",
            "ZoneId": "apne1-az2",
            "GroupName": "ap-northeast-1",
            "NetworkBorderGroup": "ap-northeast-1",
            "ZoneType": "availability-zone"
        }
    ]
}
```

これでa, c, dしか使えないことがわかる。

実際にa, c, dに制限すると無事デプロイ成功。やった。

```
cdk deploy --profile default

✨  Synthesis time: 13.89s

CdkDemoStack: building assets...

[0%] start: Building 26740e2f73367d0de7f47969183fdb0382e45092f633de32edd12dccfbb6caac:957017051518-ap-northeast-1
[100%] success: Built 26740e2f73367d0de7f47969183fdb0382e45092f633de32edd12dccfbb6caac:957017051518-ap-northeast-1

CdkDemoStack: assets built

CdkDemoStack: deploying...
[0%] start: Publishing 26740e2f73367d0de7f47969183fdb0382e45092f633de32edd12dccfbb6caac:957017051518-ap-northeast-1
[100%] success: Published 26740e2f73367d0de7f47969183fdb0382e45092f633de32edd12dccfbb6caac:957017051518-ap-northeast-1
CdkDemoStack: creating CloudFormation changeset...

 ✅  CdkDemoStack

✨  Deployment time: 76.4s

Stack ARN:
arn:aws:cloudformation:ap-northeast-1:957017051518:stack/CdkDemoStack/8fde7270-5268-11ed-ac0f-06cfd0397ec7

✨  Total time: 90.29s
```

AWSコンソールから確認すると↓の通り

![お使いの_VPC___VPC_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/6ba7f14c-dcec-9ac1-c7fb-5b9e6789ebeb.png)

次はこのVPCにEc2でも立ててみよう