#はじめに
「ELB+EC2(2台)+RDS(マルチAZ)で耐障害性に優れたシステムを構築してみた!RDS編」の続きになります。前回の記事をご覧になっていない方はぜひそちらもご覧ください!
以下に分けて記事を作成しているので、上から順にご覧ください。
・ ELB+EC2(2台)+RDS(マルチAZ)で耐障害性に優れたシステムを構築してみた!VPC編
・ ELB+EC2(2台)+RDS(マルチAZ)で耐障害性に優れたシステムを構築してみた!EC2編
・ ELB+EC2(2台)+RDS(マルチAZ)で耐障害性に優れたシステムを構築してみた!RDS編
・ ELB+EC2(2台)+RDS(マルチAZ)で耐障害性に優れたシステムを構築してみた!ELB編
・ ELB+EC2(2台)+RDS(マルチAZ)で耐障害性に優れたシステムを構築してみた!マルチAZ編
#前提
・コンソールの最低限の操作ができること
・各サービスについての最低限の知識があること
・VPCが作られていること(前回作成したVPCで構築することを前提に記載しています。)
・EC2インスタンスが作成されていること。
#セキュリティグループの作成
ELBを用いて負荷分散を行うわけですが、現在のEC2インスタンスのセキュリティグループは、SSHのみ許可している状態なので、ELBからのアクセスは通さない設定になっています。
なので、前回作成したec2-sgを少し修正します。
今回はELBからHTTPの80番ポートで通信を行います。
EC2 → セキュリティグループ → ec2-sg → インバウンドのルールを編集の順でクリックします。
ルールの追加をクリックし、タイプ「HTTP」の、ソースを0.0.0.0/0にします。
(後ほど修正しますが、一旦仮で値を設定しています。)
#LAMP環境構築
LAMP環境とは、OSをLinux、ウェブサーバをApache HTTP Server、データベースをMySQL、プログラミング言語をPHPとしたサーバ環境のことをいいます。これらの頭文字を取ってLAMPと呼ばれます。
PHPの記述方法が分からない方も多いと思いますので、私の記載内容をコピペすればできるようになっています!ちなみに、私もPHP触ったことないのでコピペしまくりました!(笑)
パッケージインストール
まずはEC2に接続して必要なパッケージをインストールします。
EC2の接続については以前の記事で記載しているので割愛します。
MySQLインストール
まず始めに、EC2インスタンスにはデフォルトでMariaDBがインストールされているためそれを削除します。
$ sudo yum remove mariadb-libs
MySQL公式のyumリポジトリを追加します。
$ sudo yum install https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm -y
MySQLのインストールを行います。
$ sudo yum install mysql-community-server
バージョンを確認します。 8.0以降になってればOKです。
$ mysql --version
mysql Ver 8.0.27 for Linux on x86_64 (MySQL Community Server - GPL)
PHPインストール
PHPのバージョン7.4をインストールします。yum install php
でphpのインストールを行うと、バージョンが古いためデータベースに書き込みができなくなりますので注意。
$ sudo amazon-linux-extras install php7.4
バージョン確認を行います。7.4になっていればOKです。
$ php -v
PHP 7.4.21 (cli) (built: Jul 7 2021 17:35:08) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
Apache HTTP Server
、MySQL Native Driver
をインストールするために、以下のコマンドを実行します。
$ sudo yum install -y httpd php-mysqlnd
##サーバ側の準備
一つ目は初期表示画面を定義したファイルで、二つ目は初期表示画面で入力された内容をMySQLに書き込むファイルです。
ファイルを作成する場所は/var/www/html/配下
になります。なのでディレクトリを移動します。
$ cd /var/www/html/
一つ目のファイルを作成します。viエディタを開きます。
$ sudo vi hello_word.php
a
を押すと左下に-- INSERT --
と表示されると思います。
表示されている状態でないと書き込みができないので注意してください。
INSERTが表示されたら以下のコードをコピペします。
<!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>
コピペが完了したら、esc
を押します。
すると-- INSERT --
が消えるので、:wq
の順に押しEnter
を押します。
詳しくは「vi コマンド」などで検索すると出てきます。
同じ容量で二つ目のファイルを作成します。
$ sudo vi 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>
定義ファイルの作成が完了したのでApachを起動し、起動後に状態確認を行います。
active (running)
と表示されていれば無事起動したことになります。
$ sudo systemctl start httpd
$ sudo systemctl status httpd
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
Active: active (running) since 日 2022-01-09 04:27:08 UTC; 3min 7s ago
Docs: man:httpd.service(8)
Main PID: 3423 (httpd)
Status: "Total requests: 0; Idle/Busy workers 100/0;Requests/sec: 0; Bytes served/sec: 0 B/sec"
CGroup: /system.slice/httpd.service
├─3423 /usr/sbin/httpd -DFOREGROUND
├─3424 /usr/sbin/httpd -DFOREGROUND
├─3425 /usr/sbin/httpd -DFOREGROUND
├─3426 /usr/sbin/httpd -DFOREGROUND
├─3427 /usr/sbin/httpd -DFOREGROUND
└─3428 /usr/sbin/httpd -DFOREGROUND
1月 09 04:27:08 ip-10-0-1-236.ap-northeast-1.compute.internal systemd[1]: Starting The Apache HTTP Server...
1月 09 04:27:08 ip-10-0-1-236.ap-northeast-1.compute.internal systemd[1]: Started The Apache HTTP Server.
次に、インスタンス起動時に自動的にApacheも起動するように設定します。
sudo systemctl enable httpd
で自動起動を有効にしています。
sudo systemctl is-enabled httpd
で状態を確認しenabled
と表示されればOKです。
$ sudo systemctl enable httpd
Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service.
$
$ sudo systemctl is-enabled httpd
enabled
同じ容量でmysqlも自動起動にしておこうと思います。
$ sudo systemctl enable mysqld
ブラウザのURLにEC2インスタンスのパブリックIPアドレスを入力し、以下のような画面が表示されればOKです。以下はApacheが起動していることを確認するテストページになります。
先ほどのURLの後ろに/hello_word.php
とつけてみると以下の画面が表示されるはずです。
ここまで確認できればサーバ側の準備が完了です!次にデータベース側の準備を行います。
##データベース側の準備
MySQLへ接続します。分からない方は以前の記事を参考にしてください。
$ mysql -u admin -p -h <エンドポイント>
Enter password: ###### パスワードを聞かれる
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1680
Server version: 8.0.23 Source distribution
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> ###### これが表示されればOK
以下の4つのコマンドを順に実行していきます。
・create database sample;
sampleという名前のデータベースを作成
・use sample;
使用するデータベース(sample)を選択
・create table words (word varchar(50));
sampleデータベース内にカラムwordをもつwordsテーブルを作成する
・select * from words;
wordsテーブルの中身を確認(この時点では空)
実行結果は以下の通りです。
mysql> create database sample;
Query OK, 1 row affected (0.03 sec)
mysql> use sample;
Database changed
mysql> create table words (word varchar(50));
Query OK, 0 rows affected (0.06 sec)
mysql> select * from words;
Empty set (0.00 sec)
mysql>
次に文字コードの設定変更を行います。
デフォルトでは文字コードは以下のように設定されています。
mysql> SHOW VARIABLES like "char%";
+--------------------------+-------------------------------------------+
| Variable_name | Value |
+--------------------------+-------------------------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| character_sets_dir | /rdsdbbin/mysql-8.0.23.R3/share/charsets/ |
+--------------------------+-------------------------------------------+
この中で、utf8mb4
という文字コードがありますが、PHPからMySQLに送信する文字コードがutf8mb4には対応していない?らしくデータ送信時にエラーが発生してしまいます。(かなりハマりました・・・)
exit
でmysqlを抜けます。
viコマンドでファイルの編集を行います。
$ sudo vi /etc/my.cnf
以下のように修正します。aを押せば編集モードになります。
保存する場合は、esc
→:wp
→Enter
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/8.0/en/server-configuration-defaults.html
[client] #### 追加
default-character-set=utf8 #### 追加
[mysql] #### 追加
default-character-set=utf8 #### 追加
[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove the leading "# " to disable binary logging
# Binary logging captures changes between backups and is enabled by
# default. It's default setting is log_bin=binlog
# disable_log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
#
# Remove leading # to revert to previous value for default_authentication_plugin,
# this will increase compatibility with older clients. For background, see:
# https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_default_authentication_plugin
# default-authentication-plugin=mysql_native_password
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
collation-server = utf8_unicode_ci #### 追加
character-set-server = utf8 #### 追加
サービスの再起動を行います。
$ sudo systemctl restart mysqld
$ sudo systemctl restart httpd
##動作確認
先ほどのWebページに戻り、以下のように入力します。
ホスト名はエンドポイント、データベース名は先ほど作成したデータベース、ひと言はデータベースに格納するデータになります。
DBに接続してデータが格納されているか確認します。データベース接続後に以下のコマンドを実行します。
以下のように表が表示されたらOKです。
mysql> use sample; ### 実行
mysql> select * from words; ### 実行
+------+
| word |
+------+
| test |
+------+
1 row in set (0.00 sec)
mysql>
#EC2インスタンス作成(二つ目)
DBへの接続も確認できたので2つ目のインスタンスを作成します。
もう一つ同じように作成しても良いですが、かなり面倒なのでAMIを取得してインスタンスを作成します。
インスタンスにチェックをつけ、アクション→イメージとテンプレート→イメージを作成の順にクリックします。
イメージ名をsimple web server
などにして作成しておきます。(AMIが利用可能になるまで数分かかります。)
インスタンスの起動をクリックし、インスタンスを作成するわけですが、今回は左タブのマイAMI
を選択し、先ほど作成したAMIを利用します。
インスタンスタイプは1つ目と同じくt2.microを選択し、インスタンスの詳細設定では、test-vpcの中のpubsub-c
を選択します。
ストレージとタグの設定は特に弄らずそのままにします。セキュリティグループは1つ目と同じセキュリティグループを選択します。
先ほど作成したEC2インスタンスのパブリックIPアドレスを利用して、先ほどのWebページを開けたらOKです。(http://54.199.219.3/hello_word.php
みたいな感じです。)
#ターゲットグループの作成
ターゲットグループでは、負荷分散を行うターゲットのグループを作成します。
EC2 → ターゲットグループ → ターゲットグループの作成の順にクリックします。
・ターゲットタイプ
今回はEC2インスタンスに対しての負荷分散なのでインスタンスを指定します。
・ターゲットグループ名
ターゲットグループの名前を定義します。今回は「web-server-tg」です。
・プロトコル:ポート
デフォルトでOKです。
・ヘルスチェックプロトコル
ヘルスチェックを行う際のプロトコルを指定します。今回は「HTTP」
・ヘルスチェックパス
どのパスに対してヘルスチェックを行うかを指定します。
指定されたパスに対してリクエストを飛ばし、ステータスコード200が返って来れば正常と判断されます。今回は「hello_word.php」を指定します。
次にどのインスタンスでグループを作成するか聞かれますので、対象のサーバ2つを選択し「保留中として以下を含める」をクリックします。
#ELBの作成
次はELBを作成します。ELBを用いれば、EC2に対してのリクエストを付加分散することができます。
EC2 → ロードバランサー → ロードバランサータイプの選択の順でクリックします。
ロードバランサタイプはALB(Application Load Balancer)を選択します。
・ロードバランサー名
ロードバランサの名前を設定します。今回は「web-server-alb」にします。
インターネット向けに公開するALBなのでインターネット向けを選択します。
・VPC
ALBを配置するVPCを選択します。test-vpcを選択します。
・マッピング
ALBを配置するサブネットを選択します。pubsub-aとpubsub-cを選択します。
・セキュリティグループ
ALBに割り当てるセキュリティグループを指定します。今回は作成していなかったので、「新しいセキュリティグループの作成」をクリックして新規作成します。
・インバウンドルール
全てのIPアドレスからのHTTPを許可します。
・セキュリティグループ
先ほどのセキュリティグループを割り当てます。(選択欄に出てこない場合は更新ボタンをクリックしてください。)
・リスナーとルーティング
ALBの特定のポートにリクエストが来た際にどのターゲットグループに飛ばすかを指定します。
今回は先ほど作成した「web-server-tg」を選択します。
残りは全てデフォルトの値で作成します。
#動作確認
先ほどのDNS名+hello_word.phpでブラウザで検索します。URLは以下のような感じです。
すると、EC2のIPアドレスを入力しなくても画面が表示されます。何回かページをリロードするとアベイラビリティーゾーンのところが、**ap-norteast-a(もしくはc)**に変わります。
それが確認できれば正常に負荷分散ができているということになります。
#セキュリティグループの修正
最初の段階では仮で設定した、EC2のセキュリティグループの修正を行います。
C2 → セキュリティグループ → ec2-sg → インバウンドのルールを編集の順にクリック
HTTP:0.0.0.0/0のところを修正します。
0.0.0.0/0 → ALBのセキュリティグループに変更(web-server-alb-sg)
#さいごに
以上でELB関連の設定は終了になります。
次にマルチAZ構成の設定を行いますが、RDSが作成されている前提で記載していますので、まだの方はぜひ過去の記事もご覧ください。
最後までご覧いただきありがとうございました。