アリババクラウドECSとWordPressを利用したサーバークラスタの設定～パート２

PHP7とNginxをインストールしてLEMPスタックのインストールを完了し、各ノードやロードバランサーなどにNginxを設定します。

*本ブログは英語版からの翻訳です。オリジナルは[こちら](https://www.alibabacloud.com/blog/setting-up-a-server-cluster-for-enterprise-web-apps--part-2_584446)からご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。*

[Alibaba Cloud Tech Share](https://www.alibabacloud.com/campaign/techshare?spm=a2c65.11461447.0.0.4f62383cvBfpkK) 執筆者、 Jeff Cleverley。

このシリーズのチュートリアルでは、高トラフィックの Web アプリケーションや企業のビジネスサイトに適した水平方向にスケーラブルなサーバクラスタをセットアップします。クラスタは 3 台の Web アプリケーションサーバと 1 台のロードバランシングサーバで構成されています。クラスタ上にWordPressを設定してインストールしますが、実際のクラスタ構成はPHPベースのWebアプリケーションに適しています。各サーバーは LEMP スタック（Linux、Nginx、MySQL、PHP）を実行します。


このチュートリアルを完了するには、シリーズの[最初のチュートリアル](https://www.alibabacloud.com/blog/setting-up-a-server-cluster-for-enterprise-web-apps--part-1_584040?spm=a2c65.11461447.0.0.4f62383cvBfpkK)を完了している必要があります。[最初のチュートリアル](https://www.alibabacloud.com/blog/setting-up-a-server-cluster-for-enterprise-web-apps--part-1_584040?spm=a2c65.11461447.0.0.4f62383cvBfpkK)では、3台のノードサーバと負荷分散用のサーバをプロビジョニングしました。ノードサーバでは、データベースとWebアプリケーションのファイルシステムのレプリケーションを設定し、サーバー間のリアルタイムのデータベース同期を提供するために、MySQLの代替として[Percona XtraDB Cluster](https://www.percona.com/software/mysql-database/percona-xtradb-cluster?spm=a2c65.11461447.0.0.4f62383cvBfpkK) Databaseを使用しました。またWeb アプリケーションファイルのレプリケーションとサーバ間の同期には、[GlusterFS](https://www.gluster.org/?spm=a2c65.11461447.0.0.4f62383cvBfpkK) 分散ファイルシステムをセットアップしました。

このチュートリアルでは、PHP7とNginxをインストールすることで、LEMPスタックのインストールを完了させます。次に、それぞれのノードとロードバランサーに Nginx を設定し、ドメインのロードバランサーに SSL 暗号化証明書を発行し、最後に WordPress をインストールして分散クラスタ全体で動作するようにします。

このチュートリアルが終わる頃には、以下のようなクラスタアーキテクチャになっているでしょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/0fab96a0-e7f3-9b1a-4be4-94b494c87934.png)



<ロードバランサを搭載した3ノードサーバクラスタを均等にバランスよくさせています>

最後のチュートリアルでは、Nginx Caching、管理用と公開サイトアクセス用のロードバランスに特化したノードの作成、そして最後にデータベースクラスタと分散ファイルシステムのハード化を含む、より高度なクラスタアーキテクチャの構成を見ていきます。

もしスーパーユーザを使用している場合は、必要に応じてコマンドの前にsudoコマンドを追加することを忘れないでください。私はまた、テストドメイン yet-another-example.com を使用しますが、コマンドを発行する際には、これをあなたのドメインに置き換えることを忘れないでください。

コマンドでは、私のサーバのプライベートとパブリックのIPアドレスを使用します。

このチュートリアルは最初のチュートリアルに直接従っているので、手順の順序はそれに応じて番号が付けられています。ステップ1から3は最初のチュートリアルにあります。このチュートリアルはステップ4から始まります。

###ステップ4: NginxとPHPをインストールする
**各ノードにNginxをインストールし、ロードバランサーをインストールします。**
全てのノードで以下のコマンドを実行してNginxをインストールします。

`# apt-get install nginx`

ロードバランサーにログインします。

`ssh root@load_balancers_ip_address`

そして、ロードバランサーにもNginxをインストールします。

```
# apt-get update
# apt-get install nginx
```

**各ノードにPHPをインストール**
各ノードには、PHPとWordPressの実行に必要な最も一般的なパッケージをインストールします。

```
# apt-get install php-fpm php-mysql
# apt-get install php7.0-curl php7.0-gd php7.0-intl php7.0-mysql php-memcached
php7.0-mbstring php7.0-zip php7.0-xml php7.0-mcrypt
# apt-get install unzip
```

###ステップ5：WordPressのファイルをダウンロードする
すべてのウェブアプリケーションのルートディレクトリを `glustervolume` の一部としてマウントしているので、WordPress ファイルを 1 つのノードにインストールするだけで、クラスタ全体に複製されます。

システム上に WP-CLI があると常に便利なので、それをインストールし、WP-CLI コマンドを使って最新バージョンの WordPress をマウントされたディレクトリにダウンロードします。

**WP-CLI のインストール**
ノード1 で以下のコマンドを実行して WP-CLI をインストールします。

PHPアーカイブをダウンロードします。

`# curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar`

実行可能にして「PATH」に移動させます。

```
# chmod +x wp-cli.phar
# mv wp-cli.phar /usr/local/bin/wp
```

動作しているかテストします。

`# wp —info`

これでターミナルにWP-CLIのインストールの詳細を示す出力が表示されるはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/6e9969aa-a8b5-769e-5e0b-6eb3a38fd01b.png)

＜WP-CLIをインストールして動作をテストします＞

各ノードでWP-CLIを利用できるようにしたい場合は、各ノードで上記の作業を繰り返します。この連載が終わる頃にはノード1が管理ノードとして設定されているので、このノードにWP-CLIを設定しておくことだけが本当に重要になってきます。

**WordPressファイルのダウンロード**
ノード1上のディレクトリをWebアプリケーションのルートディレクトリとして使用するマウントディレクトリに変更し、WordPressのコアファイルをダウンロードします。

WP-CLI を root として使用するには、'--allow-root' パラメータを使用することを忘れずに、以下のコマンドを実行してください。

```
# cd /var/www/yet-another-example.com
# wp core download --local=en_GB --allow-root
```

WP-CLIはすべてのコアファイルをダウンロードし、ディレクトリに解凍します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/50773f68-1c52-a591-101a-945c439448ac.png)

