AWS CLI復習◆Cloud9用VPCの構築

JAWS-UG CLI専門支部でのハンズオンを参考に、AWS CLIの復習として投稿します。
[JAWS-UG CLI専門支部とは？](http://jawsug-cli.s3-website-ap-northeast-1.amazonaws.com/)

# VPCを作ろう

## 1.今回の目的
VPCをCLIで作成していくのですが、今回は**「Cloud9環境用のVPC」**を作っていきたいと思います。
Cloud9環境全体イメージを以下としますと、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/626f3294-e2f3-a3ff-cf41-3318ddf2017c.png)

緑のVPCの部分、ネットワーク周りをCloudShellからCLIで作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/35a5c848-87ff-2567-b741-6635f049344c.png)

私のアカウントには現在、タグなしデフォルトVPCと、JAWS-UG CLI専門支部用のハンズオンVPCがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/4c627993-f092-126c-2c4e-321d912ef240.png)

## 2.前提条件
以下アクセス権のあるユーザで実施してください。

- AWSCloudShellFullAccess
- AmazonVPCFullAccess

また、VPCは各リージョン5つまでというソフトクォータがありますので、既存のVPCが既に5つある場合は1つ以上VPCを削除するか、VPCを作成していない別リージョンに読み替えて実施してください。

## 3.Cloud9用VPCの構築
JAWS-UG CLI専門支部　以下手順を参考にします。
[事前作業1.1. VPCの構築 (CloudShell: handson-cloud9-vpc)](http://prototype-handson-cli.s3-website-ap-northeast-1.amazonaws.com/handson_light-aws_service/handson_light-aws_service-cloud9-environment-cloudshell/ec2-vpc-create-expand-cloudshell.html)

まずはVPCの枠の部分だけ作っていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/ba0cd085-215b-1190-29a7-5dbf42dbfe0f.png)

AWSマネジメントコンソールのCloudShellアイコンをクリックしてCloudShellを開いていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/a06e0dc3-fe76-49d4-f639-0cf048c8fea5.png)

ようこそ的な画面は「Close」で閉じます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/51510ba7-544b-462e-f2f2-c011efdb31d4.png)

10秒くらい待ちます。
CloudShellが立ち上がってきたら、コマンドを打ち込んでいきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/1b08eb10-0a09-b433-13a6-3377cc4070df.png)

### リージョン確認
右上のリージョンメニューから"東京 "を選択しておきます。
（読み替えられる方は別のリージョンでも構いません）

### VPCのタグ名
`EC2_VPC_TAG_NAME`という変数に、VPCのタグ名を指定します。私はコーヒーが好きなので`cloud9-coffee-vpc`とタグ名を付けましょう。

```bash
EC2_VPC_TAG_NAME='cloud9-coffee-vpc'
```

### VPCのアドレスレンジ設定
`EC2_VPC_CIDR`という変数に、VPCのアドレスレンジを指定します。

