ひとつのEC2インスタンスで複数のIPアドレスを使った環境を構築する(EC2 + ENI + unicorn + nginx + rails)

# 背景
- ひとつのEC2インスタンス上に複数の開発環境を作りたい。
- それぞれの環境に違ったIPアドレスを割り当てたい。

間違いありましたら、指摘お願い致します。

# 前提条件
EC2上で動くrailsアプリケーションが構築済みである事。
VPC、EC2、セキュリティグループ、サブネットの設定は既にされているものとして説明します!

# 大まかな手順

今回は環境1、環境2、環境3と3つの環境を作ります。

1. ネットワークインターフェイス（ENI）を設定する
1. 3環境分、EC2のプライベートIPアドレスを用意する
1. 3環境分、グローバルIPアドレスを用意する
1. プライベートIPアドレスとグローバルIPアドレスを紐付ける
1. ネットワークインターフェイスをOSに認識させる
1. nginxの設定(バーチャルホストの設定)


# ネットワークインターフェイス（ENI）の設定

※ネットワークインターフェイスはVPC内で実行中のインスタンスでしか使用できないので注意。

EC2 ＞ ネットワークインターフェイス ＞ ネットワークインターフェイスの作成。
サブネットを選択すると、選択可能なセキュリティグループが表示されます。
選択完了後、[作成する]をクリックします。

