こんにちは、さくらインターネットの大喜多です。

今回は「故障のための設計(Design For Failure)」を考慮したWebシステムの構築について解説してまいります。

第1回 クラウドインフラのしくみ
第2回 クラウドを支える仮想化
第3回 Linuxコマンドを用いたボトルネック調査
第4回 インターネットを支える技術
第5回 ITインフラ監視入門~Zabbixインストール編~
第6回 ITインフラ監視入門~Zabbix活用編~
第7回 いまどきのインフラ設計のキモ
第8回 Design for FailureなWebシステムの構築

システムの構成とポイント

本記事で構築するシステム構成は以下の図のとおりです。

サーバ名 OS ソフトウェア プライベートIPアドレス
Web Server#1 CentOS7 Apache(httpd)+PHP 10.0.0.201/24
DB Server#1 CentOS7 MySQL 10.0.0.203/24
Web Server#2 CentOS7 Apache(httpd)+PHP 10.0.0.205/24
DB Server#2 CentOS7 MySQL 10.0.0.207/24
デフォルトゲートウェイ(VPCルータ) 10.0.0.1/24

※東京リージョン・石狩リージョン共通です。

構成のポイントは以下のとおりです。

  • 東京リージョンと石狩リージョンに同一構成のインフラを用意しDR(*1)を考慮した設計とする
  • GSLBを用いてリージョンを跨いだロードバランシングを実現する
  • 各リージョンのローカルネットワークはブリッジ接続を用いて相互通信できるようにする
  • 東京リージョンのスイッチにVPCルータを接続し、DB ServerのNAT Gatewayとして使用する
  • MySQLは東京をMaster、石狩をSlaveとしてレプリケーションを構成する

*1:DRはディザスタリカバリ(disaster recovery)の略で、災害などによる被害からの回復措置、あるいは被害を最小限に抑えるための予防措置のことを指します。ここでは東京リージョンと石狩リージョンという地理的に離れた場所に、同じレスポンスを返すWeb Server – DB Serverのセットを用意することで、「被害を最小限に抑えるための予防措置」をおこなっています。

システムの構築はさくらのクラウドを用いておこないますが、さくらのクラウドの操作に関する部分は他記事を参照していただく形式として、本記事では操作手順の解説は省略します。また、Webアプリケーションの例としてWordPressをインストールして動作させますが、WordPressの詳細についても本記事の主題ではないため詳細は割愛します。

サーバの作成 仮想サーバと仮想ディスク – 「さくらのクラウド入門」(1)
ブリッジ接続 さくらのクラウド ドキュメント – ブリッジ接続
GSLB GSLBとロードバランサの併用によるサーバ負荷分散のスケールアウト – 「さくらのクラウド入門」(10)

MySQL5.7のインストール・設定

DB Server#1/#2にMySQL5.7をインストールし、WordPressで使用するための設定をおこないます。

MariaDB関連パッケージ/ファイルの削除

CentOS7ではMariaDBが標準のデータベースになっています。MariaDBに関連するパッケージがインストールされているか確認し、インストールされている場合は削除します。

rpm -qa | grep maria

インストールされている場合の表示例です。

[root@pdns-db ~]# rpm -qa | grep maria
mariadb-libs-5.5.56-2.el7.x86_64

パッケージと関連するディレクトリを削除します。

yum remove mariadb-libs
rm -rf /var/lib/mysql

MySQL5.7のインストール

mysql57-communityリポジトリを利用してMySQL5.7(サーバ)をyumコマンドでインストールします。

rpm -Uvh http://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
yum install --enablerepo=mysql57-community mysql-community-server

OS起動時にMySQLを自動起動するように設定するとともに、MySQLを起動します。

systemctl enable mysqld.service
systemctl start mysqld.service

上記手順でMySQL5.7をインストールすると、rootパスワードは空ではなく、インストール時にtemporary passwordが生成・設定されます。temporary passwordは /var/log/mysqld.log に出力されますので、確認します(grep結果の赤字部分)

[root@pdns-db ~]# grep 'temporary password' /var/log/mysqld.log
2018-03-12T11:13:47.648797Z 1 [Note] A temporary password is generated for root@localhost: *#wydeMW<2lS

MySQLにログインします。

mysql -uroot -p

rootユーザーのパスワードを変更します。

mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '[new password]';
Query OK, 0 rows affected (0.00 sec)

WordPress用の設定

WordPressがMySQLを利用できるようにするための設定をおこないます。

wordpressという名称のデータベースおよびwordpressという名称のMySQLユーザーを作成します。

mysql> CREATE DATABASE wordpress;
mysql> GRANT ALL ON wordpress.* TO 'wordpress'@"%" IDENTIFIED BY '[new password]';
mysql> FLUSH PRIVILEGES;
mysql> \q

Firewalldの設定

Web ServerからDB ServerのMySQLへ接続できるようにするため、MySQLが使用するTCP3306番ポートへの通信を許可します。

