タグ別アーカイブ: AWS

東京リージョンで使えるようになったAmazon EFSを使って手軽なWordPress冗長化

WordPressをはじめとした管理者が自由に投稿できるタイプのCMS冗長化は、DBを Amazon RDS などに向けてもテーマの編集やアップロードした画像、各種ファイルの扱いなどが面倒でした。

Amazon S3 に画像をアップロードするようにするWordPressプラグインなども有りますし、複数サーバー間のrsync、lsyncdでファイルの内容を同期するなどの方法も有りますが、先日東京リージョンでもリリースされた Amazon EFS を利用すると簡単に「複数サーバーで共用のドキュメントルート」を実現する事が出来ます。

Amazon EFS (Elastic File System)はマネージドなNFSサービスで複数のEC2インスタンスからマウント・アクセスする事が可能です。

以下手順

AWSマネジメントコンソールにログイン。

新しいVPCを作ります。

作成したVPCに新しいサブネットを2つ作ります。ここではAZ冗長化の為に1a AZと1c AZにサブネットを作成します。

インターネットゲートウェイを作成します。

作成したインターネットゲートウェイをVPCにアタッチします。

作成したVPCのデフォルトルートテーブルにルーティングを追加。
0.0.0.0/0 を先ほど作成したインターネットゲートウェイに向けます。

Webアクセス用のセキュリティグループを追加。VPCの選択ミスに注意。

SSH/HTTP/HTTPSをまとめて許可。SSHは本来はセキュリティグループを分けてより適切に制御した方が好ましいです。

Webサーバ用のEC2インスタンスを起動していく。Amazon Linux 2 インスタンスを選択。

インスタンスタイプの選択。

VPCの選択を忘れない事。サブネットはとりあえず1aの方を選択する。自動割り当てパブリックIPは有効にする。

ストレージの設定。

セキュリティグループは「既存のセキュリティグループ」からWeb用に作成した物を適用。

キーペアが無ければ新しく作成して手元にダウンロードする。

 

 

マシンの起動を待つ。

起動したらダウンロードしたキーペアを鍵ファイルにSSH接続。

PHP関連とApacheを導入。
yum install php php-common php-opcache php-gd php-mysqlnd php-mbstring php-fpm httpd

データベース冗長化の為にAmazon RDS for MySQL のインスタンスを作成する。RDSの画面からMySQLを起動していく。

MySQL 5.7.21を選択。

マルチAZ設定を有効化。これでDB側が複数AZに冗長化されます。

DB名やユーザー、パスワードなどを適当に設定。メモしておく事。

作成したVPCを選択。DBサブネットグループは新規作成。

DBパラメータグループ、オプショングループはデフォルトのまま。本来は別で作成しておいた方がいいです。後から設定を変更する際にデフォルトのままだと面倒です。

EC2インスタンスにmysql (mysql-serverではない)をインストール。パッケージとしてはmariadbが降ってきます。

RDSのエンドポイント名をメモ。

RDSに適用されているセキュリティグループにWeb用セキュリティグループからのTCP: 3306許可を追加。

mysqlコマンドからRDSに接続が出来る事を確認。

ドキュメントルート冗長化の為のEFSを起動していきます。

作成したVPCとサブネットを選択。セキュリティグループはとりあえずデフォルトのまま。

パフォーマンスモードはとりあえずそのまま。

EFSが利用可能になるのを待ちます。

EFS用のセキュリティグループを作成。

EFS用セキュリティグループにWeb用セキュリティグループからの全許可を追加して保存。

EFSインスタンスの画面からマウント方法を確認する。必要なEFSマウントヘルパーを導入する。
sudo yum install -y amazon-efs-utils

現在のVPCの設定ではDNS名でアクセスできないという警告が出ているので対応する。

VPCの設定で「DNSホスト名の編集」を「はい」に変更。

EFSにDNS名でアクセスできるようになります。

先ほどのEFS接続方法がより具体的な内容に変化している。

EFSのセキュリティグループの設定を先ほど作成したEFS用のセキュリティグループに変更。これでWebサーバからのNFSアクセスが通るようになります。

