知識0から、AWSのEC2でウェブサーバーを構築するまで

# AWSでサーバーを立てる

![AmazonWebservices_Logo.svg.png](https://qiita-image-store.s3.amazonaws.com/0/71621/e29d22cb-61f0-4b0c-69cc-e5476c576c3f.png)

サーバー関連の知識ゼロの人(僕)が、AWSによるサーバー構築までそれぞれの過程を理解しながら一通りやってみましたので、備忘録的にまとめ。ツールとしてとても便利なだけでなく、ネットワークの仕組みを学ぶ上で非常に勉強になりました。AWS様様m()m。清書・肉付けしてないけど、WIPで公開します。追記予定。


## こんな人にオススメ

* 普段アプリ開発してるけど、自分でサーバーたて方よく知らない。ので、知りたい。
* サーバーなんとなくたてたことがあるけど、ネットワークの仕組みとか工程の意味がわかってない。ので、理解したい。

## 内容

A. ネットワーク構築
B. サーバー構築
C. Webサーバーソフトインストール
D. DBインストール
E. Railsインストール
F. 知っておくと良い周辺知識たち

という構成でサーバー構築まで説明します。僕が普段Railsでアプリ書いてるので、Railsインストールしたりもしましたが、ここは関係ない方は無視してください。

# A. ネットワーク構築

![2000px-AWS_Simple_Icons_Virtual_Private_Cloud.svg (1).png](https://qiita-image-store.s3.amazonaws.com/0/71621/d4a4e0da-667d-8e02-0163-cca77d9cedf2.png)

## 1. VPC作成

1. [ホーム画面] > [VPC] を選択
2. 右上からVPCの操作対象とするリージョンを設定.(どこでも良い.)
3. [Your VPCs] > [Create VPC] でVPC領域を作成.  
  [Name Tag]： VPCにつける名前(なんでも良い.)  
  [CIDR block]： IPアドレス範囲(ここでは10.0.0.0/16のプライベートIPアドレスとする)  

以上をそれぞれ入力すると、指定した条件を持つプライベートなネットワーク空間が作成される。

## 2. サブネット作成

CIDRブロックをさらに小さく分割したCIDRブロックを、サブネット(Subnet)と呼ぶ。今回であれば、「10.0.0.0/16」で作成したCIDRブロックを「/24」の大きさで今度は256分割する、などが一般的な分け方である。

### サブネットに分割する理由

- 物理的な隔離

  片方のサブネットが障害を起こしても、もう片方に影響が出にくくなる。

- セキュリティ上の理由

  サブネットを分けるとそれぞれに対して、別のネットワーク設定ができるため、「経理部のネットワーク」だけを分離して、他の部署からはアクセスできないようにしたい、などを実現することが可能。

### VPC領域を以下のようなサブネットに分割

1. パブリックサブネット(10.0.1.0/24)
	インターネットからアクセスすることを目的としたサブネット。この領域にWebサーバーを設置して、インターネットからアクセスできるようにする。

2. プライベートサブネット(10.0.2.0/24) ← 今回は作らない。
  インターネットから隔離したサブネット。この領域には、データベースサーバーを設置する。
  

### パブリックサブネット作成

1. サブネットを作成
  [Subnets] > [Create Subnet]

2. CIDRブロックを設定
  [Name Tag]：サブネットの名前を入力.
  [CIDR Block]：割り当てるCIDRブロックを入力.今回は「10.0.1.0/24」と入力。


## インターネットと接続する

先ほど作成したパブリックサブネット(10.0.1.0/24)をインターネットと接続する。

### インターネットに接続するための回線を引き込む

サブネットをインターネットに接続するには、「インターネットゲートウェイ(Internet Gateway)」を用いる。これは、「自分のネットワークにインターネット回線を引き込む」というイメージの作業。

1. インターネットゲートウェイを作成する
  [Internet Gateways] > [Create Internet Gateway]

2. VPC領域に結びつける.
  作成したインターネットゲートウェイにチェックをつけてから、[Attach to VPC]をクリック。結びつけるVPC領域を選択。
  
## ルーティング情報の設定

ネットワークにデータを流すためには、「ルーティング情報」と呼ばれる設定が必要で、この設定は、ルーティングテーブルや、ルートテーブルと呼ばれる。
インターネットで使われる「TCP/IP」というプロトコルでは、データを細切れにした「パケット(Packet)」という単位でデータが送受信される。パケットは、様々な「ヘッダー情報」と「データの実体」を含んでいて、ヘッダー情報の一つに「宛先IPアドレス」がある。TCP/IPでは、ネットワーク機器である「ルーター」が、この「宛先IPアドレス」を見ながら、「最も宛先IPアドレスに近い方のネットワーク」へと次々とパケットを転送していき、最終目的地まで到達させる。
「宛先IPアドレスの値が、いくつのときには、どのネットワークに流すべきか」という設定こそが、ルートテーブル。

宛先アドレス  流すべきネットワークの入り口となるルーター

という書式で設定する。宛先アドレスのことは「デスティネーション」、流すべきネットワーク先は、「ネクストホップ」や「ターゲット」という名称で呼ぶ。

### Amazon VPCでルートテーブル設定

サブネットごとにルートテーブルを設定できる。

1. サブネットに割り当てられたルートテーブルのRoute Table IDを確認する。
  ルートテーブルには、Route Table IDという識別子が付けられている。まず[Subnets]をクリックして、Route Table IDを確認する。

2. ルートテーブルの設定値を確認する
  [Route Tables] > 1で確認したRoute Table IDを持つルートテーブルをクリック。[Routes]タブをクリックすると、現在の設定値を確認できる。デフォルトでは、
  
  デスティネーション：ターゲット
  10.0.0.0/16：local
  
  という1項目だけが設定されている。VPC領域のCIDRブロックである「10.0.0.0/16」に含まれるIPアドレス宛のパケットであれば、VPC領域のルーターに接続されている相手への通信なので、VPC領域のルーター(つまり自分のローカル)にパケットを転送するという意味。現在の設定だと、「10.0.0.0/16の範囲外の宛先のパケット」は全て破棄される。
  
###  インターネットに向けて設定

「0.0.0.0/0の範囲の宛先のパケットはインターネットゲートウェイに転送する」という設定をルートテーブルに追加する。「0.0.0.0/0」は全てのIPアドレス範囲を示しているので、「転送先が指定されていない時のデフォルトの転送先」を示す。(デフォルトゲートウェイ)

1. 新しいルートテーブルを作成
  デフォルトのルートテーブルは、全てのサブネットに適用されているため変更したくないので、新しくルートテーブル作成して、サブネットに割り当てる作戦。
  [Route Tables] > [Create Route Table]

2. ルートテーブルをサブネットに割り当てる
  1で作成したルートテーブルを、パブリックサブネットに割り当てる。[Subnet Associations] > [Edit]で割り当てるサブネットを選択。
  
3. デフォルトゲートウェイをインターネットゲートウェイに設定
  Destinationに0.0.0.0/0、Targetにはインターネットゲートウェイを設定した項目を加える。(インターネットゲートウェイはigw-XXX..のやつ。)
  
# B. サーバーを構築する

これまでネットワークの構築をした。物理的な世界で言えば、インターネット接続の契約が済み、ハブやルーターという機器の配線や設定が終わった状態。これから、そのネットワーク上に仮装サーバーを作成する。

## 仮想サーバー構築

![ec2.png](https://qiita-image-store.s3.amazonaws.com/0/71621/38dcb6c9-234e-f79f-bda8-7f57c90cba70.png)


仮想サーバーは、Amazon EC2を用いて作成する。インスタンスと呼ばれる。このインスタンスにwebサーバーソフトをインストールし、webサーバーとして機能させる。インスタンスには、パブリックサブネット内で利用可能な「プライベートIPアドレス」を割り当てる。前章で、パブリックサブネットは「10.0.1.0/24」のCIDRブロックにしたので、「10.0.1.0 ~ 10.0.1.255」のいずれかの値を割り当てることになる。しかし、これらプライベートIPアドレスは、インターネットとの接続には利用できないので、インスタンスを起動する時は、もう一つ「パブリックIPアドレス」を設定するようにする。(このパブリックIPアドレスには、AWSに割り振られているIPアドレスブロックのうち適当なものが使われる。)つまり、作成したインスタンスは「VPC内で通信するためのプライベートIPアドレス」と「インターネットで通信するためのパブリックIPアドレス」の二つを持つ。

### インスタンス作成

[ホーム] > [EC2]

1. リージョンの確認(VPCと同じところに設定)
2. [Instances] > [Launch Instance]
3. AMIを選択(Amaxon Machine Image).OSがインストールされて初期のアカウントの設定まで済んだもの。今回はAmazon Linux AMIを選択。
4. インスタンスタイプを選択。(仮想マシンのスペック)
5. インスタンスの詳細情報を設定。

	1. VPCとサブネット
		インスタンスを配置するサブネットを選択。[Network]で配置したいVPC領域を選択し、[Subnet]で配置したいサブネット(先ほどパブリックに設定したもの)を選択する。

	2. パブリックIPアドレス
		インターネットからこのインスタンスにアクセスできるようにするため、パブリックIPアドレスを付与。[Automatically assign a public IP address to your instances]にチェック。
	
	3. プライベートIPアドレス
		このインスタンスには、プライベートIPアドレスも設定しましょう。「プライベートサブネット」に、先ほど「10.0.1.0/24」を定義しているので、「10.0.1.0~10.0.1.255」のいずれかのIPアドレスを指定できる。
		ここでは、「10.0.1.10」を割り当てる。
		
6. ストレージを設定する。デフォでおk。
7. インスタンスに名前をつける。なんでもいい。
8. セキュリティグループ設定する。
	セキュリティグループはインスタンスに対して、セキュリティを設定する機能。後々説明する。
9. インスタンスを起動。[Launch]をクリック。
10. キーペアを作成してダウンロード。インスタンスにログインする際に必要になる「鍵」。
11. インスタンスの起動。キーペアをダウンロードしたら、[Launch Instances]ボタンをクリックして、インスタンスを起動。[View Instances]をクリックすると、インスタンス一覧画面を表示できる。

## SSHで接続する

起動したインスタンスに、インターネットからログインして操作するのに、SSHというプロトコルを使う。

### パブリックIPアドレスを確認する

インスタンスを見て、Public IPの部分を見れば確認できる。

### SSHで接続する

1. ターミナルを起動
2. `ssh -i keyペアファイル名 ec2-user@パブリックIPアドレス`

## IPアドレスとポート番号

サーバー上でユーザーからのコマンドを受け付けるためのソフトが動いているため、SSHで接続すると、サーバーが応答してユーザー認証され、正しいユーザーであれば、ログインしてコマンドを入力してサーバーを操作できるようになる。sshにたいしてはsshdというプログラムが該当する。

TCP/IPで通信するサーバーなどの機器には、「他のコンピュータと、データを送受信するためのデータの出入り口」が用意されており、これを「ポート」という。ポートは0から65535まである。
ポートのおかげで一つのIPアドレスに対して複数のアプリケーションが同時に通信できる。
ポートには、「相手に届いたことを保証するTCP」と「確認せずに送信する高速なUDP」の2種類が存在する。詳しくは後で説明。

どのポート番号で、どのプログラムが待ち受けているかは、lsofコマンドで確認することができる。

`sudo lsof -i -n -P`

- TCPのポート22
  
  ```
  sshd	1147	root	3u	IPv4	... TCP *:22	(LISTEN)
  ```
  
  のようにssdというプログラムが、`*`　いかなるIPアドレスからの接続も待ち受けている
  
- TCPのポート25

  ```
  sendmail ... TCP 127.0.0.1:25	(LISTEN)
  ```
  接続元は、`*`ではなく、「127.0.0.1」で、自分自身を示しているので、このポートは他のコンピュータからの接続は受け付けないことを意味する。sendmailはメールを送信や転送を行うためのプログラム。
  
## ファイアウォールで接続制限する

IPアドレスや、ポート番号を元にサーバーやネットワークのセキュリティを高めることができる。

### パケットフィルタリング

パケットフィルタリングは、流れるパケットを見て、通過の可否を決める仕組み。IPアドレスを判定して、「特定のIPアドレスを送信元とするパケット以外を除外するようにする」ように構成すれば、接続元を制限できるし、ポート番号を制限すれば、特定のアプリケーションを外部から接続できないように構成できる。

### インスタンスのセキュリティグループ

実世界でパケットフィルタリングを構成するのは、ルーターやサーバー、もしくは専用のファイアウォール機器だが、AWSでは、インスタンスにたいして、構成する「セキュリティグループ」がこの機能を担う。先ほどインスタンスに対して作ったセキュリティグループを見ると、デフォの構成でinboundを見ると、ポート22にたいして全ての通信(0.0.0.0/0)を許可する、という設定があり、それ以外の設定はないことがわかる。デフォルトのこの設定では、webサーバーソフトなどをインスタンスに入れた賭しても、阻まれて通信できないので、ソフトウェアのインストールとともに、セキュリティグループの構成も変更していく。

# C. Webサーバーソフトをインストールする

構築したサーバーにWebサーバーソフトをインストールすることで、Webサーバーとしてインターネットに公開する。

## nginxを入れる

入れる. (このへんWIP)

## ドメイン名と名前解決

IPアドレスとドメイン名をDNSサーバーが変換している。ドメイン名を部分ごとに分割してそれぞれを担当するDNSサーバーがいる感じ。

nslookupコマンドでDNSサーバーの動きを見ることもできる。

# D. DBをインストール

もっとも単純な方法だと、すでに作ったインスタンスにmysqlサーバーをインストールすることもできるし、RDSインスタンスを新しく立てて、EC2インスタンスからそこにアクセスできるようにすることも可能。(このへんWIP)


# E. rails を入れる

入れる。nginxからアプリケーションサーバーにリクエストが割り振られるように設定する。（このへんWIP）

# F. 知っておくといい周辺知識たち

## ELB

- インスタンスにアクセスを振り分ける役目。ただ、外部とつなげ役なので、SSL証明書発行したり、セキュリティ的なところも担う。(aws全体でfirewallを持ってるので、あまり意識されないが。)
- ELBでpublic networkからport 443でhttps受け取って、今度はELBからlocalで、port80でEC2インスタンス上のwebサーバー(アパッチ/Nginx)にリクエスト送るっていう感じ。(ELBでSSL証明書フィルターかけるために、httpsのみ受け付ける443。逆にそこで安全保ってるので、内部ではport80でhttpでやりとりしてる。)
- インスタンスを複数持つことで一つのインスタンスが潰れた際に、生きてる残りのインスタンスを使ったりできるために複数のインスタンス持ってる
- EBSはインスタンスが潰れても残り続けるので、新しくインスタンス立ててそちらにつければ良いって感じで使える。


# S3

- S3を使う理由: EC2のインスタンスが複数存在するところでファイルなどのデータをここのEC2インスタンス上に保存していたらデータの同期取れない。そこで、そういうファイルなどを管理してくれて、複数のEC2インスタンスから見に行く共通のサーバーを別に用意する。それがS3。つまり、全てが共有で持つべきデータでRDSに保存されないデータをS3に持たせるという感じか。
- fluentedといかいう管理してくれる?アプリケーションとかもある(調べる。)

# RDS

- データベースを管理することに特化したインスタンス。
- portがデータベース向けに3306しか最初から空いていないとか、最初からデータベースが入ってるとか。
- 基本的にprivateなsubnetに置かなくても、RDSのpublic access: noとかで、外からアクセスできる設定をオフにしておけば、webサーバーを置くEC2インスタンスと同じsubnet(public)に入れていても問題はない。(そもそもなんでsubnet分けてたのか調べる。)
- データベースに最適かされたインスタンス(詳しい項目は調べればわかりそう。)
- RDSをMaster, Standbyと二つ持つことで、普段はEC2インスタンス(webサーバー用のインスタンス)どちらからもMasterにアクセスする。Masterが死んだときにStandbyに切り替える。Masterが復活した時は、再びmasterを使うように切り替える、ていうことをできるようにするために複数持つ。
- こうして複数のAZにRDSを分けて持つことをMultiAZという。
- マスターからreadonlyのシャーディング用のRDSを作れたりする。

# AZ

- 障害時にインスタンスがまとめて死ぬのを防ぐために、AZを分けるのが一般的。
- AZを分けるとsubnetが自然と分かれる。
- subnetを分ける意味は、いろいろ。異なるアプリケーションでsubnetを分けて、片方から片方へアクセスを制限したり、とか？

# aws-cli

- いちいちsshで入って作業するのが面倒なので、存在。apiでローカルからコマンド打てばインスタンス上の処理できるようになる。(具体的にどういうものが存在するのかは調べる。)

# 公開鍵と秘密鍵

- ec2インスタンス側に、.ssh/以下においてある、authorized_keyが公開鍵。localに置いてる秘密鍵、my-key.pemと照合するために使われる。(つまり、公開鍵、秘密鍵はセットで合言葉のように使われるってことか。)
- localからec2にsshしてそこから他のec2にアクセスする場合などでも、その踏み台にしているec2に直接公開鍵を置きたくない。そういう場合、最初localからsshする時に、ssh -Aとかすれば、そこから他のインスタンスのサーバーにsshして入る時に鍵を持ち越せる。

# いろいろ

- インスタンスにvimrc入れたい時は、みんなが共通に影響受けるところだと、気持ち悪いので、固有の人だけに反映されるように設定するのが一般的。具体的にはググればわかる。
- インスタンスのCPUきつくなってきたら自動でインスタンスの数増やしてくれるauto scalingとかいう技もあったりする。(そういう感じでインスタンスってぽこぽこ作られたいもの。)
- chef、ansibleはどちらも環境構築を楽にするためのツール。

# webサーバー

- アパッチ、Nginxがある理由
- 働き
	- きたhttpリクエストをそのipアドレスなどに応じて振り分けてくれている。役割のキーワードは、Virtual Host, Basic認証、特定のIP弾いたり、ログ出したり、Backlogとったり、jpg/js/cssとか軽いものはアパッチ上にキャッシュしてアプリケーション側に聞きに行かなくても返せるようにしたり、してくれている。(それぞれの役割に関しては調べる。)
- アプリケーションサーバーで同時に走れるプロセス数が決まっていて、そのプロセスがすでに使われている時に、(そのままアプリケーション側に行ったら弾かれてしまうリクエストを)apache上で待たせといてくれたりする。
- そういうリクエストの交通整備をする役割を担っているのがwebサーバー。(責務が切り出されたおかげでアプリケーションサーバーはアプリ的なロジックに集中できる。し、aptcheとかいうOSSとして世界で共有てきているのも切り出しているおかげかs。)
- だからunicorn(appサーバー)とapatcheという組み合わせも普通。(健二さんはnginxよりこの組み合わせが好きらしい)
- nginxは、機能はapatcheより減るが、高速化されたwebサーバー。
- だからwebサーバー一つでアプリケーションサーバーを複数同じサーバー上で走らせることも可能。(キャパが許す限り)

# capistrano

- 普通だったらインスタンスにsshで入り込んで新しい変更いれて、moduleとかもいれて、今走ってる奴止めて...とか？いろいろわちゃわちゃしなきゃいけないところを、capistrano使うと、localからコマンド一つ叩くことで、serverにデプロイしてくれるところまでやってくれる。
- capistranoに書いたコマンドで、sshしてサーバー用のインスタンスに実際は入っている感じ。
- circle CIは、capistrano→circle ci→webサーバーインスタンスの順にアクセスしてる。circleCIのためにport開けて、閉じて、みたいなことをしている。
- capistrano使って、インスタンスがgitにアクセスする場合にも、インスタンスがgitの秘密鍵持たなくても良いわけは、localで叩いた時に、上のssh -Aのような感じで、localの持ってる秘密鍵の情報を持ち越して持てる、みたいなことをしているからである。
- 他の新しいEC2インスタンス作って、そのインスタンスにデプロイまでセットすることを目指してcapistrano書くといいかも。gitから持ってきて...みたいなことができるはず。(課題)
- capistranoの設定にインスタンス登録しといて、それぞれのインスタンスへデプロイしに行くみたいな感じ。

# tmux

http://kanjuku-tomato.blogspot.jp/2014/02/tmux.html

普通にやってると、sshの通信が一定時間で切れてしまい、そのたびに新しく通信しなくてはいけないのが手間なので、常につなげるようにしてくれるもの。

# Route53

- 名前解決

# やるといいこと

- ELB使う
- capistrano
- RDS
- chefで環境構築

# オススメの書籍

* [Amazon Web Services 基礎からのネットワーク&サーバー構築](http://www.amazon.co.jp/Amazon-Web-Services-%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E3%81%AE%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF-%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E6%A7%8B%E7%AF%89/dp/4822262960/ref=pd_sim_14_3?ie=UTF8&refRID=0Q0PESF1NAF7E25RGRS1) この本、スーパーわかり易い良書です。知識ゼロからAWS勉強したい、使いたいという方に強くオススメします。