こんにちは、岩橋聡吾です。

やってみよう!AWSでWEBサーバー環境構築、好評の第一回に続きまして、待望の第二回をやっていきたいと思います。今回は前回作成したVPCとEC2を拡張し、少しづつ耐障害性を意識した実用的な構成を作っていきます。まずはAMIを使って前回作ったEC2のコピーを作るところから始めましょう!

AMIを設定する

これから複数の各種サーバーを設定するに先立って、AMI (Amazon Machine Image) の設定を行いましょう。EC2インスタンスをローンチする度に同じような設定を毎回行うのは煩雑ですが、
これを使ってEC2インスタンスの設定状態をスナップショットとして保存しておくことができます。後で同じEC2が必要になった時にすぐに複製が手に入ります。それでは前回作ったEC2のAMIを作成します。

EC2インスタンスの一覧画面を表示して、複製元を選んで右クリック
p981-ami-01

設定についてはこのままで、イメージを作成します
p981-ami-02

p981-ami-03

AMIの作成には少し時間がかかります。作成が終わるまで待ちましょう。
p981-ami-04

Apacheを設定する

ウェブアプリの構築の要となるウェブサーバーを設定するので、さっき作成したAMIからEC2インスタンスを作成します。

AMIの一覧を表示して、右クリック -> 作成 を選びます。状態がavailableであることを確かめてください。
p981-apache-01

インスタンスタイプは「t2.micro」を選びます。
p981-apache-02

インスタンスの詳細を設定していきます。
IPに設定する内容は選択したネットワーク・サブネットに依存します。
以前作成したAZ・サブネットのIPが10.0.0.0/24 でしたので、4つ目の数字を自由に選ぶことができます(第一回参照)。ここにIPを設定しておくことで、このインスタンスに設定されるプライベートIPを固定できます。

  • 自動割当パブリックIP: 有効
  • プライマリIP: 10.0.0.10

p981-apache-03-01

サブネットにどんなIPを設定していたか忘れてしまったら、VPCダッシュボードからサブネットを選んで確認しましょう。
p981-apache-03-02

インスタンスの名前を設定します。
p981-apache-04

セキュリティーグループ(インスタンスの仮想ファイアウォールなるもの)はとりあえずデフォルトを選んでおきます。もちろん後で正しい設定をします。
p981-apache-05

前回使用したキーペアを使ってインスタンスを立ち上げます。
p981-apache-06

サーバーにSSHログインして最低限のApacheの設定を行います。
コマンドを打ち込んでも何も表示されず、アクセス出来ない場合はセキュリティーグループの設定が悪い場合が考えられます…「22番ポートが開いていない」「アクセスIPを絞っている」等々。

$ ssh -i iwa-sg610.pem ec2-user@52.198.133.68
Last login: Sat Nov 5 05:37:54 2016 from softbank219207110185.bbtec.net

