LoginSignup
1
0

More than 1 year has passed since last update.

【AWS】ELB+EC2(2台)+RDS(マルチAZ)で耐障害性に優れたシステムを構築してみた!ELB編

Last updated at Posted at 2022-01-10

はじめに

「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にします。
(後ほど修正しますが、一旦仮で値を設定しています。)
スクリーンショット 2022-01-03 18.07.52.jpg

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 ServerMySQL 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が起動していることを確認するテストページになります。
スクリーンショット 2022-01-09 13.41.51.jpg

先ほどのURLの後ろに/hello_word.phpとつけてみると以下の画面が表示されるはずです。
スクリーンショット 2022-01-09 13.43.48.jpg

ここまで確認できればサーバ側の準備が完了です!次にデータベース側の準備を行います。

データベース側の準備

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:wpEnter

# 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ページに戻り、以下のように入力します。
ホスト名はエンドポイント、データベース名は先ほど作成したデータベース、ひと言はデータベースに格納するデータになります。

スクリーンショット 2022-01-09 13.56.02.jpg

送信をクリック後次の画面に遷移すれば成功です!
スクリーンショット 2022-01-09 17.14.03.jpg

DBに接続してデータが格納されているか確認します。データベース接続後に以下のコマンドを実行します。
以下のように表が表示されたらOKです。

mysql> use sample;              ### 実行
mysql> select * from words;     ### 実行
+------+
| word |
+------+
| test |
+------+
1 row in set (0.00 sec)

mysql>

EC2インスタンス作成(二つ目)

DBへの接続も確認できたので2つ目のインスタンスを作成します。
もう一つ同じように作成しても良いですが、かなり面倒なのでAMIを取得してインスタンスを作成します。

インスタンスにチェックをつけ、アクション→イメージとテンプレート→イメージを作成の順にクリックします。
スクリーンショット 2022-01-09 17.34.08.jpg

イメージ名をsimple web serverなどにして作成しておきます。(AMIが利用可能になるまで数分かかります。)
スクリーンショット 2022-01-09 17.34.34.jpg

インスタンスの起動をクリックし、インスタンスを作成するわけですが、今回は左タブのマイAMIを選択し、先ほど作成したAMIを利用します。
スクリーンショット 2022-01-09 17.44.53.jpg

インスタンスタイプは1つ目と同じくt2.microを選択し、インスタンスの詳細設定では、test-vpcの中のpubsub-cを選択します。
スクリーンショット 2022-01-09 17.45.44.jpg

ストレージとタグの設定は特に弄らずそのままにします。セキュリティグループは1つ目と同じセキュリティグループを選択します。
スクリーンショット 2022-01-09 17.45.57.jpg

先ほど作成したEC2インスタンスのパブリックIPアドレスを利用して、先ほどのWebページを開けたらOKです。(http://54.199.219.3/hello_word.phpみたいな感じです。)

ターゲットグループの作成

ターゲットグループでは、負荷分散を行うターゲットのグループを作成します。
EC2 → ターゲットグループ → ターゲットグループの作成の順にクリックします。

・ターゲットタイプ
今回はEC2インスタンスに対しての負荷分散なのでインスタンスを指定します。
スクリーンショット 2022-01-09 17.58.22.jpg

・ターゲットグループ名
ターゲットグループの名前を定義します。今回は「web-server-tg」です。

・プロトコル:ポート
デフォルトでOKです。

・VPC
test-vpcを選択します。
スクリーンショット 2022-01-09 17.58.43.jpg

・ヘルスチェックプロトコル
ヘルスチェックを行う際のプロトコルを指定します。今回は「HTTP

・ヘルスチェックパス
どのパスに対してヘルスチェックを行うかを指定します。
指定されたパスに対してリクエストを飛ばし、ステータスコード200が返って来れば正常と判断されます。今回は「hello_word.php」を指定します。
スクリーンショット 2022-01-09 17.59.09.jpg

次にどのインスタンスでグループを作成するか聞かれますので、対象のサーバ2つを選択し「保留中として以下を含める」をクリックします。
スクリーンショット 2022-01-09 17.59.27.jpg

ELBの作成

次はELBを作成します。ELBを用いれば、EC2に対してのリクエストを付加分散することができます。

EC2 → ロードバランサー → ロードバランサータイプの選択の順でクリックします。
ロードバランサタイプはALB(Application Load Balancer)を選択します。
スクリーンショット 2022-01-09 18.08.36.jpg

・ロードバランサー名
ロードバランサの名前を設定します。今回は「web-server-alb」にします。

・スキームスクリーンショット 2022-01-09 18.15.38.jpg

インターネット向けに公開するALBなのでインターネット向けを選択します。
スクリーンショット 2022-01-09 18.09.08.jpg

・VPC
ALBを配置するVPCを選択します。test-vpcを選択します。

・マッピング
ALBを配置するサブネットを選択します。pubsub-apubsub-cを選択します。
スクリーンショット 2022-01-09 18.12.10.jpg

・セキュリティグループ
ALBに割り当てるセキュリティグループを指定します。今回は作成していなかったので、「新しいセキュリティグループの作成」をクリックして新規作成します。
スクリーンショット 2022-01-09 18.14.14.jpg

・インバウンドルール
全てのIPアドレスからのHTTPを許可します。
スクリーンショット 2022-01-09 18.15.38.jpg

・セキュリティグループ
先ほどのセキュリティグループを割り当てます。(選択欄に出てこない場合は更新ボタンをクリックしてください。)

・リスナーとルーティング
ALBの特定のポートにリクエストが来た際にどのターゲットグループに飛ばすかを指定します。
今回は先ほど作成した「web-server-tg」を選択します。
スクリーンショット 2022-01-09 18.19.07.jpg

残りは全てデフォルトの値で作成します。

動作確認

作成後にALBのDNS名をコピーしてください。
スクリーンショット 2022-01-09 18.21.35.jpg

先ほどのDNS名+hello_word.phpでブラウザで検索します。URLは以下のような感じです。
すると、EC2のIPアドレスを入力しなくても画面が表示されます。何回かページをリロードするとアベイラビリティーゾーンのところが、ap-norteast-a(もしくはc)に変わります。
それが確認できれば正常に負荷分散ができているということになります。
スクリーンショット 2022-01-09 18.24.35.jpg

セキュリティグループの修正

最初の段階では仮で設定した、EC2のセキュリティグループの修正を行います。
C2 → セキュリティグループ → ec2-sg → インバウンドのルールを編集の順にクリック

HTTP:0.0.0.0/0のところを修正します。
0.0.0.0/0 → ALBのセキュリティグループに変更(web-server-alb-sg)
スクリーンショット 2022-01-09 18.29.11.jpg

さいごに

以上でELB関連の設定は終了になります。
次にマルチAZ構成の設定を行いますが、RDSが作成されている前提で記載していますので、まだの方はぜひ過去の記事もご覧ください。

最後までご覧いただきありがとうございました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0