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<pre wp-pre-tag-6=""></pre>amp;amp;amp;gt;
    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の整数倍になるように、各自調整を行ってください。ここの調整はアクセス数などによっても異なります。

Share this…