＜WP-CLIでWordPressコアファイルをダウンロードします＞

しかし、'ls -l' でディレクトリとファイルの所有権をチェックすると、所有権に問題があることがわかります。

以下のようにしてください。

`# chown -R www-data:www-data /var/www/yet-another-example.com`

ディレクトリとその内容を確認すると、正しい所有権を持っていることがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/2836d2d4-a679-3852-16d5-fc3d821a85da.png)

＜Web Appディレクトリの所有権をWebサーバに与える＞

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/4c1675a6-9362-4e3f-3160-756e3cfe05b2.png)

＜Webアプリディレクトリの所有権の確認について＞

ノード1やノード3では、WordPressのファイルがレプリケートされていることを確認できます。

```
# cd /var/www/yet-another-example.com
# ls 
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/a3d9a918-1087-8538-f98f-bc6e893be706.png)



＜WordPressファイルはGlustervolume全体にレプリケートされています＞

###ステップ6: Nginxを設定
**各ノードにNginxを設定し、WordPressサイトを提供します。**
各ノードで、WordPress ウェブアプリケーション用の Virtual Host Nginx 設定ファイルを作成します。

`# nano /etc/nginx/sites-available/yet-another-example.com`

以下のようにファイルを設定します。

```
server {
    listen 80;
    listen [::]:80;

    root /var/www/yet-another-example.com;
    index index.php index.htm index.html;
    server_name _;

    access_log /var/log/nginx/yetanotherexample_access.log;
    error_log /var/log/nginx/yetanotherexample_error.log;


    location / {
            try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;

    }

     location ~ /\.ht {
        deny all;
     }

    location = /favicon.ico { log_not_found off; access_log off; }
    location = /robots.txt { log_not_found off; access_log off; allow all; }
    location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
        expires max;
        log_not_found off;
    }

}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/b218486b-7a4c-3a17-9ba7-170abb4b5a94.png)

＜Webアプリケーション(WordPress)のバーチャルホストNginx設定ファイルについて＞

ファイルを保存して閉じ、/etc/nginx/sites-enabled/ディレクトリにシンボリックリンクします。

`# ln -s /etc/nginx/sites-available/yet-another-example.com /etc/nginx/sites-enabled`

ディレクトリを 'sites-enabled' ディレクトリに変更して、その内容をリストアップすると、以下のような設定ファイルのシンボリックリンクが表示されます。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/b20f8196-a972-5a42-3541-115856fe9590.png)

＜Webアプリケーションの設定ファイルをサイト有効にする＞のリンク先

Nginx の設定を変更したので、構文エラーがないかチェックしてみましょう。

`# nginx -t`

サーバー名「'_'」と相反する警告が表示されることがあります。これは、私たちが作成した設定ファイルがドメイン名に依存せず、ユーザー'_'をサーバー名として使用しているためです。

この警告は気にせず、Nginxをリロードしてください。

`# service nginx restart`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/c72611e4-91d2-a958-e08a-48739cbd08c4.png)


＜Nginxの構文警告を無視してNginxを再読み込みする＞

