カテゴリー別アーカイブ: ソフトウェア

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

ローリングリリースで提供される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の整数倍になるように、各自調整を行ってください。ここの調整はアクセス数などによっても異なります。


ci-phpunit-testが動かない理由がphp7ccだった話

Composerで導入できる kenjis/ci-phpunit-test は Codeigniter 3.x で快適にPHPUnitによるテストが書ける便利なツールです。

その ci-phpunit-test にはクラスのメソッド、PHP標準の関数、定数などを書き換える事が出来る、モンキーパッチ機能が有るのですが。なぜか動かなくなり悪戦苦闘していました。

原因はComposerでグローバルにインストールしたphp7ccでした。

sstalle/php7cc はそのPHPアプリケーションが PHP 7.0 で動作するうえで問題が無いかを静的解析するツールなのですが、どちらも nikic/php-parser というPHPで書かれたPHPパーサに依存しており、違うバージョンが入ってしまうことが原因のようです。

nikic/php-parser v1.2.1 の composer.json の記述(抜粋)
nikic/php-parser: ~1.4,

kenjis/ci-phpunit-test v0.15.0 の composer.json の記述(抜粋)
nikic/php-parser: ^2.1|^3.0

とりあえずグローバルに入っている古いバージョンをremoveする事で、問題なく動くようになりました。

なお、php7cc の代わりになりそうな物としては wimg/PHPCompatibility があります。php7cc でカバーしていた範囲をすべてチェック出来るかはまだ分からないのですが、チェックのターゲットとして、PHP 5.6 以前のバージョンであったり、PHP 7.1 にも対応してるようです。


ブログをAzure WebAppsからAmazon Lightsailに移設してみた。良い所と引っかかった所など

無料版のAzure WebAppsはそれなりに良い物だったのですが、いかんせんスペック不足過ぎており、上位のプランにアップしようと思うといきなり数千円からという価格になってくるため、AWSのAmazon EC2よりもお安く使えるAmazon Lightsailに移設してみました。

EC2(AWSにおけるIaaSなクラウドサーバ)とLightsail(AWSにおけるVPS)の違いは以下のようになっております。

Amazon EC2

  • 完全従量課金で1時間単位の課金。
  • ネットワーク使用量についても従量課金。
  • スケールアップ、スケールダウンがいつでも自由にできる。
  • ディスクの拡張も比較的容易。
  • オートスケーリングを用いたスケールアウト、スケールインも(動かすプログラムが対応していれば)簡単。
  • VPCでの様々なネットワーク制御。
  • IAMによる細かな権限制御。

Amazon Lightsail

  • マシン自体は月額定額制の固定料金(5ドル~)。スナップショットについては容量に応じた従量課金。
  • ネットワーク使用量に比較的大きめ(1TB~)の無料枠有り。
  • ディスク容量はプランごとに固定。
  • スケールアップする場合はスナップショット作成からの新マシン作成となる。
  • EC2のコンパネとは色々と勝手が異なる。EC2のVPCとも異なるのでVPC関連で出来る事でLightsailでは出来ない事が多々ある。
  • 中身はEC2のt2インスタンス(のような物)だと思われる。ハイエンドな性能は求められない。
  • 他のVPSサービスとは異なり、EC2と同じ「Amazon Linux」が使える。

今回はt2.nanoベースと思われる月額5ドルのプランにしてみました。nanoインスタンスはCPUクレジットに不安が残るものの、今のところ明らかにAzure WebApps 無料プランよりは快適に動いています。

以下、移設の中で引っかかった所をまとめておきます。

LightsailのDNS機能はRoute53側でネームサーバーの変更が必要

LightsailにはAmazon Route53とは別のDNS管理機能が有り、一般的なVPSサーバを建てるための設定が全てLighsail側で完結するようになっているのですが、ここでRoute53でドメインを取得しているとひと手間必要になります。

Route53で新規取得したドメインは自動でNSレコードやSOAレコードがRoute53側に設定されますが、LightsailのDNS管理機能を使うにはここでネームサーバの指定をLighsailのDNS機能のネームサーバーへ変更してやる必要が有ります。

考えてみれば当たり前なのですが気づくのに結構時間がかかりました。ネームサーバの指定は例えばGoogle Plubic DNSのキャッシュ フラッシュ機能でもフラッシュ出来ないので、結構な時間変更の反映を待つ形になります。仕方が無いのでRoute53側でも一次的なAレコードを追加しました。

