AWS CLIで Web サイトを構築、管理、運用する(14日目)

14日目です！
今回から、何回かに分けて、EC2周りを利用したWebサイトも併せて構築、管理、運用していきます。

まずは、ネットワーク周りの構築を実施します。


# 14日目の要約
ネットワーク設定をするよ！

# AWS CLI の準備
このあたりをみて、好きなバージョンとお使いのOSにあった環境設定をしてくださいね。
なんなら、 AWS CloudShell で実行するのも楽でよいと思います。
この記事シリーズは、AWS CloudShell で実行し、実行例を載せています。

バージョン１
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv1.html

バージョン２
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2.html

# 概要
EC2 を稼働させるためのネットワーク設定やセキュリティグループ設定をするよ

# さあ、やってみよう！
EC2を動かすには、非常に雑ですが、以下のようなネットワーク構成が必要です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344161/6edf52cd-1d82-b7b2-c03d-8ad0107eb8b3.png)

そのため、今回は以下に示すものを作成していきます。

* Amazon Virtual Private Cloud(Amazon VPC)
* Subnet
* Internet Gateway(IGW)
* RouteTable
* Security Group

12日目のまとめの後ろでお伝えした通り、セキュリティグループのルール数が重要になってきます。
上限緩和申請が済んでいない場合は、実施してから後続の実行をお願いします。

では、順々に見ていきましょう。

## VPC の作成
まずは、肝心かなめの VPC を作成します。
ec2 create-vpc コマンドを使います。

```sh
aws ec2 create-vpc --cidr-block 10.0.0.0/16
```

VPC が正常に作成できると、以下の様に json が返ってきます。
後続の操作では、 VpcId が必要になるので、確認しておきます。

```json
{
    "Vpc": {
        "CidrBlock": "10.0.0.0/16",
        "DhcpOptionsId": "dopt-********",
        "State": "pending",
        "VpcId": "vpc-*****************",
        "OwnerId": "************",
        "InstanceTenancy": "default",
        "Ipv6CidrBlockAssociationSet": [],
        "CidrBlockAssociationSet": [
            {
                "AssociationId": "vpc-cidr-assoc-*****************",
                "CidrBlock": "10.0.0.0/16",
                "CidrBlockState": {
                    "State": "associated"
                }
            }
        ],
        "IsDefault": false
    }
}
```

## サブネット の作成

```sh
aws ec2 create-subnet --cidr-block 10.0.0.0/24 --availability-zone ap-northeast-1a \
--vpc-id <VPC ID>
```

サブネットの作成に成功すると、以下のような json が返ります。
SubnetId の値を確認しておきます。

```json
{
    "Subnet": {
        "AvailabilityZone": "ap-northeast-1a",
        "AvailabilityZoneId": "apne1-az4",
        "AvailableIpAddressCount": 251,
        "CidrBlock": "10.0.0.0/24",
        "DefaultForAz": false,
        "MapPublicIpOnLaunch": false,
        "State": "available",
        "SubnetId": "subnet-*****************",
        "VpcId": "vpc-*****************",
        "OwnerId": "************",
        "AssignIpv6AddressOnCreation": false,
        "Ipv6CidrBlockAssociationSet": [],
        "SubnetArn": "arn:aws:ec2:ap-northeast-1:************:subnet/subnet-*****************"
    }
}
```

続いて、EC2 起動時にパブリックIPアドレスが自動で割り当たるように、ec2 modify-subnet-attribute コマンドで設定を変更します。

```sh
aws ec2 modify-subnet-attribute --subnet-id <サブネット ID> --map-public-ip-on-launch
```

こちらは、正常終了しても特に json は返ってきません。

## Internet Gateway の作成と割り当て
次に、VPC 内のリソースがインターネットと通信するための出入り口である Internet Gateway(IGW)を作成し、VPC に割り当てます。まずは、ec2 create-internet-gateway コマンドを使用して IGW を作成します。

```sh
aws ec2 create-internet-gateway
```

IGW の作成に成功すると、以下のような json が返ります。
InternetGatewayId の値を確認しておきます。

```json
{
    "InternetGateway": {
        "Attachments": [],
        "InternetGatewayId": "igw-*****************",
        "OwnerId": "************",
        "Tags": []
    }
}
```

そして、作成した IGW を VPC に割り当てます。ec2 attach-internet-gateway コマンドを使用します。

```sh
aws ec2 attach-internet-gateway --internet-gateway-id <value> \
--vpc-id <value>
```

こちらのコマンドも、正常終了しても特に json は返ってきません。


## ルートテーブルの作成、設定

VPC に IGW を割り当てたら、IGW を使用してインターネットと通信できるようにするために、ルートテーブルの作成と設定をします。

まずは、ルートテーブル(カスタムルートテーブル)を作成します。
VPC 作成時のデフォルトルートテーブルはそのままにしておくのがベストプラクティスです。
ルートテーブルの作成には、 ec2 create-route-table コマンドを実行します。