**ロードバランサーにNginxを設定する**
Let's Encrypt Certbot を Nginx プラグインで使えるようにするためには、ロードバランサ上に Web アプリケーション用のバーチャルホスト設定ファイルを作成する必要があります。

前のセクションでは、'root'ディレクティブを持つノードに設定ファイルを作成しましたが、'server_name'ディレクティブがないノードに設定ファイルを作成しました。

ロードバランサー上のバーチャルホスト設定ファイルは逆で、'server_name' ディレクティブはありますが、'root' ディレクティブはありません。

必要な Nginx Virtual Host の設定ファイルを作成して開きます。

`# nano /etc/nginx/sites-available/yet-another-example.com`

サーバーのIPアドレスをノードサーバーのプライベートIPアドレスに置き換えて、以下のようにファイルを設定します。

```
upstream clusternodes {
    ip_hash;
    server 172.20.62.56;
    server 172.20.213.159;
    server 172.20.213.160;
}

server {

    listen 80;

    server_name yet-another-example.com www.yet-another-example.com;

    location / {
        proxy_pass http://clusternodes;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
    }
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/6e9f2c4a-0fbb-13a0-2c94-1cf5a7bca64a.png)

＜ロードバランサー仮想ホストNginxの設定について＞

ファイルを保存して閉じ、Symlink で '/etc/nginx/sites-enabled/' ディレクトリにコピーします。

`# ln -s /etc/nginx/sites-available/yet-another-example.com /etc/nginx/sites-enabled`

ここで、'/etc/nginx/sites-enabled/' ディレクトリから 'default' バーチャルホストを削除します。

`# rm /etc/nginx/sites-enabled/default`

さて、Nginxに変更を加えているので、サービスを再起動する前に必ず構文を確認しておきましょう。

```
# nginx -t
# service nginx restart
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/01ef472a-4b6c-9c67-d9d4-06f159de905a.png)

＜設定ファイルをリンクしてNginxの構文を確認します＞

これで Nginx がサイトにサービスを提供するように設定されました。サーバーはHTTPポート80をリッスンし、トラフィックを上流の'clusternodes'にリダイレクトします。

Web アプリを HTTP/1 で提供したくないので、次のステップで修正します。

###ステップ7: ロードバランサーにLet's Encrypt SSLをインストールする
**Certbotのインストール**
ロードバランサー上に、外部パッケージリポジトリを 'apt' パッケージマネージャに追加できるようにするパッケージをインストールします。

`# apt-get install -y software-properties-common`

次に certbot 用の Let's Encrypt 外部パッケージリポジトリを追加します。

`# add-apt-repository ppa:certbot/certbot`

これで「certbot」をインストールできるようになりました。

```
# apt-get update
# apt-get install python-certbot-ngin
```

**CertbotでSSLを実装する**
通常は以下のコマンドで証明書をインストールします。

`# certbot --nginx -d domain.com -d www.domain.com`

しかし、[2018年1月21日にセキュリティ上の問題が報告](https://community.letsencrypt.org/t/solution-client-with-the-currently-selected-authenticator-does-not-support-any-combination-of-challenges-that-will-satisfy-the-ca/49983?spm=a2c65.11461447.0.0.4f62383cvBfpkK)され、このコマンドが一時的に無効になりました。この状況はすぐに改善されると思いますが、以下に回避方法を記載しておきます。

今のところは、証明書の取得中にNginxサーバーを一時的に停止させ、その後に再起動し、少し長めのコマンドを発行する必要があります。以下のコマンドを実行してください。

`# sudo certbot --authenticator standalone --installer nginx -d yet-another-example.com -d www.yet-another-example.com --pre-hook "service nginx stop" --post-hook "service nginx start”`

証明書は電子メールを送信した後に発行されるので、HTTPS のみを許可するようにサーバにリダイレクトを実装するかどうかを選択する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/cc1c8495-0c0c-aba4-1edf-dcc8d20a25a3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/75d9139f-1349-4c24-addd-ddffa9ed4de1.png)


<ロードバランサーにSSLを暗号化してみよう>

ここで、ドメインのロードバランサーNginx仮想ホスト設定ファイルを再度開いてみます。

`# nano /etc/nginx/sites-available/yet-another-example.com`

Certbotは、ポート443を介してHTTPSでサイトにサービスを提供できるように、サーバブロックを自動的に設定していることがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/d6ebefbb-bf19-490c-dce2-9d79912334bb.png)

＜Nginxバーチャルホストファイルを自動設定するツールをご紹介します＞

###ステップ7：WordPressのインストールと設定
**WordPressのデータベースとユーザーを作成する**
これを1つのノードで行う必要があるのは、node1でMySqlに接続するだけです。

`# mysql -u root -p`

