AWSでウェブアプリケーション環境構築：⑤webサーバをプライベートサブネットに配置し、メンテナンス用踏み台サーバを構築

# はじめに
これはシリーズ記事の中の1つです。

[AWSでウェブアプリケーション環境構築：⓪概要](https://qiita.com/minato-naka/items/ddb5f5301f9f590cdcbf)
[AWSでウェブアプリケーション環境構築：①EC2インスタンスにwebサーバを構築](https://qiita.com/minato-naka/items/c21e4d53db7a720f8fdd)
[AWSでウェブアプリケーション環境構築：②RDSでDBを作成し、Laravelサンプルアプリを動かす最小構成を構築](https://qiita.com/minato-naka/items/03f9dbd09eb3919a501f)
[AWSでウェブアプリケーション環境構築：③ロードバランサーを作成し、webサーバを冗長化する](https://qiita.com/minato-naka/items/396e2a25ec9a94840a67)
[AWSでウェブアプリケーション環境構築：④ElastiCacheのRedisを作成し、セッション共有可能にする](https://qiita.com/minato-naka/items/76cd5f660d987d34f7be)
[AWSでウェブアプリケーション環境構築：⑤webサーバをプライベートサブネットに配置し、メンテナンス用踏み台サーバを構築](https://qiita.com/minato-naka/items/406c2f247c0d29a93665)
**↑↑↑現在の記事↑↑↑**
[AWSでウェブアプリケーション環境構築：⑥Route53を利用して独自ドメインでアクセス可能にする](https://qiita.com/minato-naka/items/6f29694c1540f04dedb2)
[AWSでウェブアプリケーション環境構築：⑦ACMを利用してHTTPS通信可能にする](https://qiita.com/minato-naka/items/1a4f03e85857b8f61c4f)
[AWSでウェブアプリケーション環境構築：⑧サーバ負荷に応じてwebサーバがオートスケーリングする仕組みを構築](https://qiita.com/minato-naka/items/c0fab5d9fbb1cce68ac9)


# 前回まで
![4.png](https://qiita-image-store.s3.amazonaws.com/0/297693/07b1a59c-1edb-5aa7-3443-b5f3dc5bfe83.png)

前回はElastiCacheのRedisを作成し、
2台構成のwebサーバでセッション共有できる仕組みを構築しました。

# 今回構築する環境
![5.png](https://qiita-image-store.s3.amazonaws.com/0/297693/91fb78df-c041-9dcf-e4f8-706caf7a67d7.png)

セキュリティのレベルを上げるために、
webサーバをプライベートサブネットに移動します。

また、それに伴い必要になる踏み台サーバとNATゲートウェイを作成します。
※踏み台サーバ、NATゲートウェイが必要な理由は後述します

# webサーバをプライベートサブネットに移動する
プライベートサブネットに**移動する**と書きましたが、
実際にはインスタンスをプライベートサブネットに作り直します。

## 既存webサーバのAMIを取得
作り直すインスタンスは、
Apache、PHP、Laravelなどの設定を
既存のwebサーバと同一にして作成したいため、
まずは既存webサーバのAMIを取得します。

EC2インスタンスの一覧で以前作成した[laravel-sample-ec2-web-a]をチェックし、
ページ上部の[アクション]→[イメージ]→[イメージの作成]をクリック。

以前、[laravel-sample-ami-web]という名前のAMIを作成しているので、
今回は[laravel-sample-ami-web-2]という名前でAMIを作成します。
<img width="960" alt="screencapture-us-east-2-console-aws-amazon-ec2-v2-home-2019-01-31-17_44_21.png" src="https://qiita-image-store.s3.amazonaws.com/0/297693/211adc10-4cf4-4635-5885-0cb8e4947f7e.png">

## プライベートサブネットにwebサーバを作成
これまでの記事でEC2インスタンスの作成方法は何度か解説しているため、
今回は重要ポイントのみ解説します。

マネジメントコンソールの[EC2]のページの
サイドメニューの[インスタンス]をクリックし、
上部にある[インスタンスの作成]ボタンをクリック。

### AMI の選択
[マイAMI]から先ほど作成した[laravel-sample-ami-web-2]を選択します。

### インスタンスタイプの選択
いつも通りt2.microです。

### インスタンスの設定
[サブネット]で[laravel-sample-subnet-private-a]を選択してください。
それ以外は以前と同じ設定で進めます。

### ストレージの追加
デフォルト設定のまま進めます。

### タグの追加
Nameタグに[laravel-sample-ec2-web-private-a]を設定します。

### セキュリティグループの設定
[laravel-sample-sg-web]を選択します。

### 確認
最後のキーペア選択で[laravel-sample-key-pair]を選択して
インスタンスを作成します。

下記のみ注意して同じように2台目のwebサーバも作成します。
・[サブネット]で[laravel-sample-subnet-private-b]を選択する
・Nameタグに[laravel-sample-ec2-web-private-b]を設定する

これでプライベートサブネットにwebサーバが2台作成できました。

## パブリックサブネットのwebサーバを削除
パブリックサブネットにある既存のwebサーバ2台は
もう不要なため削除します。

インスタンスの一覧で
[laravel-sample-ec2-web-a]と
[laravel-sample-ec2-web-b]をチェックし、
ページ上部の[アクション]→[インスタンスの状態]→[終了]をクリック。

しばらく待ってインスタンスのステータスが[terminated]になれば削除完了です。
その後さらに時間がたてばインスタンスの一覧に表示されなくなります。

## ALBターゲットグループに登録
プライベートサブネットに作成したwebサーバをALBのターゲットグループに登録します。

ターゲットグループの一覧で以前作成した[laravel-sample-target-group]をチェックし、
ページ上部の[アクション]→[インスタンス/IPターゲットの登録と登録解除]をクリック。

表示された画面下部のEC2インスタンス一覧に、
先ほど作成した[laravel-sample-ec2-web-private-a]と[laravel-sample-ec2-web-private-b]があると思うので
2つをチェックし[登録済みに追加]をクリックします。

下記の状態にできたら[保存]をクリックします。
<img width="960" alt="screencapture-us-east-2-console-aws-amazon-ec2-v2-home-2019-01-31-18_05_13.png" src="https://qiita-image-store.s3.amazonaws.com/0/297693/ce6b61ca-e796-5fff-b349-6207760c046d.png">

## 動作確認
ALBのエンドポイントをブラウザに入力しアクセスします。

Laravelサンプルアプリが表示され、
各操作も行えれば正常に構築できています。

# 踏み台サーバを構築する
webサーバをプライベートサブネットに配置した状態で
Laravelサンプルアプリは正常に動作していますが、
この状態では問題があります。

webサーバはプライベートサブネットにあるため
直接SSH接続することができません。
（作成したインスタンスのパブリックIPに対してSSH接続を試してみてください）

この状態ではサーバにトラブルがありログを確認したいときや
Apacheなどの設定を変更したときに困ります。

そのためにパブリックサブネットに踏み台サーバを作成し、
その踏み台サーバからwebサーバに対してSSH接続できるように設定します。

## EC2インスタンスの作成
まずは踏み台サーバとなるEC2インスタンスを作成します。

### AMI の選択
Amazon Linux 2のAMIを選択します。

### インスタンスタイプの選択
t2.microを選択します。

### インスタンスの設定
[サブネット]で[laravel-sample-subnet-public-a]を選択します。
[自動割り当てパブリック IP]は[有効]にします。

それ以外はデフォルト設定のままで進みます。

### ストレージの追加
デフォルト設定のままで次に進みます。

### タグの追加
Nameタグに[laravel-sample-ec2-bastion]を設定します。

### セキュリティグループの設定
[セキュリティグループの割り当て]で[新しいセキュリティグループを作成する]を選択し、
下記のように設定します。
<img width="960" alt="screencapture-us-east-2-console-aws-amazon-ec2-v2-home-2019-01-31-18_34_16.png" src="https://qiita-image-store.s3.amazonaws.com/0/297693/b3c52ea8-ae52-5b3a-a4da-c1e5f8a378aa.png">

自分のIPからのSSH通信のみ許可します。

### 確認
設定内容を確認し、
最後のキーペア設定画面で[laravel-sample-key-pair]を選択します。
※今回は踏み台サーバとwebサーバで同じキーペアを使用していますが、本来は別々のキーペアを利用した方がいいです

最後に[インスタンスの作成]ボタンをクリックしたら作成完了です。

## 鍵ファイルの設定
次に、作成した踏み台サーバからwebサーバにSSH接続するために、
SSH鍵ファイルの設定を行います。

### 鍵ファイルの設置
踏み台サーバの
`/home/ec2-user/.ssh/`
の配下に、
[laravel-sample-key-pair.pem]の秘密鍵ファイルを置きます。

### 鍵ファイルのパーミッション変更
いま設置した鍵ファイルはこのままでは使用するときに
パーミッションエラーになっていますので、
パーミッションを変更します。

踏み台サーバにSSH接続して下記の設定をします。

```shell
#鍵ファイルのパーミッション変更
chmod 600 /home/ec2-user/.ssh/laravel-sample-key-pair.pem
```

これで踏み台サーバの必要な設定は完了です。

## webサーバのセキュリティグループ設定変更
webサーバのセキュリティグループは現在
・ALBからのHTTP接続
・自分のIPからのSSH接続
を許可している状態です。

このSSH接続を許可する接続元を踏み台サーバに変更します。

[EC2]のページの
サイドメニューの[セキュリティグループ]をクリックし、
以前作成した[laravel-sample-sg-web]をチェックし、
ページ上部の[アクション]→[インバウンドルールの編集]をクリック。

SSH接続の[ソース]を先ほど作成した[laravel-sample-ec2-bastion]の**プライベートIPアドレス**に変更します。
<img width="590" alt="screencapture-us-east-2-console-aws-amazon-ec2-v2-home-2019-01-31-18_54_20.png" src="https://qiita-image-store.s3.amazonaws.com/0/297693/85029e38-f48b-8c15-c03b-5ea2c89dc87c.png">


## 接続確認
これで踏み台サーバからwebサーバにSSH接続するための設定は完了したので、
実際に試してみます。

まず踏み台サーバにSSH接続し、
下記のコマンドを実行します。

```shell
#webサーバにSSH接続
ssh -i /home/ec2-user/.ssh/laravel-sample-key-pair.pem ec2-user@{webサーバのプライベートIP}
```

webサーバ2台ともこの方法でSSH接続できれば、
踏み台サーバの設定は正しく完了しています。

これでwebサーバのログを確認したり、
Apache設定を変更したりする作業はできるようになりました。

しかし、この状態ではまだ問題があります。
webサーバで下記のコマンドを実行してみてください。

```shell
#googleにcurlリクエスト
curl https://www.google.co.jp/
```

その結果、time outになります。
webサーバはプライベートサブネットにありますが、
プライベートサブネットはインターネットゲートウェイへのルーティングが存在しないため、
webサーバからインターネット外部向けに通信が通っていない状態です。

この状態では例えば
webサーバに新しいミドルウェアを外部からインストールしたり
外部APIを利用することができません。

これを解決するためにNATゲートウェイを利用します。

# NATゲートウェイを作成する
NATゲートウェイとは、
プライベートサブネットにあるサーバからインターネットに接続するための
中継サーバになってくれるものです。

サーバ構成図にあるこれです。
![aws laravelサンプル-ページ8.png](https://qiita-image-store.s3.amazonaws.com/0/297693/06bcd6c7-87e0-52d6-c498-5e295c792d82.png)

NATゲートウェイを使って
プライベートサブネットからインターネットに接続できる状態にするには、
NATゲートウェイを作成し、
プライベートサブネットのルートテーブルにNATゲートウェイへのルーティングを追加する必要があります。

NATゲートウェイについてはこのような記事で
わかりやすく解説されています。
https://qiita.com/TK1989/items/5d9bd5d49708c02dff3f

## NATゲートウェイの作成
[VPC]のページの
サイドメニューの[NATゲートウェイ]をクリックし、
上部にある[NATゲートウェイの作成]ボタンをクリック。

[サブネット]は[laravel-sample-subnet-public-a]を選択します。
[Elastic IP 割り当て ID]は、ElasticIPをまだ持っていないので、[新しいEIPの作成]ボタンをクリックしてください。
![screencapture-us-east-2-console-aws-amazon-vpc-home-2019-01-31-18_14_13.png](https://qiita-image-store.s3.amazonaws.com/0/297693/32bf8bb6-3804-ee06-219f-bf922343479a.png)

[NATゲートウェイの作成]ボタンをクリックすると
NATゲートウェイが作成されます。

## プライベートサブネットのルーティング変更
ルートテーブルの一覧で以前作成した[laravel-sample-route-table-private]をチェックし、
ページ上部の[アクション]→[Edit routes]をクリック。

このように、
[Destination] = [0.0.0.0/0]
[Target] = {先ほど作成したNATゲートウェイのNATゲートウェイID}
のルーティングを追加します。

## 動作確認
これでNATゲートウェイの設定が完了し、
webサーバからインターネットに接続できる状態になっているので確認します。

先ほどと同じようにwebサーバで下記のコマンドを実行してみてください。

```shell
#googleにcurlリクエスト
curl https://www.google.co.jp/
```

先ほどはtime outになりましたが、
今回は正常にレスポンスが返却されました。

これでwebサーバをプライベートサブネットに配置し
メンテナンス用の踏み台サーバ、NATゲートウェイを作成する作業がすべて完了です。

# 次回
現在は、構築したLaravelサンプルアプリにアクセスする際は
ALBに割り振られたDNS名を利用しています。

ですが実際にサービスとして公開する場合は
独自ドメインで公開したいと思います。

次回はRoute53を利用し、
このLaravelサンプルアプリを独自ドメインでアクセスできるようにします。

[AWSでウェブアプリケーション環境構築：⑥Route53を利用して独自ドメインでアクセス可能にする](https://qiita.com/minato-naka/items/6f29694c1540f04dedb2)