AWS CLI VPC

## はじめに

AWS CLIでVPCにEC2を作成し疎通の確認を取ります。
CLIの勉強をしたのでアウトプット目的です。

## 対象者
この記事は下記のような人を対象にしています。

- 駆け出しエンジニア
- AWS CLIについて全くわからない方、勉強したい方

## 環境

CLIで作業をしますので以下環境です。
```
// OSとバージョンの確認
cat /etc/system-release
Amazon Linux release 2 (Karoo)

// シェルとバージョンの確認
bash --version \
  | head -1
GNU bash, バージョン 4.2.46(2)-release (x86_64-redhat-linux-gnu)

// AWS CLIのバージョンの確認
aws --version
aws-cli/1.20.56 Python/3.7.10 Linux/4.14.246-187.474.amzn2.x86_64 botocore/1.21.56
```

## 段落
①VPCの作成
②サブネットの作成
③セキュリティグループ作成
④ルートテーブルの作成
⑤ルートテーブルとサブネットの紐付け
⑥インターネットゲートウェイ作成
⑦インターネットゲートウェイとVPCの紐付け


## VPCの作成
```
// リージョン指定
export AWS_DEFAULT_REGION='ap-northeast-1'

// VPCのタグ名指定
EC2_VPC_TAG_NAME='handson-cli-vpc'

// VPCのCIDRを指定
EC2_VPC_CIDR='10.0.0.0/16'

// タグ文字列の指定
STRING_EC2_VPC_TAG="ResourceType=vpc,Tags=[{Key=Name,Value=${EC2_VPC_TAG_NAME}}]" \
  && echo ${STRING_EC2_VPC_TAG}

// ResourceType=vpc,Tags=[{Key=Name,Value=handson-cli-vpc}]

```

create-vpcで作成VPCにタグを割り当てるには以下のような構文する必要がある
ResourceType=string,Tags=[{Key=string,Value=string}]
{Key=string,Value=string}は一つでも可能だが、スペースなど空けずに詰めて書かないとエラーになる

```
// VPVの作成
aws ec2 create-vpc \
  --cidr-block ${EC2_VPC_CIDR} \
  --tag-specifications ${STRING_EC2_VPC_TAG}

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

// 作成したVPCの存在確認
aws ec2 describe-vpcs \
  --filters Name=tag:Name,Values=${EC2_VPC_TAG_NAME}  \
  --query 'Vpcs[].Tags[?Key == `Name`].Value' \
  --output text

handson-cli-vpc

// 作成したVPCのCIDRの確認
aws ec2 describe-vpcs \
> --filters Name=tag:Name,Values=${EC2_VPC_TAG_NAME} \
> --query "Vpcs[].CidrBlock" \
> --output text

10.0.0.0/16
```

## サブネットの作成
```
// サブネット名の指定
EC2_SUBNET_TAG_NAME='handson-cli-subnet'

// サブネットのCIDRを指定
EC2_SUBNET_CIDR='10.0.0.0/24'

// AZを指定
EC2_AZ_NAME='ap-northeast-1a'

// VPCのIDを取得する
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}

vpc-0d627a55f8e265976

// サブネットのタグを作成する
STRING_EC2_SUBNET_TAG="ResourceType=subnet,Tags=[{Key=Name,Value=${EC2_SUBNET_TAG_NAME}}]" && echo ${STRING_EC2_SUBNET_TAG}

ResourceType=subnet,Tags=[{Key=Name,Value=handson-cli-subnet}]

// サブネットを作成する
aws ec2 create-subnet \
> --tag-specifications ${STRING_EC2_SUBNET_TAG} \
> --cidr-block ${EC2_SUBNET_CIDR} \
> --vpc-id ${EC2_VPC_ID} \
> --availability-zone ${EC2_AZ_NAME} 

{
    "Subnet": {
        "AvailabilityZone": "ap-northeast-1a",
        "AvailabilityZoneId": "apne1-az4",
        "AvailableIpAddressCount": 251,
        "CidrBlock": "10.0.0.0/24",
・・・・以下略


//　作成したサブネットのCIDRの確認
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

10.0.0.0/24

//　作成したサブネットの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

subnet-0af8f1c36db7c04f0

// 作成したサブネットが存在することを確認
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

handson-cli-subnet
```

## セキュリティグループの作成
```
// セキュリティーグループ名の指定
EC2_SECURITY_GROUP_NAME='handson-cli-sg'

//セキュリティグループの説明を指定
EC2_SECURITY_DESCRIPTTION='handson-cli SecurityGroup.'

//セキュリティグループの作成
aws ec2 create-security-group \
>   --group-name ${EC2_SECURITY_GROUP_NAME} \
>   --description "${EC2_SECURITY_GROUP_DESCRIPTION}" \
>   --vpc-id ${EC2_VPC_ID}

{
    "GroupId": "sg-089bac6aeeda2d58e"
}

// 作成したセキュリティグループの存在の確認
aws ec2 describe-security-groups \
> --filter Name=vpc-id,Values=${EC2_VPC_ID} \
>  --query 'SecurityGroups[].GroupName' \
>   --output text

handson-cli-sg  default
```
--descriptionには""で囲わないとエラーとなりますので注意が必要です。