__| __|_ )
_| ( / Amazon Linux AMI
___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2016.09-release-notes/
13 package(s) needed for security, out of 21 available
Run “sudo yum update” to apply all updates.
[ec2-user@ip-10-0-0-10 ~]$
[ec2-user@ip-10-0-0-10 ~]$ sudo yum install httpd
Loaded plugins: priorities, update-motd, upgrade-helper
Resolving Dependencies
–> Running transaction check
—> Package httpd.x86_64 0:2.2.31-1.8.amzn1 will be installed
–> Processing Dependency: httpd-tools = 2.2.31-1.8.amzn1 for package: httpd-2.2.31-1.8.amzn1.x86_64
–> Processing Dependency: apr-util-ldap for package: httpd-2.2.31-1.8.amzn1.x86_64
–> Processing Dependency: libaprutil-1.so.0()(64bit) for package: httpd-2.2.31-1.8.amzn1.x86_64
–> Processing Dependency: libapr-1.so.0()(64bit) for package: httpd-2.2.31-1.8.amzn1.x86_64
–> Running transaction check
—> Package apr.x86_64 0:1.5.1-1.12.amzn1 will be installed
—> Package apr-util.x86_64 0:1.4.1-4.17.amzn1 will be installed
—> Package apr-util-ldap.x86_64 0:1.4.1-4.17.amzn1 will be installed
—> Package httpd-tools.x86_64 0:2.2.31-1.8.amzn1 will be installed
–> Finished Dependency Resolution

Dependencies Resolved

================================================================================
Package Arch Version Repository Size
================================================================================
Installing:
httpd x86_64 2.2.31-1.8.amzn1 amzn-main 1.2 M
Installing for dependencies:
apr x86_64 1.5.1-1.12.amzn1 amzn-main 116 k
apr-util x86_64 1.4.1-4.17.amzn1 amzn-main 87 k
apr-util-ldap x86_64 1.4.1-4.17.amzn1 amzn-main 17 k
httpd-tools x86_64 2.2.31-1.8.amzn1 amzn-main 80 k

Transaction Summary
================================================================================
Install 1 Package (+4 Dependent packages)

Total download size: 1.5 M
Installed size: 3.6 M
Is this ok [y/d/N]: y
Downloading packages:
(1/5): apr-1.5.1-1.12.amzn1.x86_64.rpm | 116 kB 00:00
(2/5): apr-util-1.4.1-4.17.amzn1.x86_64.rpm | 87 kB 00:00
(3/5): apr-util-ldap-1.4.1-4.17.amzn1.x86_64.rpm | 17 kB 00:00
(4/5): httpd-2.2.31-1.8.amzn1.x86_64.rpm | 1.2 MB 00:00
(5/5): httpd-tools-2.2.31-1.8.amzn1.x86_64.rpm | 80 kB 00:00
——————————————————————————–
Total 9.3 MB/s | 1.5 MB 00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Installing : apr-1.5.1-1.12.amzn1.x86_64 1/5
Installing : apr-util-1.4.1-4.17.amzn1.x86_64 2/5
Installing : httpd-tools-2.2.31-1.8.amzn1.x86_64 3/5
Installing : apr-util-ldap-1.4.1-4.17.amzn1.x86_64 4/5
Installing : httpd-2.2.31-1.8.amzn1.x86_64 5/5
Verifying : httpd-tools-2.2.31-1.8.amzn1.x86_64 1/5
Verifying : apr-1.5.1-1.12.amzn1.x86_64 2/5
Verifying : httpd-2.2.31-1.8.amzn1.x86_64 3/5
Verifying : apr-util-ldap-1.4.1-4.17.amzn1.x86_64 4/5
Verifying : apr-util-1.4.1-4.17.amzn1.x86_64 5/5

Installed:
httpd.x86_64 0:2.2.31-1.8.amzn1

Dependency Installed:
apr.x86_64 0:1.5.1-1.12.amzn1 apr-util.x86_64 0:1.4.1-4.17.amzn1
apr-util-ldap.x86_64 0:1.4.1-4.17.amzn1 httpd-tools.x86_64 0:2.2.31-1.8.amzn1

Complete!

設定したApacheのhttpd.confファイルのDocumentRootは「/var/www/html/」としました。
今回はサーバーを立ち上げることが目的なので、最低限のHTMLファイルを作成しましょう。

[ec2-user@ip-10-0-0-10 ~]$ cd /var/www/html/
[ec2-user@ip-10-0-0-10 html]$ sudo touch index.html health.html
[ec2-user@ip-10-0-0-10 html]$ sudo chown ec2-user *.html
[ec2-user@ip-10-0-0-10 html]$ vi index.html

p981-apache-07-01

後述するロードバランサーの使用に必要なファイルも作成します。

[ec2-user@ip-10-0-0-10 html]$ vi health.html

p981-apache-07-02

さぁ、サーバーを立ち上げてみましょう。

[ec2-user@ip-10-0-0-10 ~]$ sudo service httpd start
Starting httpd: [ OK ]

上手くいきました。
これでIPアドレスを直接ブラウザで叩けば上記ファイルが見れるようになります。
p981-apache-08

ウェブサーバーを多重化する準備

堅牢なウェブアプリの構築にはロードバランサーと呼ばれる仕組みが活躍します。

Webアプリのパフォーマンスを上げる手段の1つとして、Webサーバー台数を増やすことがあります。その時に、複数のWebサーバーの負荷状況を見ながら、サイト訪問者をどのWebサーバーに案内すべきかを判断してくれるのがロードバランサーになります。レストランのウェイターのように、お客を一番最初に接客し空いているテーブルに案内してくれるイメージです。

p981-elb-00-01

ちなみに、サーバーの台数を増やすことをスケールアウト、反対に減らすことをスケールインと呼びます。また、サーバーのスペック(1台あたりの性能)を増やすことをスケールアップ、減らすことをスケールダウンと呼びます。

早速、AWSでロードバランサー(Elastic Load Balancing)を設置してサーバーの多重化が出来る構成にしてみましょう。
高機能版のロードバランサーが最近登場しましたが、今回はClassic Load Balancerを選択します。
p981-elb-01
p981-elb-02

ELBの名前・ELBが待受けるポート番号と使用するサブネットを設定します。
p981-elb-03

セキュリティーグループ。今回HTTP-port:80(HTTPS-port:443)以外は使用しません。
p981-elb-04

ヘルスチェックを設定します。ヘルスチェックにはいくつか種類がありますが、今回はHTTP経由でチェックしたいと思います。ELBは予め設定されたファイルの存否とその内容を一定期間毎にチェックします。ファイルが無かったり内容が決められたものでなければチェックNGとして、そのインスタンスをELBの管理下から切り離します。逆に、切り離されたインスタンスが問題無いことを一定回数分確認できたら、そのインスタンスを再びELB管理下に戻します。pingパスには先ほど作成した「health.html」を指定します。
p981-elb-05

ELBにぶら下げるインスタンスを設定します。
p981-elb-06

タグ付けをしてELBを作成します。
p981-elb-07
p981-elb-08
p981-elb-09

ウェブ用セキュリティーグループを再設定します。
せっかくELBを設定したので、これを経由しないWebサーバーへの接続は控えて欲しいですよね。新しくセキュリティーグループを作成・設定しましょう。

      EC2(Webサーバー) インバウンド設定例
  • HTTP – TCP – port:80 – 10.0.0.0/16(同サブネット内(ex.作成したELB)からのアクセスのみ許可)
  • HTTPS – TCP – port:443 – 10.0.0.0/16(同サブネット内(ex.作成したELB)からのアクセスのみ許可)
  • SSH – TCP – port:22 – 10.0.0.0/16(同サブネット内からのアクセスのみ許可)
      ELB(ロードバランサー) インバウンド設定例(前述で設定済)
  • HTTP – TCP – port:80 – 0.0.0.0/0(どこからでもOK)
  • HTTPS – TCP – port:443 – 0.0.0.0/0(どこからでもOK)

p981-elb-10

作成したセキュリティーグループを割り当てます。
p981-elb-11
p981-elb-12

セキュリティーグループの設定が終わってしばらくすると、ELBの配下に「In Service」となったインスタンスが表示されます。
「Out Of Service」のまま変わらない場合はヘルスチェックに失敗しています…セキュリティーグループ(アクセス元の絞り方が正しいか)やELBヘルスチェック(pingパスが正しいか)の設定を見直しましょう。
p981-elb-13

ヘルスチェックはデフォルトで30秒ごとに行われ、10回連続で成功すると「In Service」扱いとなります。
終わるまで待てなければ設定でこれを短縮することも出来ます。
p981-elb-14

「In Service」なインスタンスがELBに1つ以上あることが確認できたら、ELB経由でWebサーバーにアクセスしてみましょう。
ELBのDNS名をコピーして、Webブラウザのアドレス欄にペーストします。
p981-elb-15
p981-elb-16

ここまでの設定で、ELBを経由したWebサーバーへのアクセスが出来るようになりました。
今の時点でWebサーバーを増設しても良いのですが、次回の記事で最後の設定が完了してからWeb01を複製し、ELBにぶら下げます。

SSH踏み台

VPCネットワーク内(のサーバー)に接続するための踏み台サーバーを準備します。この役割は、家の敷地内へ誰でも好き勝手に入ってこられないように、塀を作り・裏口を設けそこに警備員を立たせるようなイメージです。

Apacheの設定で既に使っていましたが、普段あまりインフラに馴染みが無い方でも、時々サーバーにログインして謎の呪文のような文字列を打ち込むことがあるかもしれません。このような場合によく使われるSSH (Secure SHell) というソフトウェアを使って遠隔地に存在するサーバーをメンテナンスすることが出来るのですが、無関係の第三者からアクセスされないように対策されていることは大変重要です。加えてSSHの接続元IPも、会社オフィスや自分の自宅に限定することでサーバーが攻撃に遭う確率を減らすことができます。

AMIからインスタンスを作成します。今回は自動割当パブリックIPは無効にします。
p981-ssh-01

インスタンス名を設定します。
余談ですが、AWS Certificate試験ではSSHの踏み台インスタンスをbastion(【名詞】【可算名詞】1【築城】 稜堡(りようほ).2要塞.3とりで(と見なされるもの[人,場所]))と呼ぶようです。
p981-ssh-02

セキュリティーグループを設定します。特定のIPアドレス(会社オフィスや自分の自宅)からのアクセスのみを受け付けます。
p981-ssh-03

Elastic IP

上記手順でSSH踏み台サーバーを設定しましたが、インスタンスにグローバルIPが設定されていないため、このままでは外部からの接続を受け入れることができません。[自動割当パブリックIP]なる設定があるのですがあり、グローバルIPは割当されるのですが再起動時にそのIPアドレスが変わってしまうという落とし穴があるため実用的ではありません。このままSSH踏み台サーバーを運用するのは不便ですので何とかしましょう。

そこで、Elastic IPの登場です。
Elastic IPの画面を表示し、新しくIPアドレスをゲットしましょう。
p981-ssh-06
p981-ssh-07
p981-ssh-08

ゲットしたElastic IPをSSH踏み台インスタンスに関連付けます。設定時にインスタンスIDが必要になります。
p981-ssh-09
p981-ssh-10-01

インスタンスIDが分からない場合はEC2の画面からコピペしましょう。
p981-ssh-10-02
p981-ssh-11

Elastic IPの設定が出来ました。右下のElastic IPの欄に紐付けたIPが表示されていることを確認します。「52.199.203.168」
p981-ssh-12

実際にElastic IPを使った疎通確認と、Webサーバー個別にSSH接続が出来なくなっていることも確認します。
p981-ssh-13

Route53(DNS)

ELBにアクセスさせる際に、先述のような長大なアドレスではとても覚えきれませんし、メモするのも一苦労です。またシステムやウェブサイトのブランディングには名前も大変重要ですね! このステップでは独自のドメイン名をAWS上で使用できるように設定します。

IPアドレスとドメイン名を紐付ける仕組みとしてDNSサーバーがあります。DNSサーバーへドメインを伺うとそのIPや別のドメインが返ってきて名前解決してくれます。AWSにおいてもDNSを簡単に構築できるようにRoute53が用意されていますが、そもそも「IPアドレスとドメイン名」「ドメイン名とドメイン名」はどのようにして紐付けられるのでしょうか?

アドレスというのは「ルートドメイン」と「サブドメイン」というものに分解できます。
ルートドメイン名の所有者は、サブドメインという形で好きなドメイン名を払い出すことが出来ます。

p981-r53-00-01

例えば、yattemiyou-aws.club というルートドメインがあるとします。このドメインの所有者は、
www.yattemiyou-aws.club や、mail.yattemiyou-aws.club などといったサブドメインを自由に払い出して、それぞれにIPを紐付けすることができるというわけです。

このとき、ドメインがIPアドレスに紐付いているものをAレコード(ドメイン => xxx.xxx.xxx.xxx)。あるドメイン名がそのまた別のドメイン名に紐付いているものをCNAME(ドメイン => ドメイン)などと呼びます。それでは少し前置きが長くなりましたが実際に設定を行いたいと思います。

Route53はレジストラとしての機能も備えているため、ドメイン取得を含めた作業を一貫してAWSで完結させることが可能です。ただしドメイン取得に多少の費用が掛かりますので、今回は予め別で取得しておいたドメインをAWSに紐付けるようにしたいと思います。

また、本記事の内容を試す目的でドメインが必要な方に向けて、無料で取得できるドメイン (2016/12/04現在) Dot tkをご紹介します。

※ 万一、リンク先サイトの利用につき問題が生じた場合、その責任はリンク先サイトが負っていますので利用者ご自身の責任で対処してくださるようお願いいたします。

Route53でyattemiyou-aws.club のHosted Zoneを作成する
p981-r53-01
p981-r53-02

取得したドメインの管理画面で、AWSから与えられたDNSサーバーを設定します。
作成したホストゾーンに関連づいたネームサーバーを控えておきます。
p981-r53-03

ドメイン取得業者 (以下の例はお名前.comです) のドメイン設定でネームサーバーを設定します。
この時、控えておいた4つのサーバーをコピペで打ち込みましょう。
p981-r53-04
p981-r53-05

この手順で取得したドメインをAWSの管理下に置くことをレジストラに伝えます。
それでは、今取得したドメインとELBを紐付けましょう。

先ずはCNAMEでELBに仕向けるレコードを作成します。TTLは300秒位と短めに。
p981-r53-07-01
p981-r53-07-02
www.yattemiyou-aws.club -> iwa-elb-01-731894849.ap-northeast-1.elb.amazonaws.com
を紐付けることが出来ました。(CNAMEの設定ではサブドメインが必要になるため、ルートドメインでのアクセス設定をする場合はAレコードで行います。)

次にAレコードの設定します。
前述で、ドメインとIPアドレスを紐付けるものをAレコードと呼んでいました。が、Route53に限り、IPアドレスの代わりにAWSで使われるAliasを設定する、エイリアスリソースレコードタイプ(AレコードのAWS亜種版なるもの)と呼ばれる独自の設定があります(外からは通常のAレコードとして見られます)。実現したいインフラ構成によってはELBへのアクセスにCNAMEが使えない場合がありますので、Aレコードの設定は是非覚えておいてください。
p981-r53-09
p981-r53-10-01
p981-r53-10-02
www.yattemiyou-aws.club -> (グローバル)IPアドレス
も紐付けることが出来ました。

では、設定したドメインを使ってELBへアクセスしてみましょう。
p981-r53-08

上手くいきました。
これで、Rote53(DNSサーバー) -> ELB(ロードバランサー) -> EC2(Webサーバー) までのパケットの流れを正しく設定することができました。

第2回目の最後に

徐々にWebシステムのインフラらしくなってきましたが、DBサーバーやKVSが設定されていませんので、システムとしてこれを利用するにはまだ力不足です、次回このインフラにデータベースなどの各種ミドルウェアを追加していきます。
ご清覧頂きありがとうございました。
Wedding Parkでは一緒に技術のウエディングパークを創っていくエンジニアを募集しています。
興味のある方はぜひ一度気軽にオフィスに遊びにきてください。

◉シリーズ
・やってみよう!AWSでWEBサーバー環境構築(シリーズ第1回)
・やってみよう!AWSでWEBサーバー環境構築(シリーズ第3回)
・やってみよう!AWSでWEBサーバー環境構築(Lambda|API Gateway|シリーズ第4回)

◉筆者のおすすめ記事
・【DB設計入門|ER図|MySQL】コンビニレシートから学ぶ!データモデリング手法
・【機械学習入門|Python|scikit-learn】結局何ができる?cheat-sheetから解説してみる篇

Join Us !

ウエディングパークでは、一緒に働く仲間を募集しています!
ご興味ある方は、お気軽にお問合せください(カジュアル面談から可)

採用情報を見る