Rails Tutorialの知識から【ポートフォリオ】を作って勉強する話 #17 VPC環境構築編

# こんな人におすすめ
* プログラミング初心者でポートフォリオの作り方が分からない
* Rails Tutorialをやってみたが理解することが難しい

前回：[#16 線グラフ, Chartkick編](https://qiita.com/aokyo17/items/f5b770e490faa15e6a5b)
次回：[#17.5 MySQL導入編](https://qiita.com/aokyo17/items/36c8231798bd2d46690c)

# 今回の流れ

1. AWS環境を再構築する理由を知る
* 完成のイメージを理解する
* VPC内を構築する

この記事は、**動画を観た時間を記録するアプリのポートフォリオ**です。
今回は**完成したRailsアプリのデプロイ環境をAWS内で再構築**します。
~~ローカル開発環境にはMacを使います。~~（2020/01/21：削除）
**クライアントにはCloud9によるEC2を使います。**

# AWS環境を再構築する理由を知る
これまでは、ポートフォリオのIDEにcloud9を使ってきました。
このcloud9によって開発環境をクラウド上で整えることができました。
しかし、それでは開発環境がどのように構築されたのかが分かりません。

さらに、こんな動画と出会いました。
[ポートフォリオにAWSとDockerとCircleCIを組み込むための学習順序と教材について](https://youtu.be/LT-dXBUnZdI)

> モダンな企業の書類選考を突破するポートフォリオには、
> AWS、Docker、CircleCI（できたら）
> 以上を理解し、組み込むことが得策である。

モダン企業が使うインフラや環境構築には、AWSを使います。
そんなわけでAWS（やDockerなど）を知るために、AWSで環境を再構築します。

# 完成のイメージを理解する
完成したポートフォリオをAWSで動かすためには、2つの環境構築が必要です。

* VPC内の環境構築
* EC2内の環境構築

今回は、2つのうち「VPC内の環境構築」を行います。
VPC内は以下のように構築します。
<img width="649" alt="lantern-vpc.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454653/b3b2b494-b8b0-45d3-c809-ab1fcf294b79.png">
今のところ理解できなくても問題ありません。
実際にVPC内を構築しながら理解しましょう。

# VPC内を構築する
それではVPC内を構築します。
これからAWSで環境を構築するのに、色々な言葉が出てきます。

* VPC
* サブネット
* インターネットゲートウェイ
* ルートテーブル
* セキュリティグループ
* サブネットグループ
* RDS
* パラメータグループ
* EC2
* キーペア
* Elastic IP

これらすべてを設定する必要があります。
環境構築内で作業したい人を、パソコンで作業したいタロウくんと見立てると、それぞれこんなイメージです。

* VPC（＝土地）
* サブネット（＝家族それぞれの部屋）
* サブネットグループ（＝部屋の種類）
* インターネットゲートウェイ（＝玄関）
* ルートテーブル（＝家出ていくときのルール）
* セキュリティグループ（＝部屋の鍵）
* RDS（＝タロウのパソコンのデータ管理）
* パラメータグループ（＝データ管理の設定）
* EC2（＝タロウの部屋のパソコン）
* キーペア（＝パソコンのパスワード）
* Elastic IP（＝パソコンを置いている詳しい位置）

1つずつ設定し、ローカルからEC2に接続できるかを確かめます。

## VPC
まずは自分が作業する場所をインターネット上に確保します。
これがないと何も動かないので、早速設定していきます。

AWSにログイン → AWSマネジメントコンソール『VPC』
画面左のダッシュボード『VPC』 → 『VPCの作成』

```
名前タグ：VPC_for_Lantern（自分のアプリ名）
IPv4 CIDR ブロック：10.0.0.0/16
IPv6 CIDR ブロック：なし
テナンシー：デフォルト
『作成』
```

## サブネット
環境が動くために必要な部屋を用意します。
具体的には、EC2とDB用のサブネット（部屋）を用意します。

画面左のダッシュボード『サブネット』 → 『サブネットの作成』

```
名前タグ：Lantern-Subnet1（自分のアプリ名）
VPC：VPC_for_Lantern
アベイラビリティーゾーン：ap-northeast-1a
IPv4 CIDR ブロック：10.0.0.0/24
『作成』
```

再び『サブネットの作成』

```
名前タグ：Lantern-Subnet2（自分のアプリ名）
VPC：VPC_for_Lantern
アベイラビリティーゾーン：ap-northeast-1c
IPv4 CIDR ブロック：10.0.1.0/24
『作成』
```

## インターネットゲートウェイ
それぞれの通信がVPC内外を通るために、玄関を用意します。
すべての通信をここから通るようにするルールづけには、後述のルートテーブルを使います。

画面左のダッシュボード『インターネットゲートウェイ』 → 『インターネットゲートウェイの作成』

```
名前タグ：Gateway_for_Lantern（自分のアプリ名）
『作成』
```

作成したゲートウェイを選択 → 『アクション』 → 『VPCにアタッチ』

```
VPC：VPC_for_Lantern
『アタッチ』
```

## ルートテーブル
通信を通すルールを作ります。
今回はサブネットがインターネットゲートウェイを通るというルールを作ります。

画面左のダッシュボード『ルートテーブル』 → 『ルートテーブルの作成』

```
名前タグ：Table_for_Lantern（自分のアプリ名）
VPC：VPC_for_Lantern
『作成』
```

作成したルートテーブルを選択 → 下部タブ『ルート』 → 『ルートの編集』

```
『ルートの追加』
送信先：0.0.0.0/0
ターゲット：igw-**（Gateway_for_Lantern）
『ルートの保存』
```

## セキュリティグループ
通信のセキュリティールールを作ります。
外から内を制限するインバウンドルールと、内から外を制限するアウトバウンドルールがあります。

画面左のダッシュボード『セキュリティグループ』 → 『セキュリティグループの作成』

```
セキュリティグループ名：Lantern-SecurityGroup（自分のアプリ名）
説明：SecurityGroup_for_Lantern（自分のアプリ名）
VPC：VPC_for_Lantern
『作成』
```

作成したセキュリティグループを選択 → 下部タブ『インバウンドのルール』 → 『ルールの編集』

```
『ルールの追加』
タイプ：SSH
ソース：カスタム、0.0.0.0/0
『ルールの追加』
タイプ：HTTP
ソース：カスタム、0.0.0.0/0
『ルールの保存』
```

## サブネットグループ
サブネットをグループ化します。
RDS（データベース）作成時にサブネットグループが必要なので、作成します。

AWSマネジメントコンソール『RDS』 → 画面左のダッシュボード『サブネットグループ』 → 『DBサブネットグループの作成』

```
名前：Lantern-DB-Subnet-Group（自分のアプリ名）
説明：DB Subnet Group for Lantern（自分のアプリ名）
VPC：VPC_for_Lantern
『このVPCに関連するすべてのサブネットを追加します』
『作成』
```

## RDS
データベースを作成します。
環境の再構築に伴って、データベースをMySQLに変更します。

画面左のダッシュボード『データベース』 → 『データベースの作成』

```
データベース作成方法を選択：標準作成
エンジンのオプション：MySQL
テンプレート：無料利用枠
DBインスタンスの識別子：Lantern-mysql
マスターユーザー名：任意
マスターパスワード：任意
DBインスタンスサイズ：db.t2.micro
接続;VPC:VPC_for_Lantern
追加の接続設定;サブネットグループ：Lantern-DB-Subnet-Group
追加の接続設定;VPCセキュリティグループ：既存の選択
追加の接続設定;既存のVPCセキュリティグループ：Lantern-SecurityGroup
追加設定；バックアップの保存期間：1日
他、デフォルトでOK
『データベースの作成』
```

## パラメータグループ
パラメータグループを設定します。
RDSが日本の環境に適するように設定するためのものです。

画面左のダッシュボード『パラメータグループ』 → 『パラメータグループの作成』

```
グループ名：Lantern-params-group（自分のアプリ名）
グループ名：DB Parameter Group for Lantern（自分のアプリ名）
『作成』
```

作成したパラメータグループを選択 → 『パラメータグループアクション』 → 『編集』 → パラメータにcharacter_setを入力 → 『パラメーターの編集』

```
character_set_client     値：utf8mb4
character_set_connection 値：utf8mb4
character_set_database   値：utf8mb4
character_set_results    値：utf8mb4
character_set_server     値：utf8mb4
『変更の保存』
※ character_set_filesystemは未入力でOK
```
パラメータにcharacter_setを入力 → 『パラメーターの編集』

```
skip-character-set-client-handshake 値：1
『変更の保存』
```

## RDS用のセキュリティグループを設定する
RDSにもセキュリティグループを設定します。

AWSマネジメントコンソール『EC2』 → 画面左のダッシュボード『セキュリティグループ』 → 作成したセキュリティグループを選択 → 下部タブ『インバウンド』 → 『編集』

```
『ルールの追加』
タイプ：MYSQL/Aurora
ソース：カスタム、sgから始まる作成したセキュリティグループ名
『保存』
```

## EC2
仮想のパソコンを作成します。
アプリを作成やデプロイはここで行います。

AWSマネジメントコンソール『EC2』 → 画面左のダッシュボード『インスタンス』 → 『インスタンスの作成』

```
1. AMIの選択
Amazon Linux 2 AMI（記事公開時は一番上）
『選択』

2. インスタンスタイプの選択
デフォルトでOK
『次のステップ：インスタンスの詳細の設定』

3. インスタンスの詳細の設定
ネットワーク：VPC_for_Lantern
サブネット：Lantern_Subnet1
自動割り当てパブリックIP：有効
終了保護の有効化：チェック
『次のステップ：ストレージの追加』

4. ストレージの追加
『次のステップ：タグの追加』

5. タグの追加
『タグの追加』
キー：Name
値：Lantern-instance（自分のアプリ名）
『次のステップ：セキュリティグループの設定』

6. セキュリティグループの設定
セキュリティグループの割り当て：既存のセキュリティグループを選択する
Lantern-SecurityGroupにチェック
『確認と作成』

7. インスタンス作成の確認
『作成』
```

## キーペア
クライアントからサーバーのEC2に接続するための鍵です。
EC2インスタンスの作成を終えると、自動的に作成画面に移ります。

```
新しいキーペアの作成
キーペア名：lantern-key-pair（自分のアプリ名）
『キーペアのダウンロード』 ※必須！
『インスタンスの作成』
```

このキーペアは後で必ず使うので、無くさないようにします。

## Elastic IP
このままだとサーバーが再起動するたびにパブリックIPが変わります。
それを固定するためにElastic IPを使います。

画面左のダッシュボード『Elastic IP』 → 『インスタンスの作成』 → 『Elastic IPアドレスの割り当て』

```
『割り当て』
```

作成したElastic IPを選択 → 『アクション』 → 『Elastic IPアドレスの関連付け』

```
インスタンス：Lantern-instance
『関連付ける』
```

##Cloud9から接続
キーペアを使って、Cloud9からEC2インスタンスに接続します。
以下は、Cloud9での操作です。

```shell:local
ダウンロードしたpemを、~/.sshに移動
$ scp ~/Downloads/lantern-key-pair.pem ec2-user@IP:/home/ec2-user/.ssh
（ec2-userのところは、自分がCloud9で使用しているEC2ユーザー名）
$ cd ~/.ssh/
$ chmod 400 lantern-key-pair.pem
$ ssh -i lantern-key-pair.pem ec2-user@関連づけたElastic IP
```

出てくる選択肢にyesと答えてenterします。
こういうのが出てくると成功です。

```:server
       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|
```

#補足1：ローカルから接続する場合
ローカルのMacからEC2インスタンスに接続する方法も紹介します。
「Cloud9から接続」を行わず、代わりに以下を行います。
以下は、Macのターミナルでの操作です。

```shell:local
$ mv Downloads/lantern-key-pair.pem .ssh/
$ cd .ssh/
$ chmod 400 lantern-key-pair.pem
$ ssh -i lantern-key-pair.pem ec2-user@関連づけたElastic IP
```

出てくる選択肢にyesと答えてenterします。

# 補足2：参考記事とAWS用語について
RailsアプリケーションをデプロイするまでのAWSに出てくる用語は、以下の記事がわかりやすいので、ぜひ参考にしてみてください。
（@naoki_mochizukiさん、素敵な記事をありがとうございます。）
[(下準備編)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで](https://qiita.com/naoki_mochizuki/items/f795fe3e661a3349a7ce)

他、参考になりました↓
[RailsアプリをAWSで公開する（Rails+Unicorn+Nginx）](https://kapi-travel.com/programing/rails%E3%82%A2%E3%83%97%E3%83%AA%E3%82%92aws%E3%81%A7%E5%85%AC%E9%96%8B%E3%81%99%E3%82%8B%EF%BC%88railsunicornnginx%EF%BC%89/)
[RailsアプリをAWSにイチからデプロイするまでの手順メモ](https://www.codeofduty.me/2018/01/31/railsapp-aws-deploy/)
[RailsアプリをAWS EC2にデプロイする方法(つまづきそうなポイント)](https://qiita.com/a-itabashi/items/bfdf7d92b9a371cbe45e)
[初心者向け：AWS(EC2)にRailsのWebアプリをデプロイする方法 ④](https://qiita.com/iwaseasahi/items/b28f8b91c4638e2c57fd)
[ssh AWSデプロイ時のCloud9での公開鍵の見つけ方](https://teratail.com/questions/210332)
[【scp】Linuxでリモート・ローカル間でファイルを転送するコマンド](https://uxmilk.jp/50946)
[AWSのEC2インスタンスに複数の端末からアクセスする](https://qiita.com/kota9/items/d54a70b542da09b0c099)

---
前回：[#16 線グラフ, Chartkick編](https://qiita.com/aokyo17/items/f5b770e490faa15e6a5b)
次回：[#17.5 MySQL導入編](https://qiita.com/aokyo17/items/36c8231798bd2d46690c)