## ルートテーブルの作成
```
// ルートテーブル名の指定
EC2_ROUTE_TABLE_TAG_NAME='handson-cli-public-routetable'

// 作成するルートテーブルのタグを指定
STRING_EC2_ROUTE_TABLE_TAG="ResourceType=route-table,Tags=[{Key=Name,Value=${EC2_ROUTE_TABLE_TAG_NAME}}]" \
> && echo ${STRING_EC2_ROUTE_TABLE_TAG}

ResourceType=route-table,Tags=[{Key=Name,Value=handson-cli-public-routetable}]

// ルートテーブルの作成
aws ec2 create-route-table \
> --vpc-id  ${EC2_VPC_ID} \
> --tag-specifications ${STRING_EC2_ROUTE_TABLE_TAG} 
{
    "RouteTable": {
・・・以下略

// 作成したルートテーブルの存在確認
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

handson-cli-public-routetable
```

# ルートテーブルをサブネットへ紐付け
```
// ルートテーブルIDを取得
EC2_ROUTE_TABLE_=$( \
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_}

rtb-01d71110c1e615ec4

// サブネットIDの取得
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}

subnet-0af8f1c36db7c04f0

// ルートテーブルをサブネットに紐付け
aws ec2 associate-route-table \
> --route-table-id ${EC2_ROUTE_TABLE_ID} \
> --subnet-id ${EC2_SUBNET_ID}
{
    "AssociationId": "rtbassoc-06dea3d4353c422c8",
    "AssociationState": {
        "State": "associated"
    }
}

// ルートテーブルがサブネットに紐付けされているか確認
aws ec2 describe-route-tables \
> --route-table-ids ${EC2_ROUTE_TABLE_ID} \
> --query "RouteTables[].Associations[?SubnetId== \`${EC2_SUBNET_ID}\`].RouteTableAssociationId" \
> --output text

rtbassoc-06dea3d4353c422c8
```

## インターネットゲートウェイの作成
```
// インターネットゲートウェイ名を指定
EC2_INTERNET_GATEWAY_TAG_NAME='handson-cli-igw'

// タグ名を指定
STRING_EC2_INTERNET_GATEWAY_TAG="ResourceType=internet-gateway,Tags=[{Key=Name,Value=${EC2_INTERNET_GATEWAY_TAG_NAME}}]" \
  && echo ${STRING_EC2_INTERNET_GATEWAY_TAG}

ResourceType=internet-gateway,Tags=[{Key=Name,Value=handson-cli-igw}]

//インターネットゲートウェイを作成
aws ec2 create-internet-gateway \
> --tag-specifications ${STRING_EC2_INTERNET_GATEWAY_TAG} 
{
    "InternetGateway": {
        "Attachments": [],
        "InternetGatewayId": "igw-03f61f722ec6fd242",
        "OwnerId": "302471719360",
        "Tags": [
            {
                "Key": "Name",
                "Value": "handson-cli-igw"
            }
        ]
    }
}

// インターネットゲートウェイの存在を確認
aws ec2 describe-internet-gateways \
--filters Name=tag:Name,Values=${EC2_INTERNET_GATEWAY_TAG_NAME} \ 
--query InternetGateways[].Tags[].Value \
--output text

handson-cli-igw
```

## インターネットゲートウェイをVPCにアタッチ
```
// インターネットゲートウェイIDを取得
EC2_INTERNETGATEWAY_ID=$( \
aws ec2 describe-internet-gateways \
--filters Name=tag:Name,Values=${EC2_INTERNET_GATEWAY_TAG_NAME} \
--query InternetGateways[].InternetGatewayId  \
--output text \
> ) \
> && echo ${EC2_INTERNETGATEWAY_ID}

igw-03f61f722ec6fd242

// インターネットゲートウェイをVPCにアタッチ
aws ec2 attach-internet-gateway \
> --internet-gateway-id ${EC2_INTERNETGATEWAY_ID} \
> --vpc-id  ${EC2_VPC_ID}

// VPCにインターネットゲートウェイがアタッチされているか確認
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

vpc-0d627a55f8e265976
```

## ルートの作成
```
// ルート名を指定
EC2_ROUTE_TABLE_TAG_NAME='handson-cli-public-routetable'

// ルートのアドレスを指定
EC2_ROUTE_DESTINATION_CIDR='0.0.0.0/0'

// ルートの作成
aws ec2 create-route  \ 
--route-table-id ${EC2_ROUTE_TABLE_ID}  \
--destination-cidr-block ${EC2_ROUTE_DESTINATION_CIDR} \
 --gateway-id ${EC2_INTERNETGATEWAY_ID}
{
    "Return": true
}

// ルートが0.0.0.0/0に存在することを確認
aws ec2 describe-route-tables \ 
--filters Name=vpc-id,Values=${EC2_VPC_ID}Name=tag:Name,Values=${EC2_ROUTE_TABLE_TAG_NAME} Name=vpc-id,Values=${EC2_VPC_ID} \
--query "RouteTables[].Routes[?DestinationCidrBlock == \`${EC2_ROUTE_DESTINATION_CIDR}\`].DestinationCidrBlock" \
--output text

0.0.0.0/0

// ルートがインターネットゲートウェイにアタッチされているか確認
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

igw-xxxxxxxxxxxxxxxxx
```
作成した際にtrueが帰ってくると成功です。
それ以外の場合は、エラーを返します。


## 参考
[AWS CLIリファレンス](https://awscli.amazonaws.com/v2/documentation/api/latest/index.html)