手順通りにコマンドを実行しEFSがマウントできたことを確認。今回は手動で叩いていますが、EC2のユーザーデータに仕込んでおくと起動時にマウントしてくれるようになります。

Apacheを起動。

EC2のDNS名で接続できることを確認。

EFSマウント配下にドキュメントルート用のディレクトリを作成、Apacheのドキュメントルート設定もそこを参照するように変更。今回は /efs/wp に実態を配置、 /var/www/html/wp をそこへのシンボリックリンクにして、/var/www/html/wp をドキュメントルートにしています。

Apacheを再起動して反映。閲覧テスト用のファイルをドキュメントルートに配置。

/etc/php.ini の設定で date.timezone を Asia/Tokyo に設定しておく。PHP設定変更後もApache再起動を実施。

testと書いたindex.html、<?php phpinfo(); が実行される info.php が閲覧できることを確認。

WordPressをセットアップしていきます。tar.gzでのアーカイブをwgetでダウンロード。

アーカイブをドキュメントルート配下に展開。この際にEFSは少しディスクI/Oが遅い事が分かります。ゆくゆくはCloudFrontなどでCDNキャッシュする事も検討した方がいいかもしれません。ファイル展開後はファイルの権限をApacheのものに変更。先ほど作成したindex.htmlとinfo.phpは削除しておきます。

WebブラウザでアクセスしWordPressのセットアップを進める。

DBの向き先はRDSのエンドポイント。その他WordPressのID・パスワードは適当に設定しメモしておく。

セットアップ完了。

現在起動しているEC2インスタンスのAMI(マシンイメージ)を取得。外部からのアクセスが有る状況でもないので「再起動しない」オプションは有効でOK。

作成したAMIから2つ目のEC2インスタンスを起動していく。サブネットはAZ冗長化の為に1cの方を選択。

マシン起動後にSSHログイン、先に1aで起動している方と同様にEFSマウント。先ほども書いたようにユーザーデータにしておくと最初からマウントされた状態になるかと思います。

1aで起動している方のDNS名、同1cのDNS名でどちらもWordPressサイトが閲覧できることを確認。

テーマを切り替えてみます。

もう片方にも反映されました。

画像アップロードを含む記事を作成してみます。

どちらのDNS名でも画像が見られることを確認。これで冗長化を実現できている事が分かります。同期用の設定などを組まなくていいのは楽ですね。

最後にロードバランサ―を立てます。Application Load Balancerを使います。

既存のサブネットを登録。

Web用のセキュリティグループを設定。本来このセキュリティグループにSSH許可は不要なのでALB用に別でセキュリティグループを作成した方がいいです。

ターゲットグループには起動済みのEC2インスタンス2つを追加。

作成したロードバランサーのDNS名をメモ。

ALBのDNS名でWordPressサイトが閲覧できることを確認。

以上でWebサーバー、DBサーバーが冗長化されただけでなく、コンテンツの同期も実現した環境が完成しました。ここまで所要時間は大体1時間強~2時間ほどでした。後は以下を検討していけばいいと思います。

セッション維持:
今回セッション維持は考えていません。WordPressに記事を投稿する際は起動している適当なインスタンスに直接アクセスするなど適当な方法を使います。

オートスケーリング:
AMI作成+ユーザーデータによるEFSマウント設定でオートスケーリングさせます。ファイルの同期はEFSをマウントするだけで完了します。

セキュリティグループ周り:
もうちょっと適切な内容で整理した方がいいです。

Apahce、PHPの設定、MySQLの設定:
今回は何も触っていないのでもちろん要チューニングです

CloudFront導入:
ファイルアクセスのレスポンスが気になるようであれば導入。実際どの程度の負荷まで耐えられるかは未知数。

AWS WAF導入:
既にALBが有るのでそこにAWS WAFを追加する事が出来ます。

あとはEFSを利用したドキュメントルートがどの程度のI/Oまで耐えられるかですね。ほぼ読み込みなら問題ない気がしていますが、これを実運用するならもちろん負荷テストは必要になるかと思います。場合によってはNFSからEC2ローカルに同期するような構成も検討が必要でしょう。以上、EFSでWordPressを冗長化してみた記事でした。


