少し前に AWS で DRBD やら Pacemaker やら Heartbeat やら GlusterFS を使って WordPress を HA 構成にしてみましたが、
なんで RDS とか S3 とか使わないの? 馬鹿なの? 死ぬの? とセルフツッコミが入ったので RDS や S3 を使ってみました。
VPC は以前作ったものをそのまま使います。
おさらいすると、次のような感じです。
- VPC
- Name tag wp-vpc
- CIDR block 10.1.0.0/16
- Tenancy Default
- Subnets
- Name tag wp-net-a
- VPC wp-vpc
- Availability Zone ap-northeast-1a
- CIDR block 10.1.1.0/24
- Auto-assign Public IP yes
- Subnets
- Name tag wp-net-c
- VPC wp-vpc
- Availability Zone ap-northeast-1c
- CIDR block 10.1.2.0/24
- Auto-assign Public IP yes
- Route Tables
- Routes
- Destination 0.0.0.0/0
- Target wp-gw
- Internet Gateways
- Name tag wp-gw
- VPC wp-vpc
- Security Group
- Security group name default
- VPC wp-vpc
- inbound Rule
- Type ALL Traffic
- Source sg-xxxxxxxx (default)
- inbound Rule
- Type SSH(22)
- Source My IP
- inbound Rule
- Type All ICMP
- Source My IP
- Security Group
- Security group name public
- VPC wp-vpc
- inbound Rule
- Type HTTP
- Source Anywhere
IAM ロールを作成
WordPress から S3 にアップロードできるようにするために IAM ロールを作成します。
IAM ユーザーを作成して、そのユーザーの Access Key ID と Secret Access Key を使って S3 にアクセスすることも出来ますが、その場合は Access Key ID と Secret Access Key を EC2 インスタンス内に保存する必要があります。
一方、IAM ロールならインスタンスの作成時にロールを紐つけるだけで良いので、Access Key ID や Secret Access Key をインスタンスに保存する必要がなく、簡単かつ安全です。
特別な事情で IAM ロールが使えない場合以外は、IAM ロールを使うことが奨励されているようです。
IAM ロールを作成
IAM の Management console を開いて、左ペインの Roles から Create New Role をクリックします。
Step 1 : Set Role Name
Role Name に wp-role
などと適当な名前を入力します。
Step 2 : Select Role Type
AWS Service Roles の Amazon EC2 を選択します。
Step 4 : Set Permissions
Custom Policy を選択して、テキストエリアに次を貼り付けます。Policy Name はなんでも良いです。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}
]
}
この IAM ロールが紐付けられた EC2 インスタンスは S3 に対するフルアクセスが可能になります。
本当はもっと絞ったほうがいいのだろうけど Resource の指定方法がよくわかりませんでした。
RDS サブネットグループの作成
RDS のインスタンスを作る前に RDS サブネットグループを作成します。ここで指定したサブネットで RDS インスタンスは起動します。
RDS の Management Console の左ペインで Subnet Groups を選択して、Create DB Subnet Group をクリックします。
次のように入力して作成します。
- Name
wp-db-nets
- Description
WordPress Subnet Group
- VPC ID
wp-vpc
(前回作ったやつ)
- Availability Zone と Subnet ID を選択して以下のサブネットを追加
RDS のインスタンスを作成します。
Step 1: Select Engine
mysql を選択します。
Step 2: Production?
Yes を選択します。
Step 3: Specify DB Details
Instance Specifications を次のように指定します。
- DB Instance Class
db.t2.micro
- Allocated Storage
5 GB
- Use Provisioned IOPS
No
Settings には次のように入力します。
- DB Instance Identifier
wordpress
- Master Username
wordpress
- Master Password
wordpress
- Confirm Password
wordpress
Step 4: Configure Advanced Settings
次のように設定します。
- Network & Security
- VPN
wp-vpc
(前回作ったやつ)
- DB Subnet Group
wp-db-nets
(↑で作ったやつ)
- Publicly Accessible
No
- VPC Security Group
default
(同じセキュリティグループ同士で通信可能)
- Database Options
- Backup
- Backup Retention Period
0 days
- Maintenance
- Auto Minor Version Upgrade
No
とくに記載していない部分はデフォルトのままにします。
インスタンスが立ち上がったら、Management console でインスタンスの画面を開いて Endpoint に表示されているホスト名を覚えておきます。
S3 Budket を作成
画像などをアップロードする先として S3 のバケットを作成します。
まず、S3 の Management console を開いて Create Bucket をクリックして適当な名前のバケットを作成します(仮に example-wordpress
とします)。
作成したバケットを選択して、右上の方にある Properties をクリックします。
Permissions をクリック、Add bucket policy をクリックして、テキストエリアに下記を貼り付けて Save をクリックします
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "AddPerm",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::example-wordpress/*"
}
]
}
これで、このバケットにアップロードされたファイルは自動的に公開されるようになります。
なお、バケットの名前はグローバルに一意(すべてのアカウントで一意)でなければならないので、実際に example-wordpress
などという名前のバケットは作れません、他の人が既にその名前でバケットを作っているからです。
EC2 の Management Console の Instances から Lunch Instance をクリックして、次のようなインスタンスを1台だけ作成します。
Step 1: Choose an Amazon Machine Image (AMI)
Quick Start で Amazon Linux AMI 2014.03.2 (HVM) を選択します。
Step 2: Choose an Instance Type
t2.micro を選択します。
Step 3: Configure Instance Details
下記のみ変更して、その他はデフォルトのままにします。
Network wp-vpc
Auto-assign Public IP Enable
IAM role wp-role
Step 4: Add Storage
Volume Type を General Purpose (SSD) に変更します。
Step 5: Tag Instance
Name に wp-ap
などと判りやすい名前を入力します。
Step 6: Configure Security Group
Select an existing security group を選択して default
を選択します。
Step 7: Review Instance Launch
ざっくり内容を確認して、Launch をクリックします。
しばらく待つとインスタンスが起動するので SSH でログインします。
いろいろインストール
作成したインスタンスにいろいろインストールします。
yum update します。
yum update
mysql と apache と php をインストールします。
yum install httpd24 php55 php55-opcache php55-mysqlnd mysql55
リブートします。
reboot
各種設定
各種設定を行います。
php の設定ファイルを作ります。
cat <<EOS> /etc/php-5.5.d/_default_.ini
expose_php = Off
error_reporting = E_ALL
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /var/log/php/php.log
date.timezone = Asia/Tokyo
post_max_size = 500M
upload_max_filesize = 500M
memory_limit = 1G
EOS
cat /etc/php.d/_default_.ini
ログディレクトリを準備します。
mkdir /var/log/php/
chmod 777 /var/log/php/
touch /var/log/php/php.log
chmod 666 /var/log/php/php.log
ログローテートの設定を作成します。
cat <<EOS> /etc/logrotate.d/php
/var/log/php/*.log {
missingok
daily
rotate 10
ifempty
create 0666 root root
}
EOS
cat /etc/logrotate.d/php
いらなさそうな設定ファイルを空にします。
echo -n "" > /etc/httpd/conf.d/autoindex.conf
echo -n "" > /etc/httpd/conf.d/userdir.conf
echo -n "" > /etc/httpd/conf.d/welcome.conf
仮の index.html と ELB からのヘルスチェック先のページを作成します。
echo index > /var/www/html/index.html
echo readme > /var/www/html/readme.html
自動起動を有効にして起動します。
chkconfig httpd on
service httpd start
ELB の作成
ELB を作成します。
1. Define Load Balancer
Load Balancer name wp-lb
Create LB Inside wp-vpc
その他はデフォルトのままにします。
2. Configure Health Check
Ping Path /readme.html
その他はデフォルトのままにします。
3. Select Subnets
ap-northeast-1a
と ap-northeast-1c
を追加します。
4. Assign Security Groups
default
と public
を選択します。
5. Add EC2 Instances
↑で作成したインスタンス wp-ap
を選択します。
Stickiness
ELB の作成後、Description の Port Configuration の近くにある Edit をクリックして Enable Load Balancer Generated Cookie Stickiness
を選択します。
これをやっておかないと AP が複数になったときにセッションが維持されないことがあります(たぶん)。
ELB の DNS 名を登録
Route53 で ALIAS レコードで ELB を登録します。仮に aws.example.net
だとします。
なお、ELB を作成してからしばらく時間をおかないと登録できませんでした。
登録したドメイン名をブラウザで閲覧して index.html が表示されれば正常に登録できています。
WordPress をダウンロードして /var/www/html に展開します。
cd /usr/local/src/
wget http://ja.wordpress.org/wordpress-3.9.2-ja.zip
unzip wordpress-3.9.2-ja.zip
rm -fr /var/www/html/
mv wordpress /var/www/html/
wp-config.php を作ります。DB のホスト名には RDS の Endpoint のホスト名を指定します。
cd /var/www/html
mv wp-config-sample.php wp-config.php
sed wp-config.php -e "
/^define('DB_NAME'/c define('DB_NAME', 'wordpress');
/^define('DB_USER'/c define('DB_USER', 'wordpress');
/^define('DB_PASSWORD'/c define('DB_PASSWORD', 'wordpress');
/^define('DB_HOST'/c define('DB_HOST', 'wordpress.xxxxxxxx.ap-northeast-1.rds.amazonaws.com');
" -i
curl https://api.wordpress.org/secret-key/1.1/salt/ > /tmp/secret
sed wp-config.php -e "
/^define('AUTH_KEY'/r /tmp/secret
/^define('AUTH_KEY'/d
/^define('SECURE_AUTH_KEY'/d
/^define('LOGGED_IN_KEY'/d
/^define('NONCE_KEY'/d
/^define('AUTH_SALT'/d
/^define('SECURE_AUTH_SALT'/d
/^define('LOGGED_IN_SALT'/d
/^define('NONCE_SALT'/d
" -i
cat wp-config.php
ブザウザで http://aws.example.net/
にアクセスして WordPress のインストールウィザードに必要項目を入力してインストールを完了します。
この後、アップロードファイルの保存先の設定をするので、まだ記事の投稿は行いません。
AWS SDK for PHP には S3 のストリームラッパーがあります。次のようなパスで S3 へのアップロードやダウンロードができるようになります。
s3://<BucketName>/<PathToFile>
WordPress がアップロードするディレクトリのパスをストリームラッパーのパスに変更して、S3 にアップロードされるようにしてみます。
まず、WordPress の次の URL を開きます。普通には弄れない内部的なオプションを変更するための画面なのだと思います。
http://aws.example.net/wp-admin/options.php
upload_path
と upload_url_path
を探して、次の通りに入力して保存します。
upload_path s3://example-wordpress
upload_url_path http://example-wordpress.s3-ap-northeast-1.amazonaws.com
upload_path
に指定した値は /var/www/html
(WordPress のインストール先)からの相対パスになるようです。
なので、このままだと /var/www/html/s3://example-wordpress
などという意味不明なパスになるので、WordPress のソースを弄って修正します。
wp-includes/functions.php
の 1644 行目辺りをコメントアウトします。
//} elseif ( 0 !== strpos( $upload_path, ABSPATH ) ) {
// // $dir is absolute, $upload_path is (maybe) relative to ABSPATH
// $dir = path_join( ABSPATH, $upload_path );
後は、S3 のストリームラッパーを登録するだけです。
AWS SDK for PHP は composer でインストールできるので、まずは composer をインストールします。
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
chmod +x /usr/local/bin/composer
AWS SDK for PHP をインストールします。
cd /var/www/html
composer require aws/aws-sdk-php:\*
こんな場所で composer require すると composer.json
とか vendor/
とかが丸見えになるのでよろしくありません。が、とりあえずそのままにします。
さらに wp-config.php
に下記を追記します。
require 'vendor/autoload.php';
use Aws\S3\S3Client;
use Aws\Common\Enum\Region;
S3Client::factory(array('region' => Region::AP_NORTHEAST_1))->registerStreamWrapper();
これで S3 のストリームラッパーが登録され、アップロードファイルが S3 に保存されるようになりました。
適当に画像などをアップロードした後に S3 のバケットを閲覧してみると、アップロードされたファイルが保存されているのがわかります。
また、ブラウザで表示される画像の URL も S3 の URL になっています。
たぶん普通はこんなことしません。プラグインかなにかを使うものなのだと思いますが、実は WordPress ほとんど使ったことがなく、よく判らなかったので適当にソースを弄りました。
ググると下記のプラグインが出てきたのですが、プラグインのインストール方法とかをよく知らないので使いませんでした。
あるいは s3fs-fuse を使えば、単に /var/www/html/wp-content/uploads
にマウントするだけで終わりそうです。
AMI の作成
最後に Auto Scaling を設定してみます、と言っても単にインスタンスをたくさん立ち上げただけです。
Auto Scaling には AMI が必要なので、作成済の EC2 インスタンスを AMI 化します。
インスタンスにログインして、AMI に含めたくないファイルを削除してシャットダウンします。
rm -f /root/.ssh/authorized_keys
rm -f /home/ec2-user/.ssh/authorized_keys
rm -f /etc/ssh/ssh_host_dsa_key
rm -f /etc/ssh/ssh_host_dsa_key.pub
rm -f /etc/ssh/ssh_host_key
rm -f /etc/ssh/ssh_host_key.pub
rm -f /etc/ssh/ssh_host_rsa_key
rm -f /etc/ssh/ssh_host_rsa_key.pub
find /var/log -type f | xargs rm -fv
rm -f /root/.bash_history
shutdown -h now
EC2 の Management console で インスタンスを選択して Create Image で AMI を作ります。
Launch configuration の作成
EC2 の Management console の Launch configuration で Create launch configuration をクリックします。
1. Choose AMI
My AMIs を選択して、↑で作成した AMI を選択します。
2. Choose Instance Type
t2.micro
を選択します。
3. Configure details
Name に wp-auto
などと判りやすい名前を設定します。
IAM role には wp-role
を指定します。
4. Add Storage
Delete on Termination が On
になっていることを確認します。なっていなければ On
にします。
5. Configure Security Group
Select an existing security group を選択して default
を選択します。
6. Review
ざっくり内容を確認して右下の Create launch configuration をクリックします。
Auto Scaling Group の作成
EC2 の Management console の Auto Scaling Groups で Create Auto Scaling Groups をクリックします。
Create an Auto Scaling group from an existing launch configuration を選択して、先ほど作成した Launch configuration を選択します。
1. Configure Auto Scaling group details
Group name wp-group
Group size 起動したいインスタンスの数
Network wp-vpc
Subnet wp-net-a wp-net-c
Advanced Details を開いてさらに設定します。
Load Balancing On wp-lb (チェックボックスを On にしてテキストボックスに ELB を入力)
2. Configure scaling policies
特になにも変更せずに次に進みます。
3. Configure Notifications
特になにも変更せずに次に進みます。
4. Configure Tags
特になにも変更せずに次に進みます。
5. Review
ざっくりと内容を確認して右下の Create Auto Scaling Groups をクリックします。
しばらく待つと、インスタンスがバコバコ起動して ELB に追加されます。
さいごに
試しにインスタンスの数を 100 台に設定してみたのですが、20 台目以降はインスタンスの作成に失敗しました。
EC2 の Management console の Limits を見ると t2.micro は 20 台がリミットになっているので、申請しなければ 20 台より多くは起動できないようです。
下図は 20 台起動したときの EC2 の Management console のキャプチャです。
祭りの後