今思うとドメイン関連は、Route53だけで完結させても良かった気がします。

WordPressのサイトURL変更

昔SQLでパパっと変更すればOKだったような気がしますが、実際にはテキストではない形でデータを持っている部分も有りダメという情報を見かけました。

サイト URL の変更 – WordPress Codex 日本語版
https://wpdocs.osdn.jp/%E3%82%B5%E3%82%A4%E3%83%88_URL_%E3%81%AE%E5%A4%89%E6%9B%B4

上記を参考にwp-login.phpに一次的に

update_option('siteurl','http://example.com/');
update_option('home','http://example.com');

を記載する形で対応しました。

動かない301リダイレクト系プラグイン

WordPressはサイト移設時に行う301リダイレクトについてもプラグインがいくつか有り、移行元サイトの方で「Simple 301 Redirects」「Redirection」等を試してみたのですが、なぜか動かない。もしかしてHTTPヘッダの送出ではなく.htaccessファイルを作るなど、Apacheであること前提のプラグインだったりするんでしょうか?(未確認)

仕方が無いので(Azure WebAppsはIISなので)web.configを編集して対応しました。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
 <system.webServer>
 <rewrite>
 <rules>
 <!--
 もともとWordPressを動かすために書いてあったURLリライトルール
 -->
 <rule name="Redirect All" stopProcessing="true">
 <match url="(.*)"/>
 <action type="Redirect" url="http://www.sodo-shed.com/{R:1}" redirectType="Permanent"></action>
 </rule>
<!-- 以下略

これで問題なく新サイトへのパス指定を維持したリダイレクトが動いています。最初からこれでよかったですね。

OOM Killerで死ぬMySQL

最初からメモリが少ない(一番下の月額5ドルのプランは512MB)事が分かっているので、
innodb_buffer_pool_size=64M
にするなど相当にしょっぱい設定にしていましたが、それでもMySQLが起動しません。スワップ領域を追加する事で起動するようになりました。

Amazon EC2, mysql aborting start because InnoDB: mmap (x bytes) failed; errno 12
https://stackoverflow.com/questions/10284532/amazon-ec2-mysql-aborting-start-because-innodb-mmap-x-bytes-failed-errno-12

に記載の方法で追加(以下引用)。

Run dd if=/dev/zero of=/swapfile bs=1M count=1024
Run mkswap /swapfile
Run swapon /swapfile
Add this line /swapfile swap swap defaults 0 0 to /etc/fstab

私は1024MBではなく2048MBでスワップを作成しました。一度の接続数が10に満たないサイトですが、以下のようなメモリ使用状況になります。vm.swappinessは20に設定しています。

$ free -m
            total used free shared buffers cached
Mem:           89  473   16     33      41     85
-/+ buffers/cache: 345  143
Swap:        2047  336 1711

月額10ドルのプランではメモリが1GB有るので、お試しでも512MBはちょっと……という方はそちらを選ぶといいと思います。

CPUクレジット残高の確認方法が無い

前述のようにt2系インスタンス(と同じような制御の物)を使っている可能性が高いのですが

Amazon Lightsailのベンチマーク – 稲葉サーバーデザイン
https://inaba-serverdesign.jp/blog/20161208/aws_lightsail_benchmark.html

t2系では重要なCPUクレジットバランス(CPUクレジット残高)を確認する方法が、すくなくともマネジメントコンソール上では見当たりません。CloudWatch側のメトリクスにも有りません。

t2系インスタンスはクレジットが枯渇しそうでないか、だけを見ればCPUについて今のスペックが適切かどうかが分かりますが、それが無いのでサーバー監視の設定は何かしら別で用意した方がよさそうです。

まとめ

他にも何かあったような気がしますが、CPUクレジット以外については当たり前と言えば当たり前に必要になる対応なので、逆にそれ以外は特殊なことは無く、EC2でAmazon Linuxを立ち上げるような気持ちではるかに格安なサーバーを建てる事が可能でした。価格重視だと国内VPSにも種類は多いですが、AWSである事、VPC間接続でEC2 VPCとの接続が可能である事、その他AWSで提供されるサービスとの親和性、Amazon Linuxが使えることなどにメリットを感じるならなかなか良いんじゃないでしょうか。