少し前に AWS で DRBD やら Pacemaker やら Heartbeat やら GlusterFS を使って WordPress を HA 構成にしてみましたが、
なんで RDS とか S3 とか使わないの? 馬鹿なの? 死ぬの? とセルフツッコミが入ったので RDS や S3 を使ってみました。
VPC の作成
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 を選択して以下のサブネットを追加
wp-net-a
wp-net-c
RDS インスタンス作成
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
- Database Options
- Database Name
wordpress
- Database Name
- Backup
- Backup Retention Period
0 days
- Backup Retention Period
- Maintenance
- Auto Minor Version Upgrade
No
- Auto Minor Version Upgrade
とくに記載していない部分はデフォルトのままにします。
インスタンスが立ち上がったら、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 インスタンスの作成
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
yum update します。
yum update
mysql と apache と php をインストールします。
yum install httpd24 php55 php55-opcache php55-mysqlnd mysql55
リブートします。
reboot
各種設定
各種設定を行います。
php
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
apache
いらなさそうな設定ファイルを空にします。
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 のインストール
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 のインストールウィザードに必要項目を入力してインストールを完了します。
この後、アップロードファイルの保存先の設定をするので、まだ記事の投稿は行いません。
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
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 の補足
たぶん普通はこんなことしません。プラグインかなにかを使うものなのだと思いますが、実は 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 のキャプチャです。
祭りの後