2019年も終わるので、今年GAしたAWS CDKでVPCだけでも作ってみませんか

# はじめに
2019年ももう終わり。
今年GAになり、やろうやろうと思ってたAWS CDK...触ってない人もいるんじゃないでしょうか。
かくいう私も同じです。
今年中に何かを作ってみませんか、という事でまずは土台のVPCだけでも作ってみます。

# AWS CDKとは？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9038/0016bca8-b693-80ba-2327-923e1c0de4b5.png)

AWSリソースをプラグラミング言語(TypeScript,Python..)を使用してコード化、デプロイできるツールキットです。
プログラミング言語を使うことで、以下メリットがあります。

* Cloudformation(以下Cfn)テンプレートでは詳細/冗長になってしまう設定を簡潔に表現
* AWSベストプラクティスがライブラリに組み込まれており意識せず利用
* IDEや型補完の開発
* Cfnテンプレートとして出力も可能なので、現在のCfn資産にも互換性/移行もやりやすい
* OSS

# ドキュメント
主要なドキュメントは以下です。ワークショップもおすすめです。

* [AWS公式](https://aws.amazon.com/jp/cdk/)
* [github](https://github.com/aws/aws-cdk)
* [ワークショップ](https://cdkworkshop.com/)
* [リファレンス](https://docs.aws.amazon.com/cdk/api/latest/)

# 準備
プロジェクトを作ります。今回はtypescriptを使用します。

```zsh
$ mkdir cdk-sample
$ cd cdk-sample
$ cdk init sample-app --language=typescript
$ cdk bootstrap
```
typescriptなので、watchもしておきましょう。

```zsh
$ npm run watch
```
## VPCを作成してみる
ではVPCを作成してみます。
まずはVPC作成に必要なライブラリ(aws-ec2)をnpm installします。

```zsh
$ npm i @aws-cdk/aws-ec2
npm WARN aws-cdk@0.1.0 No repository field.
npm WARN aws-cdk@0.1.0 No license field.

+ @aws-cdk/aws-ec2@1.18.0
updated 1 package and audited 1753607 packages in 13.847s

8 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
```
では、いよいよVPCを作成するコードを書きます!!

```ts:lib/cdk-sample-stack.ts
import { Vpc } from '@aws-cdk/aws-ec2'
import cdk = require('@aws-cdk/core')

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

    new Vpc(this, 'ExampleVpc', {
      cidr: '10.0.0.0/16'
    })
  }
}
```
...まさかの短さです。たった10数行。
たったこれだけで何ができるのか?

続いて、 `cdk diff`コマンドを実行します。
このコマンドによって、実際にどのような変更が行われるのかを確認できます。

```
$ cdk diff
Stack CdkSampleStack
Resources
[+] AWS::EC2::VPC ExampleVpc ExampleVpc7799291B
[+] AWS::EC2::Subnet ExampleVpc/PublicSubnet1/Subnet ExampleVpcPublicSubnet1Subnet5BA48677
[+] AWS::EC2::RouteTable ExampleVpc/PublicSubnet1/RouteTable ExampleVpcPublicSubnet1RouteTable40A7F639
[+] AWS::EC2::SubnetRouteTableAssociation ExampleVpc/PublicSubnet1/RouteTableAssociation ExampleVpcPublicSubnet1RouteTableAssociation73CFDFDF
[+] AWS::EC2::Route ExampleVpc/PublicSubnet1/DefaultRoute ExampleVpcPublicSubnet1DefaultRouteE3DAD43E
[+] AWS::EC2::EIP ExampleVpc/PublicSubnet1/EIP ExampleVpcPublicSubnet1EIP813D7C95
[+] AWS::EC2::NatGateway ExampleVpc/PublicSubnet1/NATGateway ExampleVpcPublicSubnet1NATGatewayFA6F9E69
[+] AWS::EC2::Subnet ExampleVpc/PublicSubnet2/Subnet ExampleVpcPublicSubnet2SubnetC086E6EF
[+] AWS::EC2::RouteTable ExampleVpc/PublicSubnet2/RouteTable ExampleVpcPublicSubnet2RouteTable18D05432
[+] AWS::EC2::SubnetRouteTableAssociation ExampleVpc/PublicSubnet2/RouteTableAssociation ExampleVpcPublicSubnet2RouteTableAssociationCD7A7AA9
[+] AWS::EC2::Route ExampleVpc/PublicSubnet2/DefaultRoute ExampleVpcPublicSubnet2DefaultRoute84B48C4F
[+] AWS::EC2::EIP ExampleVpc/PublicSubnet2/EIP ExampleVpcPublicSubnet2EIP2462F4F6
[+] AWS::EC2::NatGateway ExampleVpc/PublicSubnet2/NATGateway ExampleVpcPublicSubnet2NATGateway14995A95
[+] AWS::EC2::Subnet ExampleVpc/PrivateSubnet1/Subnet ExampleVpcPrivateSubnet1SubnetC5A0FCB0
[+] AWS::EC2::RouteTable ExampleVpc/PrivateSubnet1/RouteTable ExampleVpcPrivateSubnet1RouteTable72F260C8
[+] AWS::EC2::SubnetRouteTableAssociation ExampleVpc/PrivateSubnet1/RouteTableAssociation ExampleVpcPrivateSubnet1RouteTableAssociation30834B8E
[+] AWS::EC2::Route ExampleVpc/PrivateSubnet1/DefaultRoute ExampleVpcPrivateSubnet1DefaultRouteECBB3E44
[+] AWS::EC2::Subnet ExampleVpc/PrivateSubnet2/Subnet ExampleVpcPrivateSubnet2Subnet12B13C26
[+] AWS::EC2::RouteTable ExampleVpc/PrivateSubnet2/RouteTable ExampleVpcPrivateSubnet2RouteTable1E86B73B
[+] AWS::EC2::SubnetRouteTableAssociation ExampleVpc/PrivateSubnet2/RouteTableAssociation ExampleVpcPrivateSubnet2RouteTableAssociation0D4C59A2
[+] AWS::EC2::Route ExampleVpc/PrivateSubnet2/DefaultRoute ExampleVpcPrivateSubnet2DefaultRouteD96ED0D8
[+] AWS::EC2::InternetGateway ExampleVpc/IGW ExampleVpcIGW62E759C3
[+] AWS::EC2::VPCGatewayAttachment ExampleVpc/VPCGW ExampleVpcVPCGWE8E4AC13
```
どうも以下を作成してくれるようです。

* VPC: 1つ
* Public/Private Subnet: それぞれ2つ
* Public SubnetそれぞれにNAT Gatewayを計2つ配置

これはまさに、ベストプラクティスな高可用性を保持したVPC構成となってますね。[^1]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9038/c024798e-80d9-b374-a7de-5a3c1a9b5cdb.png)


続いて、`cdk synth`コマンドを実行します。
このコマンドによって実際のCfnテンプレートが出力されます。
結果は長いので省略しますが、約270行程のテンプレートに相当するとわかります。

<details><summary>cdk synth結果</summary><div>

```yml
$ cdk synth
Resources:
  ExampleVpc7799291B:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsHostnames: true
      EnableDnsSupport: true
      InstanceTenancy: default
      Tags:
        - Key: Name
          Value: CdkSampleStack/ExampleVpc
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/Resource
  ExampleVpcPublicSubnet1Subnet5BA48677:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: 10.0.0.0/18
      VpcId:
        Ref: ExampleVpc7799291B
      AvailabilityZone:
        Fn::Select:
          - 0
          - Fn::GetAZs: ""
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: CdkSampleStack/ExampleVpc/PublicSubnet1
        - Key: aws-cdk:subnet-name
          Value: Public
        - Key: aws-cdk:subnet-type
          Value: Public
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/PublicSubnet1/Subnet
  ExampleVpcPublicSubnet1RouteTable40A7F639:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId:
        Ref: ExampleVpc7799291B
      Tags:
        - Key: Name
          Value: CdkSampleStack/ExampleVpc/PublicSubnet1
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/PublicSubnet1/RouteTable
  ExampleVpcPublicSubnet1RouteTableAssociation73CFDFDF:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId:
        Ref: ExampleVpcPublicSubnet1RouteTable40A7F639
      SubnetId:
        Ref: ExampleVpcPublicSubnet1Subnet5BA48677
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/PublicSubnet1/RouteTableAssociation
  ExampleVpcPublicSubnet1DefaultRouteE3DAD43E:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId:
        Ref: ExampleVpcPublicSubnet1RouteTable40A7F639
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId:
        Ref: ExampleVpcIGW62E759C3
    DependsOn:
      - ExampleVpcVPCGWE8E4AC13
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/PublicSubnet1/DefaultRoute
  ExampleVpcPublicSubnet1EIP813D7C95:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/PublicSubnet1/EIP
  ExampleVpcPublicSubnet1NATGatewayFA6F9E69:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId:
        Fn::GetAtt:
          - ExampleVpcPublicSubnet1EIP813D7C95
          - AllocationId
      SubnetId:
        Ref: ExampleVpcPublicSubnet1Subnet5BA48677
      Tags:
        - Key: Name
          Value: CdkSampleStack/ExampleVpc/PublicSubnet1
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/PublicSubnet1/NATGateway
  ExampleVpcPublicSubnet2SubnetC086E6EF:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: 10.0.64.0/18
      VpcId:
        Ref: ExampleVpc7799291B
      AvailabilityZone:
        Fn::Select:
          - 1
          - Fn::GetAZs: ""
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: CdkSampleStack/ExampleVpc/PublicSubnet2
        - Key: aws-cdk:subnet-name
          Value: Public
        - Key: aws-cdk:subnet-type
          Value: Public
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/PublicSubnet2/Subnet
  ExampleVpcPublicSubnet2RouteTable18D05432:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId:
        Ref: ExampleVpc7799291B
      Tags:
        - Key: Name
          Value: CdkSampleStack/ExampleVpc/PublicSubnet2
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/PublicSubnet2/RouteTable
  ExampleVpcPublicSubnet2RouteTableAssociationCD7A7AA9:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId:
        Ref: ExampleVpcPublicSubnet2RouteTable18D05432
      SubnetId:
        Ref: ExampleVpcPublicSubnet2SubnetC086E6EF
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/PublicSubnet2/RouteTableAssociation
  ExampleVpcPublicSubnet2DefaultRoute84B48C4F:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId:
        Ref: ExampleVpcPublicSubnet2RouteTable18D05432
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId:
        Ref: ExampleVpcIGW62E759C3
    DependsOn:
      - ExampleVpcVPCGWE8E4AC13
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/PublicSubnet2/DefaultRoute
  ExampleVpcPublicSubnet2EIP2462F4F6:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/PublicSubnet2/EIP
  ExampleVpcPublicSubnet2NATGateway14995A95:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId:
        Fn::GetAtt:
          - ExampleVpcPublicSubnet2EIP2462F4F6
          - AllocationId
      SubnetId:
        Ref: ExampleVpcPublicSubnet2SubnetC086E6EF
      Tags:
        - Key: Name
          Value: CdkSampleStack/ExampleVpc/PublicSubnet2
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/PublicSubnet2/NATGateway
  ExampleVpcPrivateSubnet1SubnetC5A0FCB0:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: 10.0.128.0/18
      VpcId:
        Ref: ExampleVpc7799291B
      AvailabilityZone:
        Fn::Select:
          - 0
          - Fn::GetAZs: ""
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: CdkSampleStack/ExampleVpc/PrivateSubnet1
        - Key: aws-cdk:subnet-name
          Value: Private
        - Key: aws-cdk:subnet-type
          Value: Private
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/PrivateSubnet1/Subnet
  ExampleVpcPrivateSubnet1RouteTable72F260C8:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId:
        Ref: ExampleVpc7799291B
      Tags:
        - Key: Name
          Value: CdkSampleStack/ExampleVpc/PrivateSubnet1
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/PrivateSubnet1/RouteTable
  ExampleVpcPrivateSubnet1RouteTableAssociation30834B8E:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId:
        Ref: ExampleVpcPrivateSubnet1RouteTable72F260C8
      SubnetId:
        Ref: ExampleVpcPrivateSubnet1SubnetC5A0FCB0
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/PrivateSubnet1/RouteTableAssociation
  ExampleVpcPrivateSubnet1DefaultRouteECBB3E44:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId:
        Ref: ExampleVpcPrivateSubnet1RouteTable72F260C8
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId:
        Ref: ExampleVpcPublicSubnet1NATGatewayFA6F9E69
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/PrivateSubnet1/DefaultRoute
  ExampleVpcPrivateSubnet2Subnet12B13C26:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: 10.0.192.0/18
      VpcId:
        Ref: ExampleVpc7799291B
      AvailabilityZone:
        Fn::Select:
          - 1
          - Fn::GetAZs: ""
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: CdkSampleStack/ExampleVpc/PrivateSubnet2
        - Key: aws-cdk:subnet-name
          Value: Private
        - Key: aws-cdk:subnet-type
          Value: Private
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/PrivateSubnet2/Subnet
  ExampleVpcPrivateSubnet2RouteTable1E86B73B:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId:
        Ref: ExampleVpc7799291B
      Tags:
        - Key: Name
          Value: CdkSampleStack/ExampleVpc/PrivateSubnet2
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/PrivateSubnet2/RouteTable
  ExampleVpcPrivateSubnet2RouteTableAssociation0D4C59A2:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId:
        Ref: ExampleVpcPrivateSubnet2RouteTable1E86B73B
      SubnetId:
        Ref: ExampleVpcPrivateSubnet2Subnet12B13C26
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/PrivateSubnet2/RouteTableAssociation
  ExampleVpcPrivateSubnet2DefaultRouteD96ED0D8:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId:
        Ref: ExampleVpcPrivateSubnet2RouteTable1E86B73B
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId:
        Ref: ExampleVpcPublicSubnet2NATGateway14995A95
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/PrivateSubnet2/DefaultRoute
  ExampleVpcIGW62E759C3:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: CdkSampleStack/ExampleVpc
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/IGW
  ExampleVpcVPCGWE8E4AC13:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId:
        Ref: ExampleVpc7799291B
      InternetGatewayId:
        Ref: ExampleVpcIGW62E759C3
    Metadata:
      aws:cdk:path: CdkSampleStack/ExampleVpc/VPCGW
  CDKMetadata:
    Type: AWS::CDK::Metadata
    Properties:
      Modules: aws-cdk=1.18.0,@aws-cdk/aws-cloudwatch=1.18.0,@aws-cdk/aws-ec2=1.18.0,@aws-cdk/aws-iam=1.18.0,@aws-cdk/aws-ssm=1.18.0,@aws-cdk/core=1.18.0,@aws-cdk/cx-api=1.18.0,@aws-cdk/region-info=1.18.0,jsii-runtime=node.js/v13.2.0
```
</div></details>

では、デプロイしてみましょう。

```zsh
$ cdk deploy
CdkSampleStack: deploying...
CdkSampleStack: creating CloudFormation changeset...
  0/25 | 18:45:38 | CREATE_IN_PROGRESS   | AWS::EC2::EIP                         | ExampleVpc/PublicSubnet2/EIP (ExampleVpcPublicSubnet2EIP2462F4F6)
  0/25 | 18:45:38 | CREATE_IN_PROGRESS   | AWS::EC2::InternetGateway             | ExampleVpc/IGW (ExampleVpcIGW62E759C3)
  0/25 | 18:45:38 | CREATE_IN_PROGRESS   | AWS::CDK::Metadata                    | CDKMetadata
  0/25 | 18:45:38 | CREATE_IN_PROGRESS   | AWS::EC2::VPC                         | ExampleVpc (ExampleVpc7799291B)
  0/25 | 18:45:38 | CREATE_IN_PROGRESS   | AWS::EC2::EIP                         | ExampleVpc/PublicSubnet1/EIP (ExampleVpcPublicSubnet1EIP813D7C95)
  0/25 | 18:45:38 | CREATE_IN_PROGRESS   | AWS::EC2::EIP                         | ExampleVpc/PublicSubnet2/EIP (ExampleVpcPublicSubnet2EIP2462F4F6) Resource creation Initiated
  0/25 | 18:45:38 | CREATE_IN_PROGRESS   | AWS::EC2::InternetGateway             | ExampleVpc/IGW (ExampleVpcIGW62E759C3) Resource creation Initiated
  0/25 | 18:45:39 | CREATE_IN_PROGRESS   | AWS::EC2::VPC                         | ExampleVpc (ExampleVpc7799291B) Resource creation Initiated
  0/25 | 18:45:39 | CREATE_IN_PROGRESS   | AWS::EC2::EIP                         | ExampleVpc/PublicSubnet1/EIP (ExampleVpcPublicSubnet1EIP813D7C95) Resource creation Initiated
  0/25 | 18:45:40 | CREATE_IN_PROGRESS   | AWS::CDK::Metadata                    | CDKMetadata Resource creation Initiated
  1/25 | 18:45:40 | CREATE_COMPLETE      | AWS::CDK::Metadata                    | CDKMetadata
  2/25 | 18:45:54 | CREATE_COMPLETE      | AWS::EC2::EIP                         | ExampleVpc/PublicSubnet2/EIP (ExampleVpcPublicSubnet2EIP2462F4F6)
  3/25 | 18:45:55 | CREATE_COMPLETE      | AWS::EC2::InternetGateway             | ExampleVpc/IGW (ExampleVpcIGW62E759C3)
  4/25 | 18:45:55 | CREATE_COMPLETE      | AWS::EC2::EIP                         | ExampleVpc/PublicSubnet1/EIP (ExampleVpcPublicSubnet1EIP813D7C95)
  5/25 | 18:45:55 | CREATE_COMPLETE      | AWS::EC2::VPC                         | ExampleVpc (ExampleVpc7799291B)
  5/25 | 18:45:57 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | ExampleVpc/PrivateSubnet1/RouteTable (ExampleVpcPrivateSubnet1RouteTable72F260C8)
  5/25 | 18:45:57 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | ExampleVpc/PublicSubnet1/RouteTable (ExampleVpcPublicSubnet1RouteTable40A7F639)
  5/25 | 18:45:58 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | ExampleVpc/PrivateSubnet2/RouteTable (ExampleVpcPrivateSubnet2RouteTable1E86B73B)
  5/25 | 18:45:58 | CREATE_IN_PROGRESS   | AWS::EC2::VPCGatewayAttachment        | ExampleVpc/VPCGW (ExampleVpcVPCGWE8E4AC13)
  5/25 | 18:45:58 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | ExampleVpc/PrivateSubnet1/Subnet (ExampleVpcPrivateSubnet1SubnetC5A0FCB0)
  5/25 | 18:45:58 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | ExampleVpc/PublicSubnet1/Subnet (ExampleVpcPublicSubnet1Subnet5BA48677)
  5/25 | 18:45:58 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | ExampleVpc/PrivateSubnet2/Subnet (ExampleVpcPrivateSubnet2Subnet12B13C26)
  5/25 | 18:45:58 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | ExampleVpc/PublicSubnet2/Subnet (ExampleVpcPublicSubnet2SubnetC086E6EF)
  5/25 | 18:45:58 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | ExampleVpc/PrivateSubnet1/RouteTable (ExampleVpcPrivateSubnet1RouteTable72F260C8) Resource creation Initiated
  5/25 | 18:45:58 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | ExampleVpc/PublicSubnet1/RouteTable (ExampleVpcPublicSubnet1RouteTable40A7F639) Resource creation Initiated
  5/25 | 18:45:58 | CREATE_IN_PROGRESS   | AWS::EC2::VPCGatewayAttachment        | ExampleVpc/VPCGW (ExampleVpcVPCGWE8E4AC13) Resource creation Initiated
  5/25 | 18:45:58 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | ExampleVpc/PrivateSubnet2/RouteTable (ExampleVpcPrivateSubnet2RouteTable1E86B73B) Resource creation Initiated
  5/25 | 18:45:58 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | ExampleVpc/PrivateSubnet2/Subnet (ExampleVpcPrivateSubnet2Subnet12B13C26) Resource creation Initiated
  5/25 | 18:45:58 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | ExampleVpc/PublicSubnet2/Subnet (ExampleVpcPublicSubnet2SubnetC086E6EF) Resource creation Initiated
  5/25 | 18:45:58 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | ExampleVpc/PublicSubnet1/Subnet (ExampleVpcPublicSubnet1Subnet5BA48677) Resource creation Initiated
  5/25 | 18:45:58 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | ExampleVpc/PrivateSubnet1/Subnet (ExampleVpcPrivateSubnet1SubnetC5A0FCB0) Resource creation Initiated
  6/25 | 18:45:59 | CREATE_COMPLETE      | AWS::EC2::RouteTable                  | ExampleVpc/PublicSubnet1/RouteTable (ExampleVpcPublicSubnet1RouteTable40A7F639)
  7/25 | 18:45:59 | CREATE_COMPLETE      | AWS::EC2::RouteTable                  | ExampleVpc/PrivateSubnet1/RouteTable (ExampleVpcPrivateSubnet1RouteTable72F260C8)
  8/25 | 18:45:59 | CREATE_COMPLETE      | AWS::EC2::RouteTable                  | ExampleVpc/PrivateSubnet2/RouteTable (ExampleVpcPrivateSubnet2RouteTable1E86B73B)
  8/25 | 18:46:01 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | ExampleVpc/PublicSubnet2/RouteTable (ExampleVpcPublicSubnet2RouteTable18D05432)
  8/25 | 18:46:02 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | ExampleVpc/PublicSubnet2/RouteTable (ExampleVpcPublicSubnet2RouteTable18D05432) Resource creation Initiated
  9/25 | 18:46:03 | CREATE_COMPLETE      | AWS::EC2::RouteTable                  | ExampleVpc/PublicSubnet2/RouteTable (ExampleVpcPublicSubnet2RouteTable18D05432)
 10/25 | 18:46:13 | CREATE_COMPLETE      | AWS::EC2::VPCGatewayAttachment        | ExampleVpc/VPCGW (ExampleVpcVPCGWE8E4AC13)
 11/25 | 18:46:15 | CREATE_COMPLETE      | AWS::EC2::Subnet                      | ExampleVpc/PublicSubnet2/Subnet (ExampleVpcPublicSubnet2SubnetC086E6EF)
 12/25 | 18:46:15 | CREATE_COMPLETE      | AWS::EC2::Subnet                      | ExampleVpc/PrivateSubnet1/Subnet (ExampleVpcPrivateSubnet1SubnetC5A0FCB0)
 13/25 | 18:46:15 | CREATE_COMPLETE      | AWS::EC2::Subnet                      | ExampleVpc/PrivateSubnet2/Subnet (ExampleVpcPrivateSubnet2Subnet12B13C26)
 14/25 | 18:46:15 | CREATE_COMPLETE      | AWS::EC2::Subnet                      | ExampleVpc/PublicSubnet1/Subnet (ExampleVpcPublicSubnet1Subnet5BA48677)
 14/25 | 18:46:16 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | ExampleVpc/PublicSubnet2/DefaultRoute (ExampleVpcPublicSubnet2DefaultRoute84B48C4F)
 14/25 | 18:46:16 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | ExampleVpc/PublicSubnet1/DefaultRoute (ExampleVpcPublicSubnet1DefaultRouteE3DAD43E)
 14/25 | 18:46:16 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | ExampleVpc/PublicSubnet2/DefaultRoute (ExampleVpcPublicSubnet2DefaultRoute84B48C4F) Resource creation Initiated
 14/25 | 18:46:16 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | ExampleVpc/PublicSubnet1/DefaultRoute (ExampleVpcPublicSubnet1DefaultRouteE3DAD43E) Resource creation Initiated
 14/25 | 18:46:17 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PublicSubnet1/RouteTableAssociation (ExampleVpcPublicSubnet1RouteTableAssociation73CFDFDF)
 14/25 | 18:46:17 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PublicSubnet2/RouteTableAssociation (ExampleVpcPublicSubnet2RouteTableAssociationCD7A7AA9)
 14/25 | 18:46:17 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PrivateSubnet1/RouteTableAssociation (ExampleVpcPrivateSubnet1RouteTableAssociation30834B8E)
 14/25 | 18:46:17 | CREATE_IN_PROGRESS   | AWS::EC2::NatGateway                  | ExampleVpc/PublicSubnet2/NATGateway (ExampleVpcPublicSubnet2NATGateway14995A95)
 14/25 | 18:46:17 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PrivateSubnet2/RouteTableAssociation (ExampleVpcPrivateSubnet2RouteTableAssociation0D4C59A2)
 14/25 | 18:46:17 | CREATE_IN_PROGRESS   | AWS::EC2::NatGateway                  | ExampleVpc/PublicSubnet1/NATGateway (ExampleVpcPublicSubnet1NATGatewayFA6F9E69)
 14/25 | 18:46:17 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PublicSubnet2/RouteTableAssociation (ExampleVpcPublicSubnet2RouteTableAssociationCD7A7AA9) Resource creation Initiated
 14/25 | 18:46:17 | CREATE_IN_PROGRESS   | AWS::EC2::NatGateway                  | ExampleVpc/PublicSubnet2/NATGateway (ExampleVpcPublicSubnet2NATGateway14995A95) Resource creation Initiated
 14/25 | 18:46:17 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PublicSubnet1/RouteTableAssociation (ExampleVpcPublicSubnet1RouteTableAssociation73CFDFDF) Resource creation Initiated
 14/25 | 18:46:18 | CREATE_IN_PROGRESS   | AWS::EC2::NatGateway                  | ExampleVpc/PublicSubnet1/NATGateway (ExampleVpcPublicSubnet1NATGatewayFA6F9E69) Resource creation Initiated
 14/25 | 18:46:18 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PrivateSubnet1/RouteTableAssociation (ExampleVpcPrivateSubnet1RouteTableAssociation30834B8E) Resource creation Initiated
 14/25 | 18:46:18 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PrivateSubnet2/RouteTableAssociation (ExampleVpcPrivateSubnet2RouteTableAssociation0D4C59A2) Resource creation Initiated
 15/25 | 18:46:32 | CREATE_COMPLETE      | AWS::EC2::Route                       | ExampleVpc/PublicSubnet2/DefaultRoute (ExampleVpcPublicSubnet2DefaultRoute84B48C4F)
 16/25 | 18:46:32 | CREATE_COMPLETE      | AWS::EC2::Route                       | ExampleVpc/PublicSubnet1/DefaultRoute (ExampleVpcPublicSubnet1DefaultRouteE3DAD43E)
 17/25 | 18:46:33 | CREATE_COMPLETE      | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PublicSubnet2/RouteTableAssociation (ExampleVpcPublicSubnet2RouteTableAssociationCD7A7AA9)
 18/25 | 18:46:33 | CREATE_COMPLETE      | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PublicSubnet1/RouteTableAssociation (ExampleVpcPublicSubnet1RouteTableAssociation73CFDFDF)
 19/25 | 18:46:33 | CREATE_COMPLETE      | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PrivateSubnet2/RouteTableAssociation (ExampleVpcPrivateSubnet2RouteTableAssociation0D4C59A2)
 20/25 | 18:46:33 | CREATE_COMPLETE      | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PrivateSubnet1/RouteTableAssociation (ExampleVpcPrivateSubnet1RouteTableAssociation30834B8E)
20/25 Currently in progress: ExampleVpcPublicSubnet2NATGateway14995A95, ExampleVpcPublicSubnet1NATGatewayFA6F9E69
 21/25 | 18:47:51 | CREATE_COMPLETE      | AWS::EC2::NatGateway                  | ExampleVpc/PublicSubnet2/NATGateway (ExampleVpcPublicSubnet2NATGateway14995A95)
 21/25 | 18:47:53 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | ExampleVpc/PrivateSubnet2/DefaultRoute (ExampleVpcPrivateSubnet2DefaultRouteD96ED0D8)
 21/25 | 18:47:54 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | ExampleVpc/PrivateSubnet2/DefaultRoute (ExampleVpcPrivateSubnet2DefaultRouteD96ED0D8) Resource creation Initiated
 22/25 | 18:48:09 | CREATE_COMPLETE      | AWS::EC2::Route                       | ExampleVpc/PrivateSubnet2/DefaultRoute (ExampleVpcPrivateSubnet2DefaultRouteD96ED0D8)
 23/25 | 18:48:36 | CREATE_COMPLETE      | AWS::EC2::NatGateway                  | ExampleVpc/PublicSubnet1/NATGateway (ExampleVpcPublicSubnet1NATGatewayFA6F9E69)
 23/25 | 18:48:39 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | ExampleVpc/PrivateSubnet1/DefaultRoute (ExampleVpcPrivateSubnet1DefaultRouteECBB3E44)
 23/25 | 18:48:39 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | ExampleVpc/PrivateSubnet1/DefaultRoute (ExampleVpcPrivateSubnet1DefaultRouteECBB3E44) Resource creation Initiated
 24/25 | 18:48:55 | CREATE_COMPLETE      | AWS::EC2::Route                       | ExampleVpc/PrivateSubnet1/DefaultRoute (ExampleVpcPrivateSubnet1DefaultRouteECBB3E44)
 25/25 | 18:48:57 | CREATE_COMPLETE      | AWS::CloudFormation::Stack            | CdkSampleStack

 ✅  CdkSampleStack

Stack ARN:
arn:aws:cloudformation:ap-northeast-1:123456789:stack/CdkSampleStack/111111-2222-3333-4444-55555555555
```
成功したことでCfnに`CdkSampleStack`が作成され、AWSリソースが作成されました。


## 変更してみる
[VPC ConstructsのProps](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-ec2.Vpc.html#construct-props)を参照すると、いくつか指定できそうです。
NAT Gatewayの数を2から1に減らしてみましょう。

```ts:lib/cdk-sample-stack.ts
    new ec2.Vpc(this, 'ExampleVpc', {
      cidr: '10.0.0.0/16',
      natGateways: 1 // <---- 追加
    })
```
`cdk diff`してみます。

```zsh
$ cdk diff
Stack CdkSampleStack
Resources
[-] AWS::EC2::EIP ExampleVpcPublicSubnet2EIP2462F4F6 destroy
[-] AWS::EC2::NatGateway ExampleVpcPublicSubnet2NATGateway14995A95 destroy
[~] AWS::EC2::Route ExampleVpc/PrivateSubnet2/DefaultRoute ExampleVpcPrivateSubnet2DefaultRouteD96ED0D8
 └─ [~] NatGatewayId
     └─ [~] .Ref:
         ├─ [-] ExampleVpcPublicSubnet2NATGateway14995A95
         └─ [+] ExampleVpcPublicSubnet1NATGatewayFA6F9E69
```

以下を実施してくそうです。よしなに変更してくれてますね!

* Public Subnet2内のEIP/NatGatewayを削除
* Private Subnet2のDefault Routeを、Public Subnet1のNAT Gatewayに向くように変更

deployしてみましょう。

```
$ cdk deploy
CdkSampleStack: deploying...
CdkSampleStack: creating CloudFormation changeset...
 0/4 | 23:57:17 | UPDATE_IN_PROGRESS   | AWS::EC2::Route                       | ExampleVpc/PrivateSubnet2/DefaultRoute (ExampleVpcPrivateSubnet2DefaultRouteD96ED0D8)
 1/4 | 23:57:32 | UPDATE_COMPLETE      | AWS::EC2::Route                       | ExampleVpc/PrivateSubnet2/DefaultRoute (ExampleVpcPrivateSubnet2DefaultRouteD96ED0D8)
 1/4 | 23:57:34 | UPDATE_COMPLETE_CLEA | AWS::CloudFormation::Stack            | CdkSampleStack
 1/4 | 23:57:36 | DELETE_IN_PROGRESS   | AWS::EC2::NatGateway                  | ExampleVpcPublicSubnet2NATGateway14995A95
1/4 Currently in progress: CdkSampleStack, ExampleVpcPublicSubnet2NATGateway14995A95
 2/4 | 23:58:22 | DELETE_COMPLETE      | AWS::EC2::NatGateway                  | ExampleVpcPublicSubnet2NATGateway14995A95
 2/4 | 23:58:23 | DELETE_IN_PROGRESS   | AWS::EC2::EIP                         | ExampleVpcPublicSubnet2EIP2462F4F6
 3/4 | 23:58:24 | DELETE_COMPLETE      | AWS::EC2::EIP                         | ExampleVpcPublicSubnet2EIP2462F4F6
 4/4 | 23:58:24 | UPDATE_COMPLETE      | AWS::CloudFormation::Stack            | CdkSampleStack

 ✅  CdkSampleStack

Stack ARN:
arn:aws:cloudformation:ap-northeast-1:123456789:stack/CdkSampleStack/111111-2222-3333-4444-55555555555
```
成功しました!!

# 最後に
レールに乗れればかなり簡潔かつ、ベストプラクティスにのっとった形でコードができそうです。
もう少し細かい指定もできるとおもうので、引き続き触ってみようと思います!

明日は @G-awa さんです。


[^1]: [blackbelt](https://www.slideshare.net/AmazonWebServicesJapan/20180418-aws-black-belt-online-seminar-amazon-vpc)より引用