WordPressのデータベースとユーザーを作成し、必要な権限を付与します。

```
CREATE DATABASE wordpress_cluster DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
GRANT ALL ON wordpress.* TO 'new_user'@'localhost' IDENTIFIED BY 'new_users_password';
```

FLUSH PRIVILEGESとEXIT：

```
FLUSH PRIVILEGES;
EXIT;
```

あなたの端末は以下のようになっているはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/a2862b16-2874-1ff8-e13d-e1f6158b8947.png)

＜WordPressのデータベースとユーザーの作成について＞

**WordPressの設定**
ドメインを訪問して、5分間のWordPressインストール手順を通過します。

`https://yet-another-example.com`

今のところ、どのCSSファイルも読み込まれていないことに気づくでしょう。心配しないで、最初のステップを完了させて、wp-config.phpファイルが作成されるようにしてください。

データベース名、データベースユーザー、パスワード、データベースホスト、データベースプレフィックスを入力して送信すると、インストーラーが必要なwp-config.phpファイルを作成してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/816be344-41d6-0453-673e-b61cb79f6eee.png)

＜WordPressのインストーラが必要とするデータベースの詳細を入力してください＞

ノード1で新しく作成したwp-config.phpファイルを開きます。

`# nano /var/www/yet-another-example.com/wp-config.php`

設定ファイルの最後のどこかに、require_once ABSPATH .wp-settings.phpの前に、以下の数行を追加します。

```
/* SSL Settings */
define( 'FORCE_SSL_ADMIN', true );
define( 'WP_HOME', 'https://yet-another-example.com' );
define( 'WP_SITEURL', 'https://yet-another-example.com' );

if (strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false) {
  $_SERVER['HTTPS']='on';
}

/* Disable WP-Cron */
define( 'WP_DISABLE_CRON', true')
```

端末ではこのようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/540152cc-6f5c-af22-ac58-442b3d5b5496.png)

＜WordPress設定ファイルにSSL設定を追加し、WP_Cronを無効にします＞
SSL設定により、これまで発生していたCSSの問題が修正されます。SSL経由で管理者アクセスを強制し、HTTPS経由でサイトホームをサーバーに変更し、HTTPでロードバランサーからトラフィックを転送するときに静的ファイルが必要であることをWordPressが認識できるようにします。要求された場合、HTTPSによって提供されます。

WP_CRON も無効にしていますが、これには正当な理由があります。WordPress の Cron ジョブは真の Cron ジョブではなく、スケジュールされたタスクを実行するためにサイトへの訪問に依存しています。これは恐ろしいことです。

では、Ubuntuシステムのcrontabを使ってWordPressのCronジョブをスケジュールしてみます。これは管理ノード1でのみ実行します。

`# crontab -e`

さて、cronジョブの一番下に余分な行を追加します。

`* * * * * * wget http://yourdomain.com:9443/wp-cron.php?doing_cron &> /dev/null`

crontabはこのようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/fed78235-5a09-ddb2-5cd4-7553ef7b8d6a.png)



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/dbf281ec-a7fe-9670-4525-9b32426c0864.png)


＜WordPressのスケジュールされたタスクを実行するためのシステムcronジョブを作成します＞

今、URLを再確認してください。

`https://yet-another-example.com`

そして、CSSをそのままにしてインストール作業を完了させます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/59ebcd3e-23a7-7e9c-40ed-312465ec4012.png)


<インストール作業の完了>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/92e3847a-94d1-561f-2c4e-9ad59f1490f6.png)

<クラスタ上のWordPressサイト>

###成功!
我々はPHP7とNginxをインストールすることによって、我々のLEMPスタックのインストールを完了しました。各ノードサーバのNGINXバーチャルホスト、ロードバランサのNginx設定とSSL証明書を設定し、WordPressをインストールしました。

これで、以下のクラスタアーキテクチャに従って、HTTPS で WordPress を実行している、完全に動作する等しく負荷分散されたサーバクラスタが完成しました。

次回の最終チュートリアルでは、ノード1 をウェブアプリケーション管理用に予約し、ノード2 と 3 をサイトトラフィック用に使用するように、このクラスタアーキテクチャを再構成します。

最終的に構築するクラスタ・アーキテクチャは以下のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/d84fc2d0-23fc-1491-54c5-3469521a77c2.png)

<管理者のトラフィックとサイトのトラフィックをリダイレクトするロードバランサを備えた3ノードクラスター>

最後のチュートリアルでは、Nginx FastCGi キャッシングを追加し、データベースクラスタと分散ファイルシステムを強化していきます。

それでは、またお会いしましょう。

*アリババクラウドは日本に２つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
[アリババクラウドジャパン公式ページ](https://www.alibabacloud.com/ja)*