Amazon Linux AMI のサポート期間が2年を切りました

まずは Amazon Linux 2 LTS 正式版のリリースおめでとうございます。

長期サポート (LTS) を付随した Amazon Linux 2 が一般公開
https://aws.amazon.com/jp/about-aws/whats-new/2018/06/announcing-amazon-linux-2-with-long-term-support/

Amazon Linux 2 は systemd が導入されたり、各種パッケージのバージョンが変わったり、5年間の長期サポートが提供されたりなど、これまでの Amazon Linux AMI から様々な部分で変更が有る物になっています。

なお、それに伴い以前から予告されていたように2ではない方の Amazon Linux (※1) のサポート期間は2年間となり、具体的にはセキュリティ修正の提供期間が2020年6月30日までとなります。7月6日現在既に2年間を切っている状態となります。

AWS では 2020 年 6 月 30 日まで、Amazon Linux の最新バージョンに対するセキュリティ更新とコンテナイメージの提供を継続します。

Amazon Linux 2 に関するよくある質問
https://aws.amazon.com/jp/amazon-linux-2/faqs/

2020年は RHEL 6、CentOS 6、Windows Server 2008、Windows Server 2008R2、Debian 8 LTSと様々なサーバー向けOSのサポート終了が重なる年になっていますが、そこに旧Amazon Linuxも加わる事になります。これまでのAmazon Linuxの継続的アップデートとは異なり2に直接移行ではなく再構築となりますので、工数的にもこれまでのAmazon Linuxアップデートより重いものになります。

関係者の皆様におかれましてはお早目の移行を検討いただけるよう何卒。

※1:何と呼べばいいんでしょうね、Amazon Linux 1とかAmazon Linux 無印だと微妙に通りが悪いですし、公式ではAmazon Linux AMIと言っていますが別に2もAMIで公開されているわけですし。


Amazon Linux AMI 2017.09で今こそApacheをhttp/2対応にする手順

Aローリングリリースで提供されるAmazon Linux AMIが先日バージョン2017.09となりました。数年ぶりにOpenSSLのバージョンが更新される(1.0.1k → 1.0.2k)等、それなりに変更点の大きいリリースとなっており、これによりディストリビューション標準のパッケージのみでApache/Nginxのhttp/2に対応できるようになりました。ソースコンパイルを伴うミドルウェアは実運用においては、メンテナンス性に難が有りましたが、今後は簡単に導入が可能なはずです。「今こそ」、なタイミングかと思いますので対応していきます。

Amazon Linux AMIのバージョン確認

# cat /etc/system-release
 Amazon Linux AMI release 2017.09

まだ2017.09になっていなければ(問題無い事を確認したうえで)yum updateしてください。
古いリリースはセキュリティ修正も行われません。

前提

Webサーバー

Apache 2.4を使います。WordPressを動かす為にPHP 7.1を使っています。

SSL/TLSへの対応

既にWebサイトは(常時)SSL/TLS対応になっているものとして進めます。
まだであれば、Let’s Encryptなど各種方法で対応して下さい。

ロードバランサ

ELB(ALB/CLB/NLB)は未導入のものとして話を進めます。

PHP-FPMの導入

なぜいきなりPHPの話になるかというと、Apacheでhttp/2に対応するためには、Prefork MPMではなく別のMPMを使う必要が有るからです※1。その為、PHPをApacheモジュール版ではなく、
php-fpmで動作させる必要があります。

※1: Apache 2.4.27以降はmod_http2がprefork MPMに対応しない。

導入手順

php-fpmをyumからインストール。PHP 7.1を利用しているので php71-fpm になっています。

# yum install php71-fpm

Apache側の現在のMPMを確認

# /usr/sbin/httpd -V | grep MPM
 Server MPM: prefork

preforkで動いています。

/etc/httpd/conf.modules.d/00-mpm.conf

で設定されているので上記ファイルを開き、

LoadModule mpm_prefork_module modules/mod_mpm_prefork.so

を#でコメントアウト

#LoadModule mpm_event_module modules/mod_mpm_event.so