![スクリーンショット 2017-02-03 21.12.39.png](https://qiita-image-store.s3.amazonaws.com/0/71267/b8fbed10-f405-73fc-0ca6-f8206f406e2f.png)

作成したネットワークインターフェイスが一覧に表示されます。
作成したネットワークインターフェイスを選択して[アタッチ]をクリックします。
アタッチするEC2インスタンスを選択します。

![スクリーンショット 2017-02-03 21.04.42.png](https://qiita-image-store.s3.amazonaws.com/0/71267/e7cad979-cbd3-d852-047e-a2666e3cc54d.png)

これでネットワークインターフェイスがEC2にアタッチされました！

# プライベートIPアドレスの設定
ネットワークインターフェイスにプライベートIPアドレスを追加します。

作成したネットワークインターフェイスを選択し
アクション ＞ Manage IP Addresses を選択します。

![スクリーンショット 2017-02-03 21.19.14.png](https://qiita-image-store.s3.amazonaws.com/0/71267/c3643353-c2de-721f-b134-055144adb9f0.png)

今回は3つの環境を作成するので「新しいIPの割り当て」を３回クリックします。
「更新する」をクリックすると新しいプライベートIPアドレスが割り当てられます。
プライベートIPアドレスは未入力状態だと自動的に割り当てられます。
特に決まっていない場合は未入力で大丈夫です。

![スクリーンショット 2017-02-03 21.20.11.png](https://qiita-image-store.s3.amazonaws.com/0/71267/63a69869-2ac5-15b7-919e-8d1b4de9a029.png)

環境分のプライベートIPアドレスが取得できました！

# Elastic IPの取得
今回は環境を３つる為、３つのグローバルIPを取得します。


EC2 ＞ Elastic IP ＞ 新しいアドレスの割り当て を選択します。

![スクリーンショット 2017-02-03 20.25.20.png](https://qiita-image-store.s3.amazonaws.com/0/71267/fd7b8e19-bf75-4625-d7d6-d350b7b9f4dd.png)

何も指定するところがないウィンドウが出てきます。
このまま[割り当て]をクリックします

![スクリーンショット 2017-02-03 20.34.30.png](https://qiita-image-store.s3.amazonaws.com/0/71267/d877575f-6b44-1002-c025-89b24e1c4558.png)

一覧に作成した Elastic IPが表示されているので選択します。
アクション ＞ アドレスの関連付け を選択します。

![aaaa.jpg](https://qiita-image-store.s3.amazonaws.com/0/71267/50038d23-0bc7-d252-1d4b-4c3c8724af3e.jpeg)

リソースタイプは「ネットワークインターフェイス」を選択します。
ネットワークインターフェイス、プライベートIPは作成したものを選択します。
作成したIPの数分、作業を繰り返します。

![スクリーンショット 2017-02-03 20.38.11.png](https://qiita-image-store.s3.amazonaws.com/0/71267/54861915-8323-a3b5-6e74-d655749edf36.png)

※起動中のEC2に紐づいていないElastic IPは料金が発生するので注意！

# 休憩

ここまではAWSのコンソール上で操作するので、スムーズにいくかと思います。
ここから先はEC2にコンソールからログインして設定を行います。
サーバの設定に慣れていないと、いろいろハマる・・・と思いますので気を引き締めていきましょう！
(実際にいろいろハマりました)

# ネットワークインターフェイスをOSに認識させる

まずは、先ほど作成した**プライベートIPアドレス**がeth0に追加されている事を確認します。
※今回作成したプライベートIPアドレスを仮に 21.0.1.123, 21.0.1.124, 21.0.1.125 とします。

```console:
$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu qdisc noqueue state UNKNOWN group default qlen 1
　　　　　　　　（省略）
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu qdisc mq state UP group default qlen 1000
    inet 21.0.1.201/24 brd 21.0.1.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet 21.0.1.123/24 brd 21.0.1.255 scope global secondary eth0
       valid_lft forever preferred_lft forever
    inet 21.0.1.124/24 brd 21.0.1.255 scope global secondary eth0
       valid_lft forever preferred_lft forever
    inet 21.0.1.125/24 brd 21.0.1.255 scope global secondary eth0
       valid_lft forever preferred_lft forever
    （省略）
```

プライベートIPアドレスは登録されていますが、OSに認識されていない状態ですので
OSに認識させるためのネットワーク設定ファイルを作成します。

ファイル名ですが「ifcfg-」の後にインタフェース名を記載します。
また名前は一意である必要があります。
今回追加したネットワークインターフェイスはeth0、3つの環境を作成するのでそれぞれ番号を振っています。

```console:ifcfg-eth0:1
$ cd /etc/sysconfig/network-scripts
$ touch ifcfg-eth0:1
$ vi ifcfg-eth0:1
 (ifcfg-eth0:1に以下を設定する)
DEVICE=eth0:1
BOOTPROTO=static
BROADCAST=21.0.0.255
IPADDR=21.0.1.123
NETMASK=255.255.255.0
NETWORK=21.0.0.1
ONBOOT=yes
```
この設定ファイルには**プライベートIPアドレス**を設定します。
同様にifcfg-eth0:2, ifcfg-eth0:3 のファイルも作成します。
設定が完了したらネットワークのサービスを再起動します。

```console:
$ sudo service network reload
Shutting down interface eth0:                              [  OK  ]
Shutting down loopback interface:                          [  OK  ]
Bringing up loopback interface:                            [  OK  ]
Bringing up interface eth0:
Determining IP information for eth0... done.

Determining IPv6 information for eth0... done.
Determining if ip address 21.0.1.123 is already in use for device eth0...
RTNETLINK answers: File exists
Determining if ip address 21.0.1.124 is already in use for device eth0...
RTNETLINK answers: File exists
Determining if ip address 21.0.1.125 is already in use for device eth0...
RTNETLINK answers: File exists
                                                           [  OK  ]
```

上記のように全OKが出れば完了です。
設定に誤りがある場合はエラーが出るので修正します。
下記はエラーの一部です(同じIPアドレスが設定されていると怒られました)

```console:
error in ifcfg-eth0:2: already seen ipaddr 21.0.1.125 in ifcfg-eth0:1
```

# nginxの設定

uniconは環境ごとに起動する必要があります。
listenには**プライベートIPアドレス**を指定します。

```console

$ cd /etc/nginx/conf.d/
$ cat virtual.conf
upstream unicorn {
  server unix:/home/test-user/app/dev1/project/tmp/sockets/unicorn.sock;
}

server {
  listen 21.0.1.123;
  server_name dev1;
  root /home/test-user/app/dev1/project;
  index index.html;
  charset utf-8;
  (省略)
}

upstream unicorn-dev2 {
  server unix:/home/test-user/app/dev2/project/tmp/sockets/unicorn.sock;
}

server {
  listen 21.0.1.124;
  server_name dev2;
  root /home/test-user/app/dev2/project;
  index index.html;
  charset utf-8;
}

upstream unicorn-dev3 {
  server unix:/home/test-user/app/dev3/project/tmp/sockets/unicorn.sock;
}

server {
  listen 21.0.1.125;
  server_name dev3;
  root /home/test-user/app/dev3/project;
  index index.html;
  charset utf-8;
}
```

listenには**プライベートIPアドレス**を指定します。

大事な事なので2回書きました・・・。
グローバルIPアドレスを設定していて、悩みました。
オンプレミスでの運用が長い方はハマりやすいと思います・・・:pray:


設定が完了したらnginxを再起動します。

```console
$ sudo service nginx restart
```

これで完了です！
各環境にアクセスして繋がるか確認してください！