firewall-cmd --add-port=3306/tcp --zone=public --permanent
firewall-cmd --reload

Apache(httpd)/PHP/WordPressのインストール

Web Server#1/#2にApache(httpd)/PHP/WordPressをインストールします。

Apache(httpd)/PHPのインストール

yumコマンドでApache(httpd)/PHPをインストールします。下記のコマンドにはApache(httpd)の記載がありませんが、Apache(httpd)はPHPの依存パッケージとしてインストールされます。

yum install php php-mysql

php.iniのバックアップを作成してから、編集します。

cp /etc/php.ini /etc/php.ini.org
vi /etc/php.ini

date.timezoneの部分を以下のように書き換えます。

date.timezone =
→date.timezone = "Asia/Tokyo"

Firewalldの設定

クライアントからWeb Serverへ接続できるようにするため、http通信を許可します。

firewall-cmd --add-service=http --zone=public --permanent
firewall-cmd --reload

Apache(httpd)の起動

OS起動時にApache(httpd)を自動起動するように設定するとともに、Apache(httpd)を起動します。

systemctl enable httpd
systemctl start httpd

MySQL5.7クライアントのインストール

mysql57-communityリポジトリを利用してMySQL5.7(クライアント)をyumコマンドでインストールします。

rpm -Uvh http://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
yum install --enablerepo=mysql57-community mysql-community-client

WordPressのインストール

WordPressをダウンロードして解凍し、/var/www/wordpressディレクトリに展開します。

cd /tmp
yum -y install wget
wget https://ja.wordpress.org/wordpress-4.9.5-ja.tar.gz
tar -zxvf wordpress-4.9.5-ja.tar.gz -C /var/www/
cd /var/www
chown -R apache:apache *

ドキュメントルートを/var/www/wordpressに変更します。httpd.confのバックアップを作成してから、編集します。

cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.org
vi /etc/httpd/conf/httpd.conf

以下のように書き換えます。

DocumentRoot "/var/www/wordpress"
<Directory "/var/www/wordpress">
 AllowOverride All
</Directory>

Apache(httpd)を再起動します。

systemctl stop httpd
systemctl start httpd

Webブラウザでhttp://[Global IP Addr.]/にアクセスし、WordPressのセットアップをおこないます。それぞれ、以下のように対になるよう構成します。

  • Web Server#1 – DB Server#1
  • Web Server#2 – DB Server#2

MySQL5.7のレプリケーション

DB Server#1/#2の間で、MySQL5.7のレプリケーションをおこないます。

レプリケーション設定(Master側)

Master側におこなう設定を記載します。ここではDB Server#1をMasterとします。

/etc/my.cnfを編集します。

vi /etc/my.cnf

末尾に以下のとおり追記します。

## gtid

gtid_mode = on
enforce_gtid_consistency = on

## binary log
log-bin = mysql-bin

## replication
server_id = 1
log_slave_updates

MySQLを再起動します。

systemctl restart mysqld

MySQLにログインします。

mysql -uroot -p

レプリケーション用のユーザーを作成し、レプリケーション用の設定をおこないます。

mysql> CREATE USER 'repl'@'10.0.0.0/255.255.255.0' IDENTIFIED BY '[new password]';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'10.0.0.0/255.255.255.0';
mysql> \q

レプリケーション設定(Slave側)

Slave側におこなう設定を記載します。ここではDB Server#2をSlaveとします。

/etc/my.cnfを編集します。

vi /etc/my.cnf

末尾に以下のとおり追記します。

## gtid

gtid_mode = on

enforce_gtid_consistency = on

## binary log
log-bin = mysql-bin

## replication
server_id = 2
log_slave_updates
read_only = on

MySQLを再起動します。

systemctl restart mysqld

MySQLにログインします。

mysql -uroot -p

レプリケーション用の設定をおこないます。

mysql> CHANGE MASTER TO MASTER_HOST = '10.0.0.203', MASTER_PORT = 3306, MASTER_AUTO_POSITION = 1, MASTER_HEARTBEAT_PERIOD = 60;
mysql> START SLAVE USER = 'repl' PASSWORD = '[new password]';

レプリケーションの動作確認をおこないます。

mysql> SHOW SLAVE STATUS\G

「Slave_IO_Running」と「Slave_SQL_Running」がともに「Yes」となっていれば、正常な状態です。

Slave_IO_Running: Yes
Slave_SQL_Running: Yes

おわりに

いかがでしたでしょうか。従来はデータセンターのロケーションを考慮したシステムの冗長化は、非常に高価な機器を必要としたり、権威DNSサーバの設定変更を自動でおこなうなどの作りこみを必要とするなど、敷居の高いものでした。クラウドであれば、用意されたパーツを組み合わせることで、だれでもこのような冗長構成を組むことができます。

今回で本連載は終了となります。また別の連載にてお会いできるのを楽しみにしています。ありがとうございました。