のコメントアウトを外しevent MPMを使うように修正

構文チェック

# /usr/sbin/httpd -t
 AH00513: WARNING: MaxRequestWorkers of 64 is not an integer multiple of ThreadsPerChild of 25, decreasing to nearest multiple 50, for a maximum of 2 servers.
 Syntax OK

スレッド数の部分で警告が出ていますが、これは後で修正します。

バーチャルホストの設定

PHPファイルの実行をphp-fpmに渡すための設定を追加する。
Apache(やNginx)とphp-fpmの接続は、UNIXドメインソケットと127.0.0.1:9090へのTCP/IP接続が選べますが、ApacheとPHPを同じサーバーで実行する場合は、応答速度の速いUNIXドメインソケットの方で設定します。
対象のバーチャルホスト設定に以下を追記。拡張子がphpのファイルをphp-fpmに渡します。

<FilesMatch \.php$>
    SetHandler "proxy:unix:/var/run/php-fpm/php-fpm.sock|fcgi://localhost"
</FilesMatch>

FilesMatchにマッチしたファイルしかphp-fpmに渡されない事に注意。

構文チェック

# httpd -t
 AH00513: WARNING: MaxRequestWorkers of 64 is not an integer multiple of ThreadsPerChild of 25, decreasing to nearest multiple 50, for a maximum of 2 servers.
 Syntax OK

php-fpm側の設定

ユーザーの設定やソケットファイル名の設定など修正。

# cp /etc/php-fpm.d/www.conf /etc/php-fpm.d/www.conf.orig
# vim /etc/php-fpm.d/www.conf
# diff /etc/php-fpm.d/www.conf.orig /etc/php-fpm.d/www.conf
38c38
< listen = /var/run/php-fpm/www.sock
---
> listen = /var/run/php-fpm/php-fpm.sock
48,49c48,49
< ;listen.owner = nobody
< ;listen.group = nobody
---
> listen.owner = apache
> listen.group = apache
55c55
< listen.acl_users = apache,nginx
---
> ;listen.acl_users = apache,nginx

php-fpmのログレベルをnoticeからwarningに変更する。

# vim /etc/php-fpm.conf

;log_level = notice

を以下に修正

log_level = warning

php-fpmの起動とhttpdの再起動

# /etc/init.d/php-fpm start
 Starting php-fpm-7.1: [ OK ]

# /etc/init.d/httpd restart
 Stopping httpd: [ OK ]
 Starting httpd: AH00513: WARNING: MaxRequestWorkers of 64 is not an integer multiple of ThreadsPerChild of 25, decreasing to nearest multiple 50, for a maximum of 2 servers.
 [ OK ]

まずはこの時点でWebサイトが正常に表示されることを確認する。
次にMPMの確認

# /usr/sbin/httpd -V | grep MPM
 Server MPM: event

あとはドキュメントルートに適当にphpinfoを実行するファイルを置いて確認。
下記ファイルをWebブラウザで開いた際に、Server APIに
「Apache handler 2.0」ではなく「FPM/FastCGI」と表示されていればOK。

phptest.php
<?php
    phpinfo();

※確認後はこのファイルの消し忘れにご注意ください。

これでApacheがevent MPMかつ、php-fpmでPHPが動作する環境になりました。
MPMがeventになった事により、多数のアクセスに対しても(適切にチューニングをすれば)preforkよりもスケールする事が出来ると思われます。

http2/対応

ここまでくればhttp/2対応は簡単です。
Amazon Linuxバージョンアップの時点で、mod_http2はすでに導入されているので

# ls -l /etc/httpd/modules/ | grep http2
 -rwxr-xr-x 1 root root 253544 Sep 25 08:20 mod_http2.so

対象のバーチャルホストに以下を追記

Protocols h2 http/1.1

し、httpdを再起動

# /etc/init.d/httpd restart

これでもうhttp2対応です。お疲れ様でした。

なお、Apacheで出ている、MaxRequestWorkersやThreadsPerChildのワーニングについては、MaxRequestWorkersがThreadsPerChildの整数倍になるように、各自調整を行ってください。ここの調整はアクセス数などによっても異なります。