```sh
aws ec2 create-route-table --vpc-id <value>
```

成功すると、以下のような json が返ってきます。
RouteTableId を確認してください。

```json
{
    "RouteTable": {
        "Associations": [],
        "PropagatingVgws": [],
        "RouteTableId": "rtb-*****************",
        "Routes": [
            {
                "DestinationCidrBlock": "10.0.0.0/16",
                "GatewayId": "local",
                "Origin": "CreateRouteTable",
                "State": "active"
            }
        ],
        "Tags": [],
        "VpcId": "vpc-*****************",
        "OwnerId": "************"
    }
}
```

作成したルートテーブルに、IGW へのルートを追加します。
ec2 create-route コマンドを実行します。

```sh
aws ec2 create-route --route-table-id <ルートテーブルの ID> \
--destination-cidr-block 0.0.0.0/0 --gateway-id <IGW のID>
```

正常に成功すると、以下のような json が返ります。

```json
{
    "Return": true
}
```

ルートテーブルにルートを作成したら、最後に、サブネットにルートテーブルを関連付けます。
ec2 associate-route-table コマンドを実行します。

```sh
aws ec2 associate-route-table --route-table-id <ルートテーブルの ID> \
--subnet-id <サブネットの ID>
```

関連付けが正常に行えたら、以下のような json が返ります。

```json
{
    "AssociationId": "rtbassoc-*****************",
    "AssociationState": {
        "State": "associated"
    }
}
```

## セキュリティグループの作成
まず最初に、セキュリティグループをサクッと作ってしまいます。
セキュリティグループは作成時は、インバウンドルールはなし(外からのアクセス不可)、アウトバウンドルールはフルオープンという仕様になっています。
コマンドは ec2 create-security-group を使用します。

```sh
aws ec2 create-security-group --description "Web Servers SG" \
--group-name "sg_web" --vpc-id <VPC ID>
```

次に、CloudFrontのIPアドレス一覧を取得します。
AWS では、https://ip-ranges.amazonaws.com/ip-ranges.json にて、各サービスのエンドポイントで使用している IP アドレスの範囲の一覧を公開しています。
つまり、その IP アドレス範囲を使用してセキュリティグループのインバウンドルールに登録することで、 CloudFront からのアクセスのみを認めるようにできます。

```sh
IPRANGE=`curl https://ip-ranges.amazonaws.com/ip-ranges.json | jq -c '.prefixes[] | select(.service=="CLOUDFRONT") | .ip_prefix'`
```

本記事執筆時点では、125個の登録がありました。

ちなみに、セキュリティグループに登録できるルールのデフォルト個数は、60個なので、1つのセキュリティグループに収めようとすると溢れてしまいます。そのため、上限緩和申請が必要だったのです。
※60個ルールｘ3個のグループにすれば、上限緩和申請をしなくてもよいのですが、シェル芸を楽にするために・・・

取得した IP アドレス範囲を用いて、セキュリティグループのルール作成を行います。

```sh
for ip in ${IPRANGE}; do iplist_tmp=$iplist_tmp,\{CidrIp=$ip\}; done
iplist=`echo ${iplist_tmp} | sed "s/^,//g"`

aws ec2 authorize-security-group-ingress --group-name "sg_web" \
--ip-permissions IpProtocol=tcp,FromPort=80,ToPort=80,IpRanges=[${iplist}]
```

インバウンドルールが正常に作成できると、以下のような json が返ってきます。
指定したIPアドレス範囲の個数だけルールが列挙されます。

```json
{
    "Return": true,
    "SecurityGroupRules": [
        {
            "SecurityGroupRuleId": "sgr-*****************",
            "GroupId": "sg-*****************",
            "GroupOwnerId": "************",
            "IsEgress": false,
            "IpProtocol": "tcp",
            "FromPort": 80,
            "ToPort": 80,
            "CidrIpv4": "***.***.***.***/**"
        },"(以下略)"
    ]
}
```

# まとめ
今回はEC2を使うための前段のネットワーク設定として、VPCやサブネット、セキュリティグループといったリソースを作成、設定しました。コマンドの数も多く、作成や設定の裏で、どんな操作・処理がされているのかがよくわかるのではないかと思います。※AWS CLIやAPIを使えば、どんな処理にも言えますが。。。。

というわけで、この次は、EC2 を立ち上げて、Web サーバとして動作させる予定です。
と、おもいきや・・・

* 今回使ったコマンド
 * ec2 create-vpc
 * ec2 create-subnet
 * ec2 modify-subnet-attribute
 * ec2 create-internet-gateway
 * ec2 attach-internet-gateway
 * ec2 create-route-table
 * ec2 create-route
 * ec2 associate-route-table
 * ec2 create-security-group
 * ec2 authorize-security-group