[プライベートIPアドレスってなんだ？という方はこちらへ(@ITのサイトにとびます)](https://atmarkit.itmedia.co.jp/aig/06network/privateip.html#:~:text=%E7%AF%84%E5%9B%B2%E3%81%AF%E3%82%AF%E3%83%A9%E3%82%B9A%E3%81%8B%E3%82%89,.0.0%2F16%EF%BC%89%E3%81%A8%E3%81%AA%E3%82%8B)

プライベートアドレスの範囲は以下のように決まっています。

- クラスA：10.0.0.0～10.255.255.255 （10.0.0.0/8）
- クラスB：172.16.0.0～172.31.255.255 （172.16.0.0/12）
- クラスC：192.168.0.0～192.168.255.255 （192.168.0.0/16）

この範囲の中から好きなIPアドレスを割り当てればいいのですが、今回はCloud9環境を個人の練習用にたてたいだけなので、深く考えなくてもよいです。
「お仕事で今後IPアドレスがたくさん必要！」とか、「ほかのVPCとかぶらないようにしないといけない！」というときはよく考えてあげてください。
ハンズオンではクラスAとかクラスCとか使いがちな気がするので、今回はクラスBのIPアドレス範囲を指定してみましょう。
`172.16.0.0～172.16.255.255(172.16.0.0/16)`を設定します。

```bash
EC2_VPC_CIDR='172.16.0.0/16'
```
ヒアドキュメントで、変数に値が正しく入っているか確認します。

```bash
cat << END

  # 0. AWS_REGION:"ap-northeast-1"
       AWS_REGION="${AWS_REGION}"
  # 1. EC2_VPC_TAG_NAME:"cloud9-coffee-vpc"
       EC2_VPC_TAG_NAME="${EC2_VPC_TAG_NAME}"
  # 2. EC2_VPC_CIDR:"172.16.0.0/16"
       EC2_VPC_CIDR="${EC2_VPC_CIDR}"

END
```

出力例

```bash
  # 0. AWS_REGION:"ap-northeast-1"
       AWS_REGION="ap-northeast-1"
  # 1. EC2_VPC_TAG_NAME:"cloud9-coffee-vpc"
       EC2_VPC_TAG_NAME="cloud9-coffee-vpc"
  # 2. EC2_VPC_CIDR:"172.16.0.0/16"
       EC2_VPC_CIDR="172.16.0.0/16"
```

上下の文字列が同じであれば、変数に正しい値が格納されています。
[(ちょっと脱線)ヒアドキュメントとはなんぞや](https://qiita.com/emiki/items/b2526b9780e4d50ae7c4#%E3%81%A1%E3%82%87%E3%81%A3%E3%81%A8%E8%84%B1%E7%B7%9A%E3%83%92%E3%82%A2%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88%E3%81%A8%E3%81%AF%E3%81%AA%E3%82%93%E3%81%9E%E3%82%84)

`AWS_REGION`という変数は、環境変数です。最初に選択したリージョン名が自動的に格納されています。
[参考(IT用語辞典 e-words様)環境変数 【environment variables】](https://e-words.jp/w/%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0.html)

### VPCのタグ文字列設定
`EC2_VPC_TAG_NAME`という変数でVPCのタグ名を指定しましたが、次は`STRING_EC2_VPC_TAG`という変数にタグ文字列を格納します。
リソースタイプ=vpcと指定します。
また、タグの要素は**「key」**と**「value」**です。`key`に`Name`、`value`に`cloud9-coffee-vpc`を格納します。

```bash
STRING_EC2_VPC_TAG="ResourceType=vpc,Tags=[{Key=Name,Value=${EC2_VPC_TAG_NAME}}]" \
  && echo ${STRING_EC2_VPC_TAG}
```

出力例

```bash
ResourceType=vpc,Tags=[{Key=Name,Value=cloud9-coffee-vpc}]
```

ヒアドキュメントで、変数に値が正しく入っているか確認します。

```bash
cat << END

  # STRING_EC2_VPC_TAG:"ResourceType=vpc,Tags=[{Key=Name,Value=cloud9-coffee-vpc}]"
    STRING_EC2_VPC_TAG="${STRING_EC2_VPC_TAG}"

END
```

出力例

```bash

  # STRING_EC2_VPC_TAG:"ResourceType=vpc,Tags=[{Key=Name,Value=cloud9-coffee-vpc}]"
    STRING_EC2_VPC_TAG="ResourceType=vpc,Tags=[{Key=Name,Value=cloud9-coffee-vpc}]"

```

上下の文字列が同じであれば、変数に正しい値が格納されています。

### VPC作成
VPCを作成します。

```bash
aws ec2 create-vpc \
  --cidr-block ${EC2_VPC_CIDR} \
  --tag-specifications ${STRING_EC2_VPC_TAG}
```

出力例

```bash
{
    "Vpc": {
        "VpcId": "vpc-xxxxxxxxxxxxxxxxx",
        "InstanceTenancy": "default",
        "Tags": [
            "Value": "cloud9-coffee-vpc",
            "Key": "Name"
        ],
        "CidrBlockAssociationSet": [
            {
                "AssociationId": "vpc-cidr-assoc-xxxxxxxx",
                "CidrBlock": "172.16.0.0/16",
                "CidrBlockState": {
                    "State": "associated"
                }
            }
        ],
        "Ipv6CidrBlockAssociationSet": [],
        "State": "pending",
        "DhcpOptionsId": "dopt-xxxxxxxx",
        "CidrBlock": "vpc-xxxxxxxxxxxxxxxxx",
        "OwnerId": "XXXXXXXXXXXX",
        "IsDefault": false
    }
}
```

- `aws ec2 create-vpc` 
  - VPCを作成する

- `--cidr-block`
  - VPCのIPアドレス範囲（CIDRブロック）を指定する

- `--tag-specifications`
  - VPCにタグ付けする

##### (ちょっと脱線)VPCを操作するのにCLIコマンドが「aws ec2」？
マネジメントコンソール上のサービスとしては「VPC」と独立していますが、APIとしてはVPCは「EC2」のAPIの中に含まれています。公式リファレンス検索の際には気を付けてください。

|マネジメントコンソール|CLI(API)|
|:--:|:--:|
|VPC|EC2|
|EC2|EC2|

AWS創設（？）当時はVPCというサービスがなく、EC2だけがポンと立てられるようになっていた時代があったそうです（今でいうクラシックEC2というもの、らしい）。EC2サービスがその後拡張してネットワーキングの設定も細かくできるようになって、VPCというサービスに発展したらしく、そのような歴史があってVPCのAPIはEC2のAPIに含まれてしまっているようです。

（脱線ここまで）
***
### VPCが作成できているか確認
では、"cloud9-coffee-vpc"なんてタグ名がついたVPCができているかを確認します。

```bash
aws ec2 describe-vpcs \
  --filters Name=tag:Name,Values=${EC2_VPC_TAG_NAME}  \
  --query 'Vpcs[].Tags[?Key == `Name`].Value' \
  --output text
```

出力例

```bash
cloud9-coffee-vpc
```

- `aws ec2 describe-vpcs`
  - VPCの詳細を出力する
- `--filters`
  - より具体的なリストを返すためのフィルター名と値のペア。フィルタを使用して、タグ、属性、IDなどの特定の基準によってリソースをフィルタする。
  - `Name=tag:Name`：フィルタの名前（今回はタグの`key`が`Name`）
  - `Values=${EC2_VPC_TAG_NAME}`：フィルタの値（今回はタグの`value`が`cloud9-coffee-vpc`）
- ```--query 'Vpcs[].Tags[?Key == `Name`].Value'```
  - 応答データのフィルタリングに使用するJMESPathクエリ。今回は、VPCの中で、`key`が`Name`なものの中で`value`項目だけ出力させる
- `--output text`
  - 出力のフォーマットをテキスト文書に指定

filterとqueryの使い分けはまた別にまとめたいと思っているのですが、大まかに以下のような使い分けになるようです。

- フィルター：出力結果の絞り込み（--filters）
- クエリー：出力項目の絞り込み（--query）

[参考(Developer IO様)AWS CLIのフィルターとクエリーの使い方についてまとめてみた](https://dev.classmethod.jp/articles/aws-cli-filter-and-query-howto/)




次に、VPC"cloud9-coffee-vpc"のCIDRが"172.16.0.0/16"であることを確認します。

```bash
aws ec2 describe-vpcs \
  --filters Name=tag:Name,Values=${EC2_VPC_TAG_NAME} \
  --query "Vpcs[].CidrBlock" \
  --output text
```

出力例

```bash
172.16.0.0/16
```

- `--query "Vpcs[].CidrBlock"`
 - VPCの中の`CidrBlock`という項目を表示させる


ここでCloudShellのセッションはいったん切断します。
以後の操作で変数汚染を防ぐため、`Ctr+D`で接続を切断します。
再度CloudShellから操作する際は`Enter`でCloudShellに再接続します。

マネジメントコンソール上でも、新しく「cloud9-coffee-vpc」というタグのついたVPCが作成されているのが確認できます。
※表示されない場合は少し待ってからブラウザをリロードするか、選択しているリージョンが"東京"であることを確認してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/0da12a77-5ab3-c85d-5174-e601b94e6c31.png)



## 4.Cloud9用VPCにアタッチするインターネットゲートウェイの作成
JAWS-UG CLI専門支部　以下手順を参考にします。
[事前作業1.2. インターネットゲートウェイの作成 (CloudShell: handson-cloud9-internet-gateway)](http://prototype-handson-cli.s3-website-ap-northeast-1.amazonaws.com/handson_light-aws_service/handson_light-aws_service-cloud9-environment-cloudshell/ec2-internet_gateway-create-expand-cloudshell.html)

インターネットゲートウェイを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/b58969e3-2201-d267-b3a8-202bb4cf8a9d.png)

### リージョン確認
右上のリージョンメニューから"東京"を選択しておきます。
VPC作成時に東京以外のリージョンを選択した方は、作成したVPCと同じリージョンにしておいてください。

### インターネットゲートウェイのタグ名

`EC2_INTERNET_GATEWAY_TAG_NAME`という変数に、インターネットゲートウェイのタグ名を格納します。
私はコーヒーが好きなので`cloud9-coffee-internet-gateway`とタグ名を付けましょう。

```bash
EC2_INTERNET_GATEWAY_TAG_NAME='cloud9-coffee-internet-gateway'
```

ヒアドキュメントで、変数に値が正しく入っているか確認します。

```bash
cat << END

  # 0. AWS_REGION:"ap-northeast-1"
       AWS_REGION="${AWS_REGION}"

  # 1. EC2_INTERNET_GATEWAY_TAG_NAME:"cloud9-coffee-internet-gateway"
       EC2_INTERNET_GATEWAY_TAG_NAME="${EC2_INTERNET_GATEWAY_TAG_NAME}"

END
```

出力例

```bash
  # 0. AWS_REGION:"ap-northeast-1"
       AWS_REGION="ap-northeast-1"

  # 1. EC2_INTERNET_GATEWAY_TAG_NAME:"cloud9-coffee-internet-gateway"
       EC2_INTERNET_GATEWAY_TAG_NAME="cloud9-coffee-internet-gateway"
```

上下の文字列が同じであれば、変数に正しい値が格納されています。
繰り返しますが`AWS_REGION`という変数は、環境変数です。

### インターネットゲートウェイのタグ文字列設定
次は`STRING_EC2_INTERNET_GATEWAY_TAG`という変数にインターネットゲートウェイのタグ文字列を格納します。
リソースタイプ=internet-gatewayと指定します。
また、タグは`key`に`Name`、`value`に`cloud9-coffee-internet-gateway`を格納します。

```bash
STRING_EC2_INTERNET_GATEWAY_TAG="ResourceType=internet-gateway,Tags=[{Key=Name,Value=${EC2_INTERNET_GATEWAY_TAG_NAME}}]" \
  && echo ${STRING_EC2_INTERNET_GATEWAY_TAG}
```

出力例

```bash
ResourceType=internet-gateway,Tags=[{Key=Name,Value=cloud9-coffee-internet-gateway}]
```

ヒアドキュメントで、変数に値が正しく入っているか確認します。

```bash
cat << END

  # STRING_EC2_INTERNET_GATEWAY_TAG:"ResourceType=internet-gateway,Tags=[{Key=Name,Value=cloud9-coffee-internet-gateway}]"
    STRING_EC2_INTERNET_GATEWAY_TAG="${STRING_EC2_INTERNET_GATEWAY_TAG}"

END
```

出力例

```bash
  # STRING_EC2_INTERNET_GATEWAY_TAG:"ResourceType=internet-gateway,Tags=[{Key=Name,Value=cloud9-coffee-internet-gateway}]"
    STRING_EC2_INTERNET_GATEWAY_TAG="ResourceType=internet-gateway,Tags=[{Key=Name,Value=cloud9-coffee-internet-gateway}]"
```

### インターネットゲートウェイの作成
それではインターネットゲートウェイを作成します。

```bash
aws ec2 create-internet-gateway \
  --tag-specifications ${STRING_EC2_INTERNET_GATEWAY_TAG}
```

出力例


```bash
{
  "InternetGateway": {
    "Attachments": []
    "InternetGatewayId": "igw-xxxxxxxxxxxxxxxxx",
    "OwnerId": "XXXXXXXXXXXX",
    "Tags": [
        {
            "Key": "Name",
            "Value": "cloud9-coffee-internet-gateway"
        }
  }
}
```
- `aws ec2 create-internet-gateway`
  - インターネットゲートウェイを作成する
- `--tag-specifications`
  - タグ名を指定する


### インターネットゲートウェイが作成できているか確認
では、"cloud9-coffee-internet-gateway"なんてタグ名がついたインターネットゲートウェイができているかを確認します。

```bash
aws ec2 describe-internet-gateways \
  --filters Name=tag:Name,Values=${EC2_INTERNET_GATEWAY_TAG_NAME}  \
  --query "InternetGateways[].Tags[].Value" \
  --output text
```

出力例

```bash
cloud9-coffee-internet-gateway
```

ここでCloudShellのセッションはいったん切断します。
以後の操作で変数汚染を防ぐため、`Ctr+D`で接続を切断します。
再度CloudShellから操作する際は`Enter`でCloudShellに再接続します。

マネジメントコンソール上でも、新しく「cloud9-coffee-internet-gateway」というタグのついたインターネットゲートウェイが作成されているのが確認できます。
※表示されない場合は少し待ってからブラウザをリロードするか、選択しているリージョンが"東京"であることを確認してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/c0b6fcc4-b81b-bae3-2d92-bc93e6ab95a6.png)



## 5.Cloud9用VPCにインターネットゲートウェイをアタッチする
JAWS-UG CLI専門支部　以下手順を参考にします。
[事前作業1.3. インターネットゲートウェイのアタッチ (CloudShell: handson-cloud9-vpc : handson-cloud9-internet-gateway)](http://prototype-handson-cli.s3-website-ap-northeast-1.amazonaws.com/handson_light-aws_service/handson_light-aws_service-cloud9-environment-cloudshell/ec2-internet_gateway-update-expand-attach-cloudshell.html)

インターネットゲートウェイをVPCにアタッチしていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/ddeb8ed5-0d73-7d70-911e-3915c6b189f5.png)

### リージョン確認
右上のリージョンメニューから"東京"を選択しておきます。
VPC作成時に東京以外のリージョンを選択した方は、作成したVPCと同じリージョンにしておいてください。

### VPCとインターネットゲートウェイのタグ名
インターネットゲートウェイをVPCにアタッチするために、各タグ名を変数に格納しておきます。
VPCタグ名として、`EC2_VPC_TAG_NAME`には`cloud9-coffee-vpc`を格納します。
インターネットゲートウェイタグ名として、`EC2_INTERNET_GATEWAY_TAG_NAME`には`cloud9-coffee-internet-gateway`を格納します。

```bash
EC2_VPC_TAG_NAME='cloud9-coffee-vpc'
EC2_INTERNET_GATEWAY_TAG_NAME='cloud9-coffee-internet-gateway'
```

ヒアドキュメントで、変数に値が正しく入っているか確認します。

```bash
cat << END

  # 0. AWS_REGION:"ap-northeast-1"
       AWS_REGION="${AWS_REGION}"
  # 1. EC2_VPC_TAG_NAME:"cloud9-coffee-vpc"
       EC2_VPC_TAG_NAME="${EC2_VPC_TAG_NAME}"
  # 2. EC2_INTERNET_GATEWAY_TAG_NAME:"cloud9-coffee-internet-gateway"
       EC2_INTERNET_GATEWAY_TAG_NAME="${EC2_INTERNET_GATEWAY_TAG_NAME}"

END
```

出力例

```bash
  # 0. AWS_REGION:"ap-northeast-1"
       AWS_REGION="ap-northeast-1"
  # 1. EC2_VPC_TAG_NAME:"cloud9-coffee-vpc"
       EC2_VPC_TAG_NAME="cloud9-coffee-vpc"
  # 2. EC2_INTERNET_GATEWAY_TAG_NAME:"cloud9-coffee-internet-gateway"
       EC2_INTERNET_GATEWAY_TAG_NAME="cloud9-coffee-internet-gateway"
```

上下の文字列が同じであれば、変数に正しい値が格納されています。
`AWS_REGION`という変数は、環境変数です。


### VPCとインターネットゲートウェイのID取得
インターネットゲートウェイをVPCにアタッチするために、該当のVPCとインターネットゲートウェイのIDが必要になります。そのIDを抽出して変数に格納していきます。

まずVPC IDを取得します。
`EC2_VPC_ID`という変数に、抽出したVPC IDを格納します。

```bash
EC2_VPC_ID=$( \
  aws ec2 describe-vpcs \
    --filters Name=tag:Name,Values=${EC2_VPC_TAG_NAME}  \
    --query 'Vpcs[].VpcId' \
    --output text \
) \
  && echo ${EC2_VPC_ID}
```

出力例

```bash
vpc-xxxxxxxxxxxxxxxxx
```

- `--query 'Vpcs[].VpcId'`
  - VPCの中で`VpcId`という項目を表示する
 
VPC IDは実施する環境によって違いますので、`vpc-xxxxxxxxxxxxxxxxx`としています。
CloudShell上ではIDの数字が表示されているはずです。

次にインターネットゲートウェイIDを取得します。
`EC2_INTERNET_GATEWAY_ID`という変数に、抽出したインターネットゲートウェイIDを格納します。

```bash
EC2_INTERNET_GATEWAY_ID=$( \
  aws ec2 describe-internet-gateways \
    --filters Name=tag:Name,Values=${EC2_INTERNET_GATEWAY_TAG_NAME} \
    --query "InternetGateways[].InternetGatewayId" \
    --output text \
) \
  && echo ${EC2_INTERNET_GATEWAY_ID}
```

出力例

```bash
igw-xxxxxxxxxxxxxxxxx
```

- `--query "InternetGateways[].InternetGatewayId"`
  - インターネットゲートウェイの中で`InternetGatewayId`という項目を表示する

インターネットゲートウェイIDは実施する環境によって違いますので、`igw-xxxxxxxxxxxxxxxxx`としています。
CloudShell上ではIDの数字が表示されているはずです。

ヒアドキュメントで、変数に値が正しく入っているか確認します。

```bash
cat << END

  # EC2_VPC_ID:"vpc-xxxxxxxxxxxxxxxxx"
    EC2_VPC_ID="${EC2_VPC_ID}"
  # EC2_INTERNET_GATEWAY_ID:"igw-xxxxxxxxxxxxxxxxx"
    EC2_INTERNET_GATEWAY_ID="${EC2_INTERNET_GATEWAY_ID}"

END
```

出力例

```bash
  # EC2_VPC_ID:"vpc-xxxxxxxxxxxxxxxxx"
    EC2_VPC_ID="vpc-xxxxxxxxxxxxxxxxx"
  # EC2_INTERNET_GATEWAY_ID:"igw-xxxxxxxxxxxxxxxxx"
    EC2_INTERNET_GATEWAY_ID="igw-xxxxxxxxxxxxxxxxx"
```


### インターネットゲートウェイをVPCにアタッチする
インターネットゲートウェイをVPCにアタッチしていきます。

```bash
aws ec2 attach-internet-gateway \
  --vpc-id ${EC2_VPC_ID} \
  --internet-gateway-id ${EC2_INTERNET_GATEWAY_ID}
```

(出力なし)

- `aws ec2 attach-internet-gateway`
  - インターネットゲートウェイをアタッチするコマンド
- `--vpc-id`
  - インターネットゲートウェイをアタッチするVPC IDを指定
- `--internet-gateway-id`
  - アタッチするインターネットゲートウェイIDを指定


### インターネットゲートウェイがVPCにアタッチされているか確認
VPC`cloud9-coffee-vpc`にインターネットゲートウェイ`cloud9-coffee-internet-gateway`がアタッチされていることを確認します。

```bash
aws ec2 describe-internet-gateways \
  --filters Name=tag:Name,Values=${EC2_INTERNET_GATEWAY_TAG_NAME}  \
  --query "InternetGateways[].Attachments[?VpcId == \`${EC2_VPC_ID}\`].VpcId" \
  --output text
```

出力例

```bash
vpc-xxxxxxxxxxxxxxxxx
```

- `aws ec2 describe-internet-gateways`
  - インターネットゲートウェイの詳細を表示する
- `--filters Name=tag:Name,Values=${EC2_INTERNET_GATEWAY_TAG_NAME}`
  - 表示したい`key`が`Name`、`value`が`cloud9-coffee-internet-gateway`であるインターネットゲートウェイを検索する
- ```--query "InternetGateways[].Attachments[?VpcId == \`${EC2_VPC_ID}\`].VpcId"```
  - アタッチされているインターネットゲートウェイの中で`VpcId`が`cloud9-coffee-vpc`であるもののVPC IDを表示させる


ここでCloudShellのセッションはいったん切断します。
以後の操作で変数汚染を防ぐため、`Ctr+D`で接続を切断します。
再度CloudShellから操作する際は`Enter`でCloudShellに再接続します。

マネジメントコンソール上でも、「cloud9-coffee-internet-gateway」というタグのついたインターネットゲートウェイが「cloud9-coffee-vpc」というタグのついたVPCにアタッチされているのが確認できます。
※表示されない場合は少し待ってからブラウザをリロードするか、選択しているリージョンが"東京"であることを確認してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/94f3d37e-3796-9a41-361d-f36e969cfe8a.png)


## 6.Cloud9用VPC内のサブネットに紐づけるルートテーブルを作成する
JAWS-UG CLI専門支部　以下手順を参考にします。
[事前作業1.4. ルートテーブルの作成 (CloudShell: handson-cloud9-route-table)](http://prototype-handson-cli.s3-website-ap-northeast-1.amazonaws.com/handson_light-aws_service/handson_light-aws_service-cloud9-environment-cloudshell/ec2-route_table-create-expand-cloudshell.html)

ルートテーブルは後ほど中にルーティング情報を設定してサブネットに紐づけます。
まずは空っぽのルートテーブルの枠だけ作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/815ea0ae-9388-63a2-9859-ec855b78cd15.png)


### リージョン確認
右上のリージョンメニューから"東京"を選択しておきます。
VPC作成時に東京以外のリージョンを選択した方は、作成したVPCと同じリージョンにしておいてください。

### VPCのタグ名
ルートテーブルを作成する際、ルートテーブルが紐づくサブネットが含まれる（サブネットはこの後作成するのですが）VPCのIDが必要になります。VPC IDを抽出するのにVPCのタグ名が必要になるため、変数にVPCのタグ名を格納しておきます。

```bash
EC2_VPC_TAG_NAME='cloud9-coffee-vpc'
```

### ルートテーブルのタグ名
`EC2_ROUTE_TABLE_TAG_NAME`という変数に、ルートテーブルのタグ名を指定します。私はコーヒーが好きなので`cloud9-coffee-route-table`とタグ名を付けましょう。

```bash
EC2_ROUTE_TABLE_TAG_NAME='cloud9-coffee-route-table'
```

ヒアドキュメントで、変数に値が正しく入っているか確認します。

```bash
cat << END

  # 0. AWS_REGION:"ap-northeast-1"
       AWS_REGION="${AWS_REGION}"
  # 1. EC2_VPC_TAG_NAME:"cloud9-coffee-vpc"
       EC2_VPC_TAG_NAME="${EC2_VPC_TAG_NAME}"
  # 2. EC2_ROUTE_TABLE_TAG_NAME:"cloud9-coffee-route-table"
       EC2_ROUTE_TABLE_TAG_NAME="${EC2_ROUTE_TABLE_TAG_NAME}"

END
```

出力例

```bash
  # 0. AWS_REGION:"ap-northeast-1"
       AWS_REGION="ap-northeast-1"
  # 1. EC2_VPC_TAG_NAME:"cloud9-coffee-vpc"
       EC2_VPC_TAG_NAME="cloud9-coffee-vpc"
  # 2. EC2_ROUTE_TABLE_TAG_NAME:"cloud9-coffee-route-table"
       EC2_ROUTE_TABLE_TAG_NAME="cloud9-coffee-route-table"
```

上下の文字列が同じであれば、変数に正しい値が格納されています。
`AWS_REGION`という変数は、環境変数です。

### VPC IDの取得
ルートテーブル作成時、VPC IDが必要になる話を先ほどしました。早速VPC IDを抽出して`EC2_VPC_ID`という変数に格納していきます。

```bash
EC2_VPC_ID=$( \
  aws ec2 describe-vpcs \
    --filters Name=tag:Name,Values=${EC2_VPC_TAG_NAME}  \
    --query 'Vpcs[].VpcId' \
    --output text \
) \
  && echo ${EC2_VPC_ID}
```

出力例

```bash
vpc-xxxxxxxxxxxxxxxxx
```

### ルートテーブルのタグ文字列設定
次は`STRING_EC2_ROUTE_TABLE_TAG`という変数にルートテーブルのタグ文字列を格納します。
リソースタイプ=route-tableと指定します。
また、タグは`key`に`Name`、`value`に`cloud9-coffee-route-table`を格納します。

```bash
STRING_EC2_ROUTE_TABLE_TAG="ResourceType=route-table,Tags=[{Key=Name,Value=${EC2_ROUTE_TABLE_TAG_NAME}}]" \
  && echo ${STRING_EC2_ROUTE_TABLE_TAG}
```

出力例

```bash
ResourceType=route-table,Tags=[{Key=Name,Value=cloud9-coffee-route-table}]
```

ヒアドキュメントで、変数に値が正しく入っているか確認します。

```bash
cat << END

  # EC2_VPC_ID:"vpc-xxxxxxxxxxxxxxxxx"
    EC2_VPC_ID="${EC2_VPC_ID}"
  # STRING_EC2_ROUTE_TABLE_TAG:"ResourceType=route-table,Tags=[{Key=Name,Value=cloud9-coffee-route-table}]"
    STRING_EC2_ROUTE_TABLE_TAG="${STRING_EC2_ROUTE_TABLE_TAG}"

END
```

出力例

```bash
  # EC2_VPC_ID:"vpc-xxxxxxxxxxxxxxxxx"
    EC2_VPC_ID="vpc-xxxxxxxxxxxxxxxxx"
  # STRING_EC2_ROUTE_TABLE_TAG:"ResourceType=route-table,Tags=[{Key=Name,Value=cloud9-coffee-route-table}]"
    STRING_EC2_ROUTE_TABLE_TAG="ResourceType=route-table,Tags=[{Key=Name,Value=cloud9-coffee-route-table}]"
```


### ルートテーブル作成
ルートテーブルを作成します。

```bash
aws ec2 create-route-table \
  --vpc-id ${EC2_VPC_ID} \
  --tag-specifications ${STRING_EC2_ROUTE_TABLE_TAG}
```

出力例

```bash
{
  "RouteTable": {
    "Associations": [],
    "PropagatingVgws": [],
    "RouteTableId": "rtb-xxxxxxxxxxxxxxxxx",
    "VpcId": "vpc-xxxxxxxxxxxxxxxxx",
    "Tags": [
        {
            "Key": "Name",
            "Value": "cloud9-coffee-route-table"
        }
    ],
    "OwnerId": "XXXXXXXXXXXX",
    "Routes": [
        {
            "GatewayId": "local",
            "DestinationCidrBlock": "172.16.0.0/16",
            "State": "active",
            "Origin": "CreateRouteTable"
        }
    ]
  }
}
```

- `aws ec2 create-route-table`
  - ルートテーブルを作成する
- `--vpc-id`
  - VPC IDを指定する
- `--tag-specifications`
  - ルートテーブルのタグ名を指定する

### ルートテーブルが作成できているか確認
では、"cloud9-coffee-route-table"なんてタグ名がついたルートテーブルができているかを確認します。

```bash
aws ec2 describe-route-tables \
  --filters Name=vpc-id,Values=${EC2_VPC_ID} \
            Name=tag:Name,Values=${EC2_ROUTE_TABLE_TAG_NAME}  \
  --query "RouteTables[].Tags[?Key == \`Name\`].Value" \
  --output text
```

出力例

```bash
handson-cloud9-route-table
```

- `aws ec2 describe-route-tables`
  - ルートテーブルの詳細を表示する
- `--filters Name=vpc-id,Values=${EC2_VPC_ID} \
            Name=tag:Name,Values=${EC2_ROUTE_TABLE_TAG_NAME}  \`
  - ここで--filterオプションを使ってAND検索しています。
VPC ID（vpc-id）が"vpc-xxxxxxxxxxxxxxxxx(取得したVPC ID)"**かつ**タグ名が"cloud9-coffee-route-table"のAND検索をしているというわけです。
- ```--query "RouteTables[].Tags[?Key == \`Name\`].Value"```
  - `key=Name`であるタグの`value`値を表示する

ここでCloudShellのセッションはいったん切断します。
以後の操作で変数汚染を防ぐため、`Ctr+D`で接続を切断します。
再度CloudShellから操作する際は`Enter`でCloudShellに再接続します。

マネジメントコンソール上でも、新しく「cloud9-coffee-route-table」というタグのついたルートテーブルが作成されているのが確認できます。
※表示されない場合は少し待ってからブラウザをリロードするか、選択しているリージョンが"東京"であることを確認してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/62741702-c53b-38d9-8639-f439af87c849.png)



## 7.ルートテーブルにルート設定する
JAWS-UG CLI専門支部　以下手順を参考にします。
[事前作業1.5. ルートの作成 (CloudShell: インターネットゲートウェイ: 0.0.0.0/0)](http://prototype-handson-cli.s3-website-ap-northeast-1.amazonaws.com/handson_light-aws_service/handson_light-aws_service-cloud9-environment-cloudshell/ec2-route-create-expand-internet_gateway-cloudshell.html)

ルートテーブル"cloud9-coffee-route-table"に、宛先"0.0.0.0/0"へのゲートウェイがインターネットゲートウェイ"cloud9-coffee-internet-gateway"となるルートを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/006bda46-bc04-4c89-3031-53a71a2562c8.png)


### リージョン確認
右上のリージョンメニューから"東京"を選択しておきます。
VPC作成時に東京以外のリージョンを選択した方は、作成したVPCと同じリージョンにしておいてください。

### VPCとルートテーブルのタグ名
ルートテーブルにルート設定する際、VPC IDとルートテーブルIDとインターネットゲートウェイIDが必要になります。各種IDを抽出するために、タグ名を変数に格納しておきます。

```bash
EC2_VPC_TAG_NAME='cloud9-coffee-vpc'
EC2_ROUTE_TABLE_TAG_NAME='cloud9-coffee-route-table'
EC2_INTERNET_GATEWAY_TAG_NAME='cloud9-coffee-internet-gateway'
```

### 宛先アドレス(0.0.0.0/0)

宛先アドレス(インターネット向け：0.0.0.0/0)を指定します。
`EC2_ROUTE_DESTINATION_CIDR`という変数に、IPアドレスCIDR範囲`0.0.0.0/0`を格納します。

```bash
EC2_ROUTE_DESTINATION_CIDR='0.0.0.0/0'
```

ヒアドキュメントで、変数に値が正しく入っているか確認します。

```bash
cat << END

  # 0. AWS_REGION:"ap-northeast-1"
       AWS_REGION="${AWS_REGION}"
  # 1. EC2_VPC_TAG_NAME:"cloud9-coffee-vpc"
       EC2_VPC_TAG_NAME="${EC2_VPC_TAG_NAME}"
  # 2. EC2_ROUTE_TABLE_TAG_NAME:"cloud9-coffee-route-table"
       EC2_ROUTE_TABLE_TAG_NAME="${EC2_ROUTE_TABLE_TAG_NAME}"
  # 3. EC2_ROUTE_DESTINATION_CIDR:"0.0.0.0/0"
       EC2_ROUTE_DESTINATION_CIDR="${EC2_ROUTE_DESTINATION_CIDR}"
  # 4. EC2_INTERNET_GATEWAY_TAG_NAME:"cloud9-coffee-internet-gateway"
       EC2_INTERNET_GATEWAY_TAG_NAME="${EC2_INTERNET_GATEWAY_TAG_NAME}"

END
```

出力例

```bash
  # 0. AWS_REGION:"ap-northeast-1"
       AWS_REGION="ap-northeast-1"
  # 1. EC2_VPC_TAG_NAME:"cloud9-coffee-vpc"
       EC2_VPC_TAG_NAME="cloud9-coffee-vpc"
  # 2. EC2_ROUTE_TABLE_TAG_NAME:"cloud9-coffee-route-table"
       EC2_ROUTE_TABLE_TAG_NAME="cloud9-coffee-route-table"
  # 3. EC2_ROUTE_DESTINATION_CIDR:"0.0.0.0/0"
       EC2_ROUTE_DESTINATION_CIDR="0.0.0.0/0"
  # 4. EC2_INTERNET_GATEWAY_TAG_NAME:"cloud9-coffee-internet-gateway"
       EC2_INTERNET_GATEWAY_TAG_NAME="cloud9-coffee-internet-gateway"
```

上下の文字列が同じであれば、変数に正しい値が格納されています。
`AWS_REGION`という変数は、環境変数です。


### 各種IDの取得
VPC IDを取得します。
`EC2_VPC_ID`という変数に、抽出したVPC IDを格納します。

```bash
EC2_VPC_ID=$( \
  aws ec2 describe-vpcs \
    --filters Name=tag:Name,Values=${EC2_VPC_TAG_NAME}  \
    --query 'Vpcs[].VpcId' \
    --output text \
) \
  && echo ${EC2_VPC_ID}
```

出力例

```bash
vpc-xxxxxxxxxxxxxxxxx
```

ルートテーブルIDを取得します。
`EC2_ROUTE_TABLE_ID`という変数に、抽出したルートテーブルIDを格納します。

```bash
EC2_ROUTE_TABLE_ID=$( \
  aws ec2 describe-route-tables \
    --filters Name=vpc-id,Values=${EC2_VPC_ID} \
              Name=tag:Name,Values=${EC2_ROUTE_TABLE_TAG_NAME}  \
    --query "RouteTables[].RouteTableId" \
    --output text \
) \
  && echo ${EC2_ROUTE_TABLE_ID}
```

出力例

```bash
rtb-xxxxxxxxxxxxxxxxx
```

- `aws ec2 describe-route-tables`
  - ルートテーブルの詳細を表示する
- `--filters Name=vpc-id,Values=${EC2_VPC_ID} \
              Name=tag:Name,Values=${EC2_ROUTE_TABLE_TAG_NAME}  \`
  - VPC ID（vpc-id）が"vpc-xxxxxxxxxxxxxxxxx(取得したVPC ID)"**かつ**タグ名が"cloud9-coffee-route-table"のAND検索をしている
- `--query "RouteTables[].RouteTableId"`
  - ルートテーブルの中のルートテーブルID項目(RouteTableId)を表示する


インターネットゲートウェイIDを取得します。
`EC2_INTERNET_GATEWAY_ID`という変数に、抽出したインターネットゲートウェイIDを格納します。

```bash
EC2_INTERNET_GATEWAY_ID=$( \
  aws ec2 describe-internet-gateways \
    --filters Name=tag:Name,Values=${EC2_INTERNET_GATEWAY_TAG_NAME} \
    --query "InternetGateways[].InternetGatewayId" \
    --output text \
) \
  && echo ${EC2_INTERNET_GATEWAY_ID}
```

出力例

```bash
igw-xxxxxxxxxxxxxxxxx
```

ヒアドキュメントで、変数に値が正しく入っているか確認します。

```bash
cat << END

  # EC2_ROUTE_TABLE_ID:"rtb-xxxxxxxxxxxxxxxxx"
    EC2_ROUTE_TABLE_ID="${EC2_ROUTE_TABLE_ID}"
  # EC2_INTERNET_GATEWAY_ID:"igw-xxxxxxxxxxxxxxxxx"
    EC2_INTERNET_GATEWAY_ID="${EC2_INTERNET_GATEWAY_ID}"

END
```

出力例

```bash
  # EC2_ROUTE_TABLE_ID:"rtb-xxxxxxxxxxxxxxxxx"
    EC2_ROUTE_TABLE_ID="rtb-xxxxxxxxxxxxxxxxx"
  # EC2_INTERNET_GATEWAY_ID:"igw-xxxxxxxxxxxxxxxxx"
    EC2_INTERNET_GATEWAY_ID="igw-xxxxxxxxxxxxxxxxx"
```


### ルートの設定
ではルートテーブルの中にルートを設定していきます。

```bash
aws ec2 create-route \
  --route-table-id ${EC2_ROUTE_TABLE_ID} \
  --destination-cidr-block ${EC2_ROUTE_DESTINATION_CIDR} \
  --gateway-id ${EC2_INTERNET_GATEWAY_ID}
```

出力例

```bash
{
  "Return": true
}
```

- `aws ec2 create-route`
  - ルートを作成する
- `--route-table-id`
  - ルートを設定するルートテーブルIDを指定する
- `--destination-cidr-block`
  - 宛先CIDR範囲を指定する
- `--gateway-id`
  - ターゲットとなるゲートウェイIDを指定する。今回はインターネットゲートウェイを指定している


### ルートテーブルに設定したルーティング設定があることを確認する
ルートテーブル"cloud9-coffee-route-table"に"0.0.0.0/0"へのルートが存在することを確認します。

```bash
aws ec2 describe-route-tables \
  --filters Name=vpc-id,Values=${EC2_VPC_ID} \
            Name=tag:Name,Values=${EC2_ROUTE_TABLE_TAG_NAME}  \
  --query "RouteTables[].Routes[?DestinationCidrBlock == \`${EC2_ROUTE_DESTINATION_CIDR}\`].DestinationCidrBlock" \
  --output text
```

出力例

```bash
0.0.0.0/0
```

- ```--query "RouteTables[].Routes[?DestinationCidrBlock == \`${EC2_ROUTE_DESTINATION_CIDR}\`].DestinationCidrBlock" \```
  - ルートテーブルの中の宛先CIDR範囲(DestinationCidrBlock)が、設定したCIDR範囲(0.0.0.0/0)である宛先CIDR範囲項目(DestinationCidrBlock)を表示する


続いてルートテーブル"cloud9-coffee-route-table"の"0.0.0.0/0"へのルートがインターネットゲートウェイ"cloud9-coffee-internet-gateway"に設定されていることを確認します。

```bash
aws ec2 describe-route-tables \
  --filters Name=vpc-id,Values=${EC2_VPC_ID} \
            Name=tag:Name,Values=${EC2_ROUTE_TABLE_TAG_NAME}  \
  --query "RouteTables[].Routes[?DestinationCidrBlock == \`${EC2_ROUTE_DESTINATION_CIDR}\`].GatewayId" \
  --output text
```

出力例

```bash
igw-xxxxxxxxxxxxxxxxx
```

- ```--query "RouteTables[].Routes[?DestinationCidrBlock == \`${EC2_ROUTE_DESTINATION_CIDR}\`].GatewayId" \```
  - ルートテーブルの中の宛先CIDR範囲(DestinationCidrBlock)が、設定したCIDR範囲(0.0.0.0/0)であるゲートウェイID項目(GatewayId)を表示する


ここでCloudShellのセッションはいったん切断します。
以後の操作で変数汚染を防ぐため、`Ctr+D`で接続を切断します。
再度CloudShellから操作する際は`Enter`でCloudShellに再接続します。


マネジメントコンソール上でも、ルートテーブル「cloud9-coffee-route-table」のルーティング設定に、送信先が"0.0.0.0/0"、ターゲットが"igw-xxxxxxxxxxxxxxxxx(作成したインターネットゲートウェイのID)"のルートが存在するのが確認できます。
※表示されない場合は少し待ってからブラウザをリロードするか、選択しているリージョンが"東京"であることを確認してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/c335547d-b168-69a7-f06f-d49933e719c3.png)


## 8.Cloud9用VPC内にサブネットを作成する
JAWS-UG CLI専門支部　以下手順を参考にします。
[事前作業1.6. サブネットの作成 (CloudShell: public-subnet)](http://prototype-handson-cli.s3-website-ap-northeast-1.amazonaws.com/handson_light-aws_service/handson_light-aws_service-cloud9-environment-cloudshell/ec2-subnet-create-expand-cloudshell-public_alpha.html)

サブネットを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/24071480-341e-ac67-854e-514bdf6632cb.png)

### リージョン確認
右上のリージョンメニューから"東京"を選択しておきます。
VPC作成時に東京以外のリージョンを選択した方は、作成したVPCと同じリージョンにしておいてください。

### VPCのタグ名
サブネットを作成するにはサブネットを作成するVPCのVPC IDが必要になります。VPC IDを抽出するのにVPCのタグ名が必要になるため、変数にVPCのタグ名を格納しておきます。

```bash
EC2_VPC_TAG_NAME='cloud9-coffee-vpc'
```

### サブネットのタグ名
`EC2_SUBNET_TAG_NAME`という変数に、サブネットのタグ名を指定します。
このサブネットはインターネットへ接続できるパブリックサブネットにする予定です。私はコーヒーが好きなので`cloud9-coffee-public-subnet`とタグ名を付けましょう。

```bash
EC2_SUBNET_TAG_NAME='cloud9-coffee-public-subnet'
```

### サブネットのアドレスレンジ設定
`EC2_SUBNET_CIDR`という変数に、サブネットのアドレスレンジを指定します。
現在作成済みの`cloud9-coffee-vpc`のアドレス範囲は`172.16.0.0～172.16.255.255(172.16.0.0/16)`です。
サブネットのIPアドレス範囲は、このVPCのアドレス範囲に収まるように設定します。
今回は`172.16.0.0～172.16.255.255(172.16.0.0/24)`と設定してみましょう。

```bash
EC2_SUBNET_CIDR='172.16.0.0/24'
```

### サブネットを配置するAZ名を指定する
`EC2_AZ_NAME`という変数に、サブネットを配置するAZ(アベイラビリティゾーン)名を指定します。

東京リージョン（ap-northeast-1）には以下3つのAZがあります。

- ap-northeast-1a
- ap-northeast-1c
- ap-northeast-1d

今回はどこでもいいですが、`ap-northeast-1d`にしてみましょう。

```bash
EC2_AZ_NAME="ap-northeast-1d"
```

2021年8月7日のAWS亀田さん勉強会「最新サービスをみんなで触ってみる」で聞いたうろ覚えのことですが、一度にたくさんの人が`ap-northeast-1d`を選択しても、`ap-northeast-1d`AZ内のいろいろなデータセンタに分散されるため、ある程度同時にアクセスしても大丈夫、みたいな感じらしいです。規模が大きいのでしょうかね？


ヒアドキュメントで、変数に値が正しく入っているか確認します。

```bash
cat << END

  # 0. AWS_REGION:"ap-northeast-1"
       AWS_REGION="${AWS_REGION}"
  # 1. EC2_VPC_TAG_NAME:"cloud9-coffee-vpc"
       EC2_VPC_TAG_NAME="${EC2_VPC_TAG_NAME}"
  # 2. EC2_SUBNET_TAG_NAME:"cloud9-coffee-public-subnet"
       EC2_SUBNET_TAG_NAME="${EC2_SUBNET_TAG_NAME}"
  # 3. EC2_SUBNET_CIDR:"172.16.0.0/24"
       EC2_SUBNET_CIDR="${EC2_SUBNET_CIDR}"
  # 4. EC2_AZ_NAME:"ap-northeast-1d"
       EC2_AZ_NAME="${EC2_AZ_NAME}"

END
```

出力例

```bash
  # 0. AWS_REGION:"ap-northeast-1"
       AWS_REGION="ap-northeast-1"
  # 1. EC2_VPC_TAG_NAME:"cloud9-coffee-vpc"
       EC2_VPC_TAG_NAME="cloud9-coffee-vpc"
  # 2. EC2_SUBNET_TAG_NAME:"cloud9-coffee-public-subnet"
       EC2_SUBNET_TAG_NAME="cloud9-coffee-public-subnet"
  # 3. EC2_SUBNET_CIDR:"172.16.0.0/24"
       EC2_SUBNET_CIDR="172.16.0.0/24"
  # 4. EC2_AZ_NAME:"ap-northeast-1d"
       EC2_AZ_NAME="ap-northeast-1d"
```

上下の文字列が同じであれば、変数に正しい値が格納されています。
`AWS_REGION`という変数は、環境変数です。

### VPC IDの取得
VPC IDの取得も慣れてきましたね。

```bash
EC2_VPC_ID=$( \
  aws ec2 describe-vpcs \
    --filters Name=tag:Name,Values=${EC2_VPC_TAG_NAME}  \
    --query 'Vpcs[].VpcId' \
    --output text \
) \
  && echo ${EC2_VPC_ID}
```

出力例

```bash
vpc-xxxxxxxxxxxxxxxxx
```

### サブネットのタグ文字列設定
次は`STRING_EC2_SUBNET_TAG`という変数にサブネットのタグ文字列を格納します。
リソースタイプ=`subnet`と指定します。
また、タグは`key`に`Name`、`value`に`cloud9-coffee-public-subnet`を格納します。

```bash
STRING_EC2_SUBNET_TAG="ResourceType=subnet,Tags=[{Key=Name,Value=${EC2_SUBNET_TAG_NAME}}]" \
  && echo ${STRING_EC2_SUBNET_TAG}
```

出力例

```bash
ResourceType=subnet,Tags=[{Key=Name,Value=cloud9-coffee-public-subnet}]
```

### サブネットの作成
サブネットを作成します。

```bash
aws ec2 create-subnet \
  --vpc-id ${EC2_VPC_ID} \
  --cidr-block ${EC2_SUBNET_CIDR} \
  --availability-zone ${EC2_AZ_NAME} \
  --tag-specifications ${STRING_EC2_SUBNET_TAG}
```

出力例

```bash
{
  "Subnet": {
    "AvailabilityZone": "ap-northeast-1d",
    "AvailabilityZoneId": "<AZ_ID>",
    "AvailableIpAddressCount": 251
    "CidrBlock": "172.16.0.0/24",
    "DefaultForAz": false,
    "MapPublicIpOnLaunch": false,
    "State": "pending",
    "SubnetId": "subnet-xxxxxxxxxxxxxxxxx",
    "VpcId": "vpc-xxxxxxxxxxxxxxxxx",
    "OwnerId": "XXXXXXXXXXXX",
    "AssignIpv6AddressOnCreation": false,
    "Ipv6CidrBlockAssociationSet": [],
    "Tags": [
        {
            "Key": "Name",
            "Value": "cloud9-coffee-public-subnet"
        }
    ],
    "SubnetArn": "arn:aws:ec2:ap-northeast-1:XXXXXXXXXXXX:subnet/subnet-xxxxxxxxxxxxxxxxx"
  }
}
```

- `aws ec2 create-subnet`
  - サブネットを作成する
- `--vpc-id`
  - サブネットを作成するVPCのVPC IDを指定する
- `--cidr-block`
  - サブネットのCIDR範囲を指定する
- `--availability-zone`
  - サブネットを作成するAZ名を指定する
- `--tag-specifications`
  - タグ名を指定する

### サブネットができているか確認
VPC"cloud9-coffee-vpc"にサブネット"cloud9-coffee-public-subnet"が存在することを確認します。

```bash
aws ec2 describe-subnets \
  --filters Name=vpc-id,Values=${EC2_VPC_ID} \
            Name=tag:Name,Values=${EC2_SUBNET_TAG_NAME}  \
  --query 'Subnets[].Tags[?Key == `Name`].Value' \
  --output text
```

出力例

```bash
cloud9-coffee-public-subnet
```

- `aws ec2 describe-subnets`
  - サブネットの詳細を表示する
- ```--filters Name=vpc-id,Values=${EC2_VPC_ID} \
            Name=tag:Name,Values=${EC2_SUBNET_TAG_NAME}```
   - VPC ID（vpc-id）が"vpc-xxxxxxxxxxxxxxxxx(取得したVPC ID)"かつタグ名が"cloud9-coffee-public-subnet"のAND検索
- ```--query 'Subnets[].Tags[?Key == `Name`].Value'```
  - `key=Name`であるタグの`value`値を表示する


続いてサブネット"cloud9-coffee-public-subnet"のCIDRは"172.16.0.0/24"であることを確認します。

```bash
aws ec2 describe-subnets \
  --filters Name=vpc-id,Values=${EC2_VPC_ID} \
            Name=tag:Name,Values=${EC2_SUBNET_TAG_NAME}  \
  --query "Subnets[].CidrBlock" \
  --output text
```

出力例

```bash
172.16.0.0/24
```

- `--query "Subnets[].CidrBlock"`
  - サブネットの中の`CidrBlock`という項目を表示させる


続いて、サブネット"cloud9-coffee-public-subnet"のAZは"ap-northeast-1d"であることを確認します。

```bash
aws ec2 describe-subnets \
  --filters Name=vpc-id,Values=${EC2_VPC_ID} \
            Name=tag:Name,Values=${EC2_SUBNET_TAG_NAME}  \
  --query "Subnets[].AvailabilityZone" \
  --output text
```

出力例

```bash
ap-northeast-1d
```

- `--query "Subnets[].AvailabilityZone"`
  - サブネットの中の`AvailabilityZone`という項目を表示させる


ここでCloudShellのセッションはいったん切断します。
以後の操作で変数汚染を防ぐため、`Ctr+D`で接続を切断します。
再度CloudShellから操作する際は`Enter`でCloudShellに再接続します。


マネジメントコンソール上でも、新しく「cloud9-coffee-public-subnet」というタグのついたサブネットが作成されているのが確認できます。
※表示されない場合は少し待ってからブラウザをリロードするか、選択しているリージョンが"東京"であることを確認してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/9549a85d-b645-37ea-2d69-d6ecfd743528.png)


## 9.Cloud9用VPC内のサブネットにルートテーブルを紐づける
JAWS-UG CLI専門支部　以下手順を参考にします。
[事前作業1.7. ルートテーブルの更新 (CloudShell: public-subnetとの関連付け)](http://prototype-handson-cli.s3-website-ap-northeast-1.amazonaws.com/handson_light-aws_service/handson_light-aws_service-cloud9-environment-cloudshell/ec2-route_table-update-expand-associate-cloudshell-public_alpha.html)

作成したサブネットに、作成したルートテーブルを紐づけます。これでこのサブネットからインターネットへ接続できるようになり、パブリックサブネットと名乗れるようになります。
いよいよコーヒーのいい香りがしてきましたね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/030c4db6-852d-56f1-60a7-615462f3276e.png)

### リージョン確認
右上のリージョンメニューから"東京"を選択しておきます。
VPC作成時に東京以外のリージョンを選択した方は、作成したVPCと同じリージョンにしておいてください。


### VPC、ルートテーブル、サブネットのタグ名
各種タグ名を変数に格納します。

```bash
EC2_VPC_TAG_NAME='cloud9-coffee-vpc'
EC2_ROUTE_TABLE_TAG_NAME='cloud9-coffee-route-table'
EC2_SUBNET_TAG_NAME='cloud9-coffee-public-subnet'
```

ヒアドキュメントで、変数に値が正しく入っているか確認します。

```bash
cat << END

  # 0. AWS_REGION:"ap-northeast-1"
       AWS_REGION="${AWS_REGION}"
  # 1. EC2_VPC_TAG_NAME:"cloud9-coffee-vpc"
       EC2_VPC_TAG_NAME="${EC2_VPC_TAG_NAME}"
  # 2. EC2_ROUTE_TABLE_TAG_NAME:"cloud9-coffee-route-table"
       EC2_ROUTE_TABLE_TAG_NAME="${EC2_ROUTE_TABLE_TAG_NAME}"
  # 3. EC2_SUBNET_TAG_NAME:"cloud9-coffee-public-subnet"
       EC2_SUBNET_TAG_NAME="${EC2_SUBNET_TAG_NAME}"

END
```

出力例


```bash
  # 0. AWS_REGION:"ap-northeast-1"
       AWS_REGION="ap-northeast-1"
  # 1. EC2_VPC_TAG_NAME:"cloud9-coffee-vpc"
       EC2_VPC_TAG_NAME="cloud9-coffee-vpc"
  # 2. EC2_ROUTE_TABLE_TAG_NAME:"cloud9-coffee-route-table"
       EC2_ROUTE_TABLE_TAG_NAME="cloud9-coffee-route-table"
  # 3. EC2_SUBNET_TAG_NAME:"cloud9-coffee-public-subnet"
       EC2_SUBNET_TAG_NAME="cloud9-coffee-public-subnet"
```

上下の文字列が同じであれば、変数に正しい値が格納されています。
`AWS_REGION`という変数は、環境変数です。

### VPC、ルートテーブル、サブネットのID取得

VPC IDを取得します。

```bash
EC2_VPC_ID=$( \
  aws ec2 describe-vpcs \
    --filters Name=tag:Name,Values=${EC2_VPC_TAG_NAME}  \
    --query 'Vpcs[].VpcId' \
    --output text \
) \
  && echo ${EC2_VPC_ID}
```

出力例

```bash
vpc-xxxxxxxxxxxxxxxxx
```

ルートテーブルIDを取得します。

```bash
EC2_ROUTE_TABLE_ID=$( \
  aws ec2 describe-route-tables \
    --filters Name=vpc-id,Values=${EC2_VPC_ID} \
              Name=tag:Name,Values=${EC2_ROUTE_TABLE_TAG_NAME}  \
    --query "RouteTables[].RouteTableId" \
    --output text \
) \
  && echo ${EC2_ROUTE_TABLE_ID}
```

出力例

```bash
rtb-xxxxxxxxxxxxxxxxx
```

サブネットIDを取得します。

```bash
EC2_SUBNET_ID=$( \
  aws ec2 describe-subnets \
    --filters Name=vpc-id,Values=${EC2_VPC_ID} \
              Name=tag:Name,Values=${EC2_SUBNET_TAG_NAME}  \
    --query "Subnets[].SubnetId" \
    --output text \
) \
  && echo ${EC2_SUBNET_ID}
```

出力例

```bash
subnet-xxxxxxxxxxxxxxxxx
```

ヒアドキュメントで、変数に値が正しく入っているか確認します。

```bash
cat << END

  # EC2_SUBNET_ID:"subnet-xxxxxxxxxxxxxxxxx"
    EC2_SUBNET_ID="${EC2_SUBNET_ID}"
  # EC2_ROUTE_TABLE_ID:"rtb-xxxxxxxxxxxxxxxxx"
    EC2_ROUTE_TABLE_ID="${EC2_ROUTE_TABLE_ID}"

END
```

出力例

```bash
  # EC2_SUBNET_ID:"subnet-xxxxxxxxxxxxxxxxx"
    EC2_SUBNET_ID="subnet-xxxxxxxxxxxxxxxxx"
  # EC2_ROUTE_TABLE_ID:"rtb-xxxxxxxxxxxxxxxxx"
    EC2_ROUTE_TABLE_ID="rtb-xxxxxxxxxxxxxxxxx"
```


### ルートテーブルをサブネットに関連付ける
ルートテーブルとサブネットを関連付けします。

```bash
aws ec2 associate-route-table \
  --subnet-id ${EC2_SUBNET_ID} \
  --route-table-id ${EC2_ROUTE_TABLE_ID}
```

出力例

```bash
{
  "AssociationId": "rtbassoc-xxxxxxxxxxxxxxxxx"
  "AssociationState": {
      "State": "associated"
  }
}
```
- `aws ec2 associate-route-table`
  - ルートテーブルをサブネットに関連付ける
- `--subnet-id`
  - 関連付けるサブネットのサブネットIDを指定する
- `--route-table-id`
  - 関連付けるルートテーブルのルートテーブルIDを指定する


### ルートテーブルがサブネットに紐づいたか確認する
ルートテーブル"cloud9-coffee-route-table"がサブネット"cloud9-coffee-public-subnet"と関連付いていることを確認します。

```bash
aws ec2 describe-route-tables \
  --route-table-ids ${EC2_ROUTE_TABLE_ID} \
  --query "RouteTables[].Associations[?SubnetId == \`${EC2_SUBNET_ID}\`].RouteTableAssociationId" \
  --output text
```

出力例

```bash
rtbassoc-xxxxxxxxxxxxxxxxxx
```

ここでCloudShellのセッションは`Ctr+D`で切断します。


マネジメントコンソール上でも、ルートテーブル"cloud9-coffee-route-table"がサブネット"cloud9-coffee-public-subnet"と関連付いていることが確認できます。
※表示されない場合は少し待ってからブラウザをリロードするか、選択しているリージョンが"東京"であることを確認してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/c4b66286-c1f6-22a1-f4f6-fb77a459717d.png)


# Cloud9環境のためのVPCができました
以上で、Cloud9環境を作成する前準備として、ルートテーブルなども含むVPCの作成が完了しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/c670b697-c4a1-7272-f161-be4e46bce872.png)

ここまでで作成したリソースには課金されません。
次回は、**Cloud9環境を操作するためのユーザ作成**の復習を実施する予定です。

権限周りのイメージ図↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/6db08e2d-91d3-2317-fa79-75fd3837b895.png)




# 参考資料

https://docs.aws.amazon.com/ja_jp/cli/latest/reference/ec2/index.html

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-subnets-commands-example.html