AWS Cloud Development Kit (AWS CDK) を使って VPC 環境と EC2 インスタンスを作る

以下のイメージの VPC 環境を aws-cdk を使って作成する。
![aws-sdk-vpc.png](https://qiita-image-store.s3.amazonaws.com/0/81973/5a123ec2-7df6-a72a-4156-8ff39f6c8b4f.png)

## 参照元

[aws/aws-cdk: The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code](https://github.com/aws/aws-cdk)

## 環境

MacOS

```console
$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.14.6
BuildVersion:	18G84
```

[Node.js (>= 8.11.x)](https://nodejs.org/en/download/)

```console
$ node -v
v10.15.3
```

```console
$ npm -v
6.10.2
```

## セットアップ

### 前提条件

AWS CLI のインストールと AWS 認証情報が指定が完了していること。
[AWS Command Line Interface のインストール](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/installing.html)
[AWS CLI の設定](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-getting-started.html)

### aws cdk のインストール

```console

$ sudo npm i -g aws-cdk
Password:
/usr/local/bin/cdk -> /usr/local/lib/node_modules/aws-cdk/bin/cdk

> core-js@2.6.9 postinstall /usr/local/lib/node_modules/aws-cdk/node_modules/core-js
> node scripts/postinstall || echo "ignore"

Thank you for using core-js ( https://github.com/zloirock/core-js ) for polyfilling JavaScript standard library!

The project needs your help! Please consider supporting of core-js on Open Collective or Patreon:
> https://opencollective.com/core-js
> https://www.patreon.com/zloirock

Also, the author of core-js ( https://github.com/zloirock ) is looking for a good job -)

+ aws-cdk@1.2.0
added 237 packages from 242 contributors in 10.302s
```

## AWS CDK app の構築

app とは CloudFormation スタックを作成するためのコード。 `cdk deploy`(下記参照) 実行時に app の内容が CloudFormation テンプレートに変換されて CloudFormation スタックとして作成される。 

### app の新規作成

```console
$ mkdir cdk-sample
$ cd cdk-sample
$ cdk init app --language=typescript
Applying project template app for typescript
Initializing a new git repository...
Executing npm install...
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN cdk-sample@0.1.0 No repository field.
npm WARN cdk-sample@0.1.0 No license field.

# Useful commands

 * `npm run build`   compile typescript to js
 * `npm run watch`   watch for changes and compile
 * `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
```

### 使用するライブラリを追加する

```console
~/cdk-sample# npm i -s @aws-cdk/aws-ec2
+ @aws-cdk/aws-ec2@1.1.0
added 4 packages from 1 contributor and audited 538 packages in 4.327s
found 0 vulnerabilities
```

### 使用するアベイラビリティーゾーンを指定する

別に指定しなくても良いです。

```json
# cdk.context.json
{
  "availability-zones:account=１２３４５６７８９０１２:region=ap-northeast-1": [
    "ap-northeast-1b",
    "ap-northeast-1c"
  ]
}
```

`bin/cdk-sample.ts`(cdk init によって自動生成されるファイル)に `env` プロパティを追加し、`cdk.context.json` の情報を参照できるようにする。
 
```typescript
#!/usr/bin/env node
import 'source-map-support/register'
import cdk = require('@aws-cdk/core')
import { CdkSampleStack } from '../lib/cdk-sample-stack'

const app = new cdk.App()
new CdkSampleStack(app, 'CdkSampleStack', {
  env: {
    account: '１２３４５６７８９０１２',
    region: 'ap-northeast-1'
  }
})
```

### app 配下の AWS リソースをコードで定義する

`lib/cdk-sample-stack.ts` というファイルが自動生成されているので、下記の内容を追記する。

VPC とその配下の EC2 インスタンスを１つ作成している。 `bin/cdk-sample.ts` から参照される。

```typescript
import { Vpc } from '@aws-cdk/aws-ec2'
import cdk = require('@aws-cdk/core')
import ec2 = require('@aws-cdk/aws-ec2')

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

    const vpc = new Vpc(this, 'ExampleVpc', {
      cidr: '10.0.0.0/16'
    })

    new ec2.CfnInstance(this, 'MyInstance', {
      imageId: 'ami-0c3fd0f5d33134a76',
      instanceType: 't2.micro',
      keyName: 'ssh_key_sample',
      subnetId: vpc.publicSubnets[0].subnetId,
      securityGroupIds: [vpc.vpcDefaultSecurityGroup]
    })
  }
}
```

### 作成したコードをコンパイルする

TypeScript から JavaScript にトランスパイルする。

```console
$ npm run build
```

`watch` コマンドを使用するとコードが変更されたと同時にコンパイルが実行される。

```console
$ npm run watch
[18:08:11] Starting compilation in watch mode...

[18:08:15] Found 0 errors. Watching for file changes.
```

### AWS CDK app (CloudFormation スタック) をデプロイする

CloudFormation スタックが作成される。

```console
$ cdk deploy
CdkSampleStack: deploying...
CdkSampleStack: creating CloudFormation changeset...
  0/26 | 09:51:48 | CREATE_IN_PROGRESS   | AWS::CDK::Metadata                    | CDKMetadata 
  0/26 | 09:51:48 | CREATE_IN_PROGRESS   | AWS::EC2::EIP                         | ExampleVpc/PublicSubnet1/EIP (ExampleVpcPublicSubnet1EIP813D7C95) 
  0/26 | 09:51:48 | CREATE_IN_PROGRESS   | AWS::EC2::EIP                         | ExampleVpc/PublicSubnet2/EIP (ExampleVpcPublicSubnet2EIP2462F4F6) 
  0/26 | 09:51:48 | CREATE_IN_PROGRESS   | AWS::EC2::VPC                         | ExampleVpc (ExampleVpc7799291B) 
  0/26 | 09:51:49 | CREATE_IN_PROGRESS   | AWS::EC2::EIP                         | ExampleVpc/PublicSubnet2/EIP (ExampleVpcPublicSubnet2EIP2462F4F6) Resource creation Initiated
  0/26 | 09:51:49 | CREATE_IN_PROGRESS   | AWS::EC2::EIP                         | ExampleVpc/PublicSubnet1/EIP (ExampleVpcPublicSubnet1EIP813D7C95) Resource creation Initiated
  0/26 | 09:51:49 | CREATE_IN_PROGRESS   | AWS::EC2::VPC                         | ExampleVpc (ExampleVpc7799291B) Resource creation Initiated
  0/26 | 09:51:49 | CREATE_IN_PROGRESS   | AWS::EC2::InternetGateway             | ExampleVpc/IGW (ExampleVpcIGW62E759C3) 
  0/26 | 09:51:49 | CREATE_IN_PROGRESS   | AWS::EC2::InternetGateway             | ExampleVpc/IGW (ExampleVpcIGW62E759C3) Resource creation Initiated
  0/26 | 09:51:50 | CREATE_IN_PROGRESS   | AWS::CDK::Metadata                    | CDKMetadata Resource creation Initiated
  1/26 | 09:51:50 | CREATE_COMPLETE      | AWS::CDK::Metadata                    | CDKMetadata 
  2/26 | 09:52:04 | CREATE_COMPLETE      | AWS::EC2::EIP                         | ExampleVpc/PublicSubnet2/EIP (ExampleVpcPublicSubnet2EIP2462F4F6) 
  3/26 | 09:52:04 | CREATE_COMPLETE      | AWS::EC2::EIP                         | ExampleVpc/PublicSubnet1/EIP (ExampleVpcPublicSubnet1EIP813D7C95) 
  4/26 | 09:52:05 | CREATE_COMPLETE      | AWS::EC2::VPC                         | ExampleVpc (ExampleVpc7799291B) 
  5/26 | 09:52:05 | CREATE_COMPLETE      | AWS::EC2::InternetGateway             | ExampleVpc/IGW (ExampleVpcIGW62E759C3) 
  5/26 | 09:52:07 | CREATE_IN_PROGRESS   | AWS::EC2::VPCGatewayAttachment        | ExampleVpc/VPCGW (ExampleVpcVPCGWE8E4AC13) 
  5/26 | 09:52:07 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | ExampleVpc/PublicSubnet2/RouteTable (ExampleVpcPublicSubnet2RouteTable18D05432) 
  5/26 | 09:52:07 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | ExampleVpc/PublicSubnet1/Subnet (ExampleVpcPublicSubnet1Subnet5BA48677) 
  5/26 | 09:52:07 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | ExampleVpc/PrivateSubnet2/Subnet (ExampleVpcPrivateSubnet2Subnet12B13C26) 
  5/26 | 09:52:07 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | ExampleVpc/PublicSubnet1/RouteTable (ExampleVpcPublicSubnet1RouteTable40A7F639) 
  5/26 | 09:52:07 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | ExampleVpc/PrivateSubnet2/RouteTable (ExampleVpcPrivateSubnet2RouteTable1E86B73B) 
  5/26 | 09:52:08 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | ExampleVpc/PrivateSubnet1/Subnet (ExampleVpcPrivateSubnet1SubnetC5A0FCB0) 
  5/26 | 09:52:08 | CREATE_IN_PROGRESS   | AWS::EC2::VPCGatewayAttachment        | ExampleVpc/VPCGW (ExampleVpcVPCGWE8E4AC13) Resource creation Initiated
  5/26 | 09:52:08 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | ExampleVpc/PublicSubnet2/Subnet (ExampleVpcPublicSubnet2SubnetC086E6EF) 
  5/26 | 09:52:08 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | ExampleVpc/PrivateSubnet1/RouteTable (ExampleVpcPrivateSubnet1RouteTable72F260C8) 
  5/26 | 09:52:08 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | ExampleVpc/PublicSubnet2/RouteTable (ExampleVpcPublicSubnet2RouteTable18D05432) Resource creation Initiated
  5/26 | 09:52:08 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | ExampleVpc/PublicSubnet1/RouteTable (ExampleVpcPublicSubnet1RouteTable40A7F639) Resource creation Initiated
  5/26 | 09:52:08 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | ExampleVpc/PrivateSubnet2/RouteTable (ExampleVpcPrivateSubnet2RouteTable1E86B73B) Resource creation Initiated
  5/26 | 09:52:08 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | ExampleVpc/PublicSubnet1/Subnet (ExampleVpcPublicSubnet1Subnet5BA48677) Resource creation Initiated
  5/26 | 09:52:08 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | ExampleVpc/PrivateSubnet2/Subnet (ExampleVpcPrivateSubnet2Subnet12B13C26) Resource creation Initiated
  5/26 | 09:52:08 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | ExampleVpc/PublicSubnet2/Subnet (ExampleVpcPublicSubnet2SubnetC086E6EF) Resource creation Initiated
  5/26 | 09:52:08 | CREATE_IN_PROGRESS   | AWS::EC2::RouteTable                  | ExampleVpc/PrivateSubnet1/RouteTable (ExampleVpcPrivateSubnet1RouteTable72F260C8) Resource creation Initiated
  5/26 | 09:52:08 | CREATE_IN_PROGRESS   | AWS::EC2::Subnet                      | ExampleVpc/PrivateSubnet1/Subnet (ExampleVpcPrivateSubnet1SubnetC5A0FCB0) Resource creation Initiated
  6/26 | 09:52:09 | CREATE_COMPLETE      | AWS::EC2::RouteTable                  | ExampleVpc/PublicSubnet1/RouteTable (ExampleVpcPublicSubnet1RouteTable40A7F639) 
  7/26 | 09:52:09 | CREATE_COMPLETE      | AWS::EC2::RouteTable                  | ExampleVpc/PublicSubnet2/RouteTable (ExampleVpcPublicSubnet2RouteTable18D05432) 
  8/26 | 09:52:09 | CREATE_COMPLETE      | AWS::EC2::RouteTable                  | ExampleVpc/PrivateSubnet2/RouteTable (ExampleVpcPrivateSubnet2RouteTable1E86B73B) 
  9/26 | 09:52:09 | CREATE_COMPLETE      | AWS::EC2::RouteTable                  | ExampleVpc/PrivateSubnet1/RouteTable (ExampleVpcPrivateSubnet1RouteTable72F260C8) 
 10/26 | 09:52:23 | CREATE_COMPLETE      | AWS::EC2::VPCGatewayAttachment        | ExampleVpc/VPCGW (ExampleVpcVPCGWE8E4AC13) 
 11/26 | 09:52:24 | CREATE_COMPLETE      | AWS::EC2::Subnet                      | ExampleVpc/PrivateSubnet2/Subnet (ExampleVpcPrivateSubnet2Subnet12B13C26) 
 12/26 | 09:52:24 | CREATE_COMPLETE      | AWS::EC2::Subnet                      | ExampleVpc/PublicSubnet1/Subnet (ExampleVpcPublicSubnet1Subnet5BA48677) 
 13/26 | 09:52:24 | CREATE_COMPLETE      | AWS::EC2::Subnet                      | ExampleVpc/PublicSubnet2/Subnet (ExampleVpcPublicSubnet2SubnetC086E6EF) 
 14/26 | 09:52:24 | CREATE_COMPLETE      | AWS::EC2::Subnet                      | ExampleVpc/PrivateSubnet1/Subnet (ExampleVpcPrivateSubnet1SubnetC5A0FCB0) 
 14/26 | 09:52:25 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | ExampleVpc/PublicSubnet1/DefaultRoute (ExampleVpcPublicSubnet1DefaultRouteE3DAD43E) 
 14/26 | 09:52:26 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | ExampleVpc/PublicSubnet2/DefaultRoute (ExampleVpcPublicSubnet2DefaultRoute84B48C4F) 
 14/26 | 09:52:26 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PrivateSubnet2/RouteTableAssociation (ExampleVpcPrivateSubnet2RouteTableAssociation0D4C59A2) 
 14/26 | 09:52:26 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | ExampleVpc/PublicSubnet1/DefaultRoute (ExampleVpcPublicSubnet1DefaultRouteE3DAD43E) Resource creation Initiated
 14/26 | 09:52:26 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PublicSubnet2/RouteTableAssociation (ExampleVpcPublicSubnet2RouteTableAssociationCD7A7AA9) 
 14/26 | 09:52:26 | CREATE_IN_PROGRESS   | AWS::EC2::NatGateway                  | ExampleVpc/PublicSubnet1/NATGateway (ExampleVpcPublicSubnet1NATGatewayFA6F9E69) 
 14/26 | 09:52:26 | CREATE_IN_PROGRESS   | AWS::EC2::NatGateway                  | ExampleVpc/PublicSubnet2/NATGateway (ExampleVpcPublicSubnet2NATGateway14995A95) 
 14/26 | 09:52:26 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | ExampleVpc/PublicSubnet2/DefaultRoute (ExampleVpcPublicSubnet2DefaultRoute84B48C4F) Resource creation Initiated
 14/26 | 09:52:26 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PrivateSubnet1/RouteTableAssociation (ExampleVpcPrivateSubnet1RouteTableAssociation30834B8E) 
 14/26 | 09:52:27 | CREATE_IN_PROGRESS   | AWS::EC2::Instance                    | MyInstance 
 14/26 | 09:52:27 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PrivateSubnet2/RouteTableAssociation (ExampleVpcPrivateSubnet2RouteTableAssociation0D4C59A2) Resource creation Initiated
 14/26 | 09:52:27 | CREATE_IN_PROGRESS   | AWS::EC2::NatGateway                  | ExampleVpc/PublicSubnet1/NATGateway (ExampleVpcPublicSubnet1NATGatewayFA6F9E69) Resource creation Initiated
 14/26 | 09:52:27 | CREATE_IN_PROGRESS   | AWS::EC2::NatGateway                  | ExampleVpc/PublicSubnet2/NATGateway (ExampleVpcPublicSubnet2NATGateway14995A95) Resource creation Initiated
 14/26 | 09:52:27 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PublicSubnet1/RouteTableAssociation (ExampleVpcPublicSubnet1RouteTableAssociation73CFDFDF) 
 14/26 | 09:52:27 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PublicSubnet2/RouteTableAssociation (ExampleVpcPublicSubnet2RouteTableAssociationCD7A7AA9) Resource creation Initiated
 14/26 | 09:52:27 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PrivateSubnet1/RouteTableAssociation (ExampleVpcPrivateSubnet1RouteTableAssociation30834B8E) Resource creation Initiated
 14/26 | 09:52:28 | CREATE_IN_PROGRESS   | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PublicSubnet1/RouteTableAssociation (ExampleVpcPublicSubnet1RouteTableAssociation73CFDFDF) Resource creation Initiated
 14/26 | 09:52:28 | CREATE_IN_PROGRESS   | AWS::EC2::Instance                    | MyInstance Resource creation Initiated
 15/26 | 09:52:41 | CREATE_COMPLETE      | AWS::EC2::Route                       | ExampleVpc/PublicSubnet1/DefaultRoute (ExampleVpcPublicSubnet1DefaultRouteE3DAD43E) 
 16/26 | 09:52:42 | CREATE_COMPLETE      | AWS::EC2::Route                       | ExampleVpc/PublicSubnet2/DefaultRoute (ExampleVpcPublicSubnet2DefaultRoute84B48C4F) 
 17/26 | 09:52:42 | CREATE_COMPLETE      | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PrivateSubnet2/RouteTableAssociation (ExampleVpcPrivateSubnet2RouteTableAssociation0D4C59A2) 
 18/26 | 09:52:43 | CREATE_COMPLETE      | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PublicSubnet2/RouteTableAssociation (ExampleVpcPublicSubnet2RouteTableAssociationCD7A7AA9) 
 19/26 | 09:52:43 | CREATE_COMPLETE      | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PrivateSubnet1/RouteTableAssociation (ExampleVpcPrivateSubnet1RouteTableAssociation30834B8E) 
 20/26 | 09:52:43 | CREATE_COMPLETE      | AWS::EC2::SubnetRouteTableAssociation | ExampleVpc/PublicSubnet1/RouteTableAssociation (ExampleVpcPublicSubnet1RouteTableAssociation73CFDFDF) 
 21/26 | 09:53:00 | CREATE_COMPLETE      | AWS::EC2::Instance                    | MyInstance 
21/26 Currently in progress: ExampleVpcPublicSubnet1NATGatewayFA6F9E69, ExampleVpcPublicSubnet2NATGateway14995A95
 22/26 | 09:54:15 | CREATE_COMPLETE      | AWS::EC2::NatGateway                  | ExampleVpc/PublicSubnet2/NATGateway (ExampleVpcPublicSubnet2NATGateway14995A95) 
 23/26 | 09:54:15 | CREATE_COMPLETE      | AWS::EC2::NatGateway                  | ExampleVpc/PublicSubnet1/NATGateway (ExampleVpcPublicSubnet1NATGatewayFA6F9E69) 
 23/26 | 09:54:17 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | ExampleVpc/PrivateSubnet2/DefaultRoute (ExampleVpcPrivateSubnet2DefaultRouteD96ED0D8) 
 23/26 | 09:54:18 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | ExampleVpc/PrivateSubnet1/DefaultRoute (ExampleVpcPrivateSubnet1DefaultRouteECBB3E44) 
 23/26 | 09:54:18 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | ExampleVpc/PrivateSubnet2/DefaultRoute (ExampleVpcPrivateSubnet2DefaultRouteD96ED0D8) Resource creation Initiated
 23/26 | 09:54:18 | CREATE_IN_PROGRESS   | AWS::EC2::Route                       | ExampleVpc/PrivateSubnet1/DefaultRoute (ExampleVpcPrivateSubnet1DefaultRouteECBB3E44) Resource creation Initiated
 24/26 | 09:54:33 | CREATE_COMPLETE      | AWS::EC2::Route                       | ExampleVpc/PrivateSubnet2/DefaultRoute (ExampleVpcPrivateSubnet2DefaultRouteD96ED0D8) 
 25/26 | 09:54:34 | CREATE_COMPLETE      | AWS::EC2::Route                       | ExampleVpc/PrivateSubnet1/DefaultRoute (ExampleVpcPrivateSubnet1DefaultRouteECBB3E44) 
 26/26 | 09:54:36 | CREATE_COMPLETE      | AWS::CloudFormation::Stack            | CdkSampleStack 

 ✅  CdkSampleStack

Stack ARN:
arn:aws:cloudformation:ap-northeast-1:123456789012:stack/CdkSampleStack/07781bf0-b19b-11e9-af40-0e7d1a719a58

```

完成！