こんにちは、ロジカル・アーツの井川です。
第4回記事ですね。いよいよ佳境に入ってまいりました。ここまで来ればあと少しです。いつものように全体の大まかな流れを振り返っておきましょう。
- 第1回:VPC、サブネットの作成
- 第2回:EC2インスタンス(Amazon Linux)の作成、接続
- 第3回:RDSインスタンス(MySQL)の作成、接続
- 第4回(今回):ELBの作成とLAMP環境の構築
- 第5回:RDSのMulti-AZ配置
- 補足記事:AWS用語集
今回の作業を終えると、次のような構成が完成します。
AWSのリソースとしては、新しく作成するのはELBだけですが、ついでにLAMP環境の構築も行いたいと思います。LAMP環境についての詳しい説明は本文中で述べます。それでは始めていきましょう。
- ELBとは
- EC2インスタンスのセキュリティグループの設定追加(80ポート開放)
- LAMP環境の構築
- 2つめのEC2インスタンスの作成
- ELBの作成
- AMIの削除方法
- ELBの削除方法
- おわりに
- 参考サイト
ELBとは
ELB(Elastic Load Balancing)とは、受信したトラフィックを複数のターゲット(例えばEC2インスタンス)に自動的に分散させるサービスのことです。いわゆる負荷分散ができます。ELBは次の三種類のロードバランサーをサポートしていますが、今回はClassic Load Balancerを使用します。
- Application Load Balancer
- Network Load Balancer
- Classic Load Balancer
EC2インスタンスのセキュリティグループの設定追加(80ポート開放)
今回の設定では、ELBはHTTPプロトコルで通信するようにします。そのため、EC2に割り当てたセキュリティーグループ(ec2-sg)に80ポートでの通信を許可するように設定する必要があります。
EC2管理ページに移動し、左側の「セキュリティグループ」を選択します。「グループ名」が「ec2-sg」のセキュリティグループを選択し、「インバウンド」タブを選択した状態で「編集」をクリックします。
「ルールの追加」をクリックし、「タイプ」は「HTTP」を選択します。ソースについては、今の時点では任意のトラフックを許可するように「0.0.0.0/0」と入力します。最後に「保存」をクリックします。
これでセキュリティグループの設定は終わりました。
LAMP環境の構築
さて、ここではLAMP環境というものを構築し、ブラウザ上でRDSインスタンスにデータを送信できるようにしたいと思います。
LAMP環境とは
OSをLinux、ウェブサーバをApache HTTP Server、データベースをMySQL、プログラミング言語をPHPとしたサーバ環境のことをいいます*1。これらの頭文字を取ってLAMPと呼ばれます。
今回は次のような機能を実装していきます。
- サーバ側
以下の画面を表示させます。(簡単なものですが、、、) この画面でMySQLにログインするのに必要な情報と、データベース名とひと言を入力して送信ボタンをクリックすれば、入力したひと言がMySQLのテーブルに保存されるようにします。なお、画面にあるアベイラビリティゾーンは、アクセスしたEC2インスタンスのあるアベイラビリティゾーンを表示しています。ロードバランサーによりトラフィックが分散されていることを、この表示が切り替わることによって確認することができます。
- データベース側
「sample」という名前でデータベースを作成します。次にsampleデータベースにwordというカラムをもつwordsというテーブルを作成します。
では実際に作っていきましょう!
必要パッケージのインストール
まずはEC2インスタンスにSSH接続し、次のコマンドを実行します:
sudo yum install -y httpd24 php70 mysql56 php70-mysqlnd
このコマンドでApache HTTP Server、MySQL、PHP ソフトウェアパッケージとMySQL Native Driverがインストールされます。SSH接続の方法は第2回記事を参考にしてください。
サーバ側の準備
ファイルをふたつ準備します。ひとつは先程のHello Wordページ用のファイル(hello_word.php
)で、もうひとつは送信された情報をMySQLに送る用のファイル(test.php
)です。
次のコードをコピーして、 hello_word.php
という名前で保存します。
<!DOCTYPE html> <html> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> <head> <meta charset="utf-8"> <title>Top Page</title> <style type="text/css"> .jumbotron-extend { position: relative; height: 225px; } </style> </head> <body> <header> <nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark"> <a class="navbar-brand" href="hello_word.php">Hello Word</a> </nav> </header> <div class="jumbotron text-center jumbotron-extend"> <div class="container-fluid"> <div> <h1 class="display-4">Hello, word!</h1> <h4> <?php $ch = curl_init("http://169.254.169.254/latest/meta-data/placement/availability-zone"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, True); $resp = curl_exec($ch); echo "アベイラビリティーゾーン:" . $resp; curl_close($ch); ?> </h4> <p class="lead">以下の項目を入力して送信ボタンをクリックすれば、入力したひと言がデータベースに登録されます。</p> </div> </div> </div> <form action="test.php" method="POST"> <div class="form-row justify-content-center"> <div class="form-group col-md-6"> <label>ホスト名</label> <input type="text" class="form-control" name="host" required> <label>ユーザ名</label> <input type="text" class="form-control" name="username" required> <label>パスワード</label> <input type="password" class="form-control" name="passwd" required> <label>データベース名</label> <input type="text" class="form-control" name="dbname" > <label>ひと言</label> <input type="text" class="form-control" name="word"> </div> </div> <div class="row justify-content-center"> <input class="btn btn-primary" type="submit" value="送信"> </div> </form> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script> </body> </html>
こちらのコードは test.php
という名前で保存します。
<!DOCTYPE html> <html> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> <head> <meta charset="utf-8"> <title>Access Page</title> </head> <body class="text-center"> <header> <nav class="navbar navbar-expand-md navbar-dark bg-dark"> <a class="navbar-brand" href="hello_word.php">Hello Word</a> </nav> </header> <?php $host = $_POST["host"]; $username = $_POST["username"]; $passwd = $_POST["passwd"]; $dbname = $_POST["dbname"]; $word = $_POST["word"]; ?> <main role="main"> <div class="jumbotron text-center"> <h1 class="jumbotron-heading"> <?php $link = mysqli_connect($host, $username, $passwd, $dbname); if(!$link) { die("接続失敗 php" . mysqli_connect_error() ); } echo "接続成功"; ?> </h1> <p> <?php $word = mysqli_real_escape_string($link, $word); $result = mysqli_query($link, "INSERT INTO words VALUES (\"$word\")"); if(!$result){ die("クエリ失敗"); } echo $word . "がデータベースに保存されました"; mysqli_close($link); ?> </p> <a href="hello_word.php" class="btn btn-primary my-2">戻る</a> </div> </main> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script> </body> </html>
保存したら、これらをEC2インスタンスに転送します。第2回に引き続いてTera Termを使って説明します。Macでの転送方法は、例えば次を参考にしてください。
Tera Termを起動し、EC2インスタンスに接続した状態で、画面上部の「ファイル」から「SSH SCP」を選択します。1ファイルずつしか送れないことに注意してください。
下の画像の左側の赤枠の部分をクリックし、先程作成したファイルを保存したディレクトリから選択して、「Send」ボタンをクリックします。
ふたつとも送り終わったら、ls
コマンドでファイルが送られていることを確認し、/var/www/html/
ディレクトリにこれらのファイルを移します。ファイルは次のコマンドで移動させることができます:
sudo mv hello_word.php test.php /var/www/html/
Apacheサーバを起動しましょう。これでインターネット経由でアクセスできるようになります。コマンドはsudo service httpd start
です。
続けてsudo chkconfig httpd on
でシステム起動時にApacheサーバも起動するようにします。また、chkconfig --list httpd
でhttpdの設定を確認できます。実行レベル2,3,4,5でon
であればうまくいっています。
ブラウザのアドレスバーにEC2インスタンスに割り当てたElastic IPアドレスを入力します。サーバが起動していれば、次のような画面になるはずです。
入力したアドレスに続いて /hello_word.php
と入力してみてください。以下の画面になれば成功です。
これでサーバの準備が出来ました!
データベース側の準備
次にデータベース側の準備をします。
EC2インスタンス経由でMySQLに接続し、次のコマンドたちを実行してください。接続方法は例によって、第3回記事を参考にしてください。
実行順序 | コマンド | 内容 |
---|---|---|
1 | create database sample; |
sampleという名前のデータベースを作成 |
2 | use sample; |
使用するデータベース(sample)を選択 |
3 | create table words (word varchar(50)); |
sampleデータベース内にカラムwordをもつwordsテーブルを作成する |
4 | select * from words; |
wordsテーブルの中身を確認(この時点では空) |
機能確認
先程のウェブページに戻りましょう。
以下の情報を入力し、送信ボタンをクリックします。うまくいけば、次の画面になるはずです。
項目 | 内容 |
---|---|
ホスト名 | RDSインスタンスのエンドポイント |
ユーザ名 | admin |
パスワード | RDSインスタンス作成時に設定したもの |
データベース名 | sample |
ひと言 | test(何でも可*2) |
実際にデータが保存されていることを確認しましょう。もう一度 select * from words;
を実行してください。次のようになっていれば成功です!
2つめのEC2インスタンスの作成
さて、もう一度同じ設定のEC2インスタンスを作るのは大変ですよね。既存のEC2インスタンスのイメージを作成すれば同じ設定のEC2インスタンスが簡単に作れるようになります。
イメージの作成
EC2管理ページに移動し、左側の「インスタンス」を選択します。 「sample」と名前を付けたインスタンスを選択した状態で、「アクション」プルダウンメニューから「イメージ」 -> 「イメージの作成」をクリックします。
「イメージ名」を「simple web server」と入力し、「イメージの作成」をクリックします。
しばらく待つとイメージが作成されるので、EC2インスタンスを作成しましょう。
EC2インスタンスの作成
基本的な流れは以前EC2インスタンスを作成した時と同じなので、変更点だけ説明します。詳細は第2回記事を参照してください。最初の「AMIの選択」で、左側の「マイAMI」を選択し、作成したイメージ(simple web server)を選択します。
「インスタンスの詳細設定」で、「サブネット」は「sample-public-1c」と名前の付いているものを選択します。
「タグの追加」では、「キー」を「Name」とし、「値」を「sample2」にします。
「セキュリティグループの設定」では、既にEC2インスタンスに割り当てているセキュリティグループ(ec2-sg)を選択します。
これで2つめのEC2インスタンスが作れました!
ELBの作成
それではいよいよELBの作成に取り掛かりましょう。
再びEC2管理ページから、左側の「ロードバランサー」を選択し、「ロードバランサーの作成」をクリックします。
Classic Load Balancerの「作成」をクリックします。
「ロードバランサー名」は「elb」と入力し、「ロードバランサー作成する場所」は「sample」と名前の付いたVPCを選択します。
ページ下部に移動し、「サブネットの選択」で、名前に「public」と付けたサブネットふたつを選択します。その後「セキュリティグループの割り当て」をクリックします。
「新しいセキュリティグループを作成する」を選択し、「セキュリティグループ名」は「elb-sg」とし、「説明」は「Security group for ELB」と入力します。「タイプ」は「HTTP」を選択し、「セキュリティ設定の構成」をクリックします。
そのまま「ヘルスチェックの設定」をクリックします。
「pingパス」を「/hello_word.php」に変更してください。これにより、ELBを経由したトラフィックがこのPHPファイルに向かいます。「EC2インスタンスの追加」をクリックして次の画面に行きます。
「sample」と「sample2」と名前を付けたEC2インスタンスを選択します。それから「タグの追加」をクリックします。
タグは付けずに、「確認と作成」をクリックします。
そのまま「作成」をクリックします。
「閉じる」をクリックします。
「名前」が「elb」のロードバランサーを選択し、「インスタンス」タブを選択します。「ステータス」が「InService」になるまでしばらく待ちます。
「説明」タブを選択し、「DNS名」をコピーします。これがElastic IPアドレスの代わりになります。
ブラウザのアドレスバーに{DNS名}/hello_word.php
と入力すれば(波括弧は不要)、おなじみの画面になります。ブラウザのリロードボタンを何度か押してみてください。アベイラビリティゾーンが切り替わることが確認できると思います。
最後にEC2インスタンスたちに割り当てたセキュリティグループ(ec2-sg)を編集し、作成したELBからの通信のみを許可するように設定します。
EC2管理ページで、左側の「セキュリティグループ」を選択します。「インバウンド」タグを選択し、「編集」をクリックします。
「タイプ」が「HTTP」の「ソース」を、ELBに割り当てたセキュリティグループ(elb-sgと入力すれば出てくるかと思います)にして「保存」をクリックします。
これでELBを経由しないHTTP通信はできなくなります。はじめにしたように、Elastic IPアドレスでアクセスしようとしても繋がりません。
AMIの削除方法
不要なAMIは次のように削除できます。
「EC2管理ページ」から左側の「AMI」を選択した状態で、削除したいAMIを選択します(下の例では「AMI 名」が「simple web server」のもの)。その後、「アクション」プルダウンメニューをクリックし、「登録解除」をクリックします。
次の画面で「次へ」をクリックすれば、AMIが削除されます。
ELBの削除方法
不要なELBは次のように削除できます。
「EC2管理ページ」から左側の「ロードバランサー」を選択した状態で、削除したいロードバランサーを選択します(下の例では「名前」が「elb」のもの)。その後、「アクション」プルダウンメニューをクリックし、「削除」をクリックします。
次の画面で「はい、削除する」をクリックすれば、ロードバランサーが削除されます。
おわりに
お疲れ様でした!ELBの作成自体はそれほど大変でもなかったと思います。LAMP環境のほうは動作確認レベルの簡単なものを作りましたが、興味のある方はいろいろ試してみてください。ただ、今回作ったものはセキュリティ的な考慮は特にしていないので、おわったら削除するようお願いします。次回はRDSをMulti-AZ構成にして、いよいよスケーラブルな構成が完成します。