CloudFront custom origin
t1.micro (LAMP + WordPress & Really Static plugin) + cloudfront custom origin で激安・爆速サイトを構築する Tips
概要
JAWS-UG 大阪支部 第一回勉強会での @kaz_goto さんの発表に触発されて、CMS から静的コンテンツを生成し CloudFront の Custom Origin でダイレクトに公開する手法で設計。
出来る限り簡単に構築でき、運用も簡単で、出来る限り安価で、出来る限り高性能といった贅沢な希望をかなえる。 ;)
JAWSUG Osaka 第1回 ウェブサイト構築事例紹介 - cloudpack(クラウドパック)Amazon EC2などクラウドの導入設計、運用・保守サービス 激速CDNホスティング
- コンテンツ作成は手慣れたツール(WordPress)を利用し、静的コンテンツを CloudFront で公開する。
- もちろん MT が好きな人は MT で OK :)
- WordPressの稼働負荷はコンテンツの制作時のみであるので、t1.micro で安価に構成する。(ubuntu Linux, Apache, MySQL, PHP5) (us-east-1 が安い)
- WordPressサーバ(CMSサーバ)は、制作/管理機能・動的コンテンツ確認機能・(CloudFrontのOriginとしての)静的コンテンツOrigin機能を持つ。
- 静的コンテンツの生成はReally Static Pluginを使用する。
CloudFront の Origin 指定は path が指定できないので、各機能の URL は以下のようにする。
- 制作/管理機能 : http://cms.example.com/blog/wp-admin/
- 動的コンテンツ確認機能 : http://cms.example.com/blog/
- 静的コンテンツOrigin機能 : http://cms.example.com/
公開用静的コンテンツの URL は http://www.example.com/ とする。
CloudFront の設定
- CustomOrigin -> DNSName : cms.example.com
- CNAME : www.example.com
- DefaultRootObject : index.html
構成図
AWSの利点
激安・爆速といった面以外に、圧倒的な利便性がある。
- bootable + cow(copy on write) なスナップショットがとれる (AMI)
- お手軽なバックアップ・コールドスタンバイ
- multi zone, multi region
- CloudFront を使うことにより location は気にしなくてもいいが、サーバも localtion を任意に選択できる
- その他 書ききれないほどのメリット有り
構築手順
(気持ちの余裕ができたら、Cloud Formation の Template 作るかもしれず...)
Tips
日本語文字列の制限
- マルチバイトな文字列は URL PATH には使用できない。
- Really Static は UTF-8の「URL エンコード」(Percent-Encoding) はきちんとできてる
- としたら、やはり CloudFront でマルチバイトな文字列が使えるかどうかはアヤシイ
Cache 時間の問題
★★★重要★★★
- CloudFront の edge location でのキャッシュ時間は。標準で24時間。指定できる最短時間は1時間
- 誤ってキャッシュの有効期限を長くしてしまったらとても痛い
- CloudFront Invalidation 機能をつかって、キャッシュされたコンテンツの強制削除は可能(10分〜20分ぐらいで消える)
- ただし、経験上どうしても消えない現象も見受けられた
- CloudFrontを有効にするまえにApacheの設定をしっかりしておく事が重要
追記
- CloudFront 機能追加で TTL=0 も設定できるようになりました
mod_expires を有効にして、運用が安定するまでは最短の1時間にする事
<IfModule mod_expires.c> ExpiresActive On ExpiresDefault "access plus 1 hours" </IfModule>
運用が安定してきたら、ブラウザでのキャッシュを有効に利用するために、 text/html 以外を長くする
<IfModule mod_expires.c> ExpiresActive On ExpiresDefault "access plus 1 hours" ExpiresByType text/html "access plus 1 hours" ExpiresByType text/css "access plus 1 weeks" ExpiresByType text/javascript "access plus 1 weeks" ExpiresByType application/x-javascript "access plus 1 weeks" ExpiresByType application/javascript "access plus 1 weeks" ExpiresByType image/jpeg "access plus 1 weeks" ExpiresByType image/png "access plus 1 weeks" ExpiresByType image/gif "access plus 1 weeks" ExpiresByType image/x-icon "access plus 1 weeks" </IfModule>
- 即座に更新したい場合は、パス名やファイル名を変えることで可能
- ただし、DocumentRoot の index.html はどうしても1時間のキャッシュになるので注意する事
CloudFront 用の GUI ツール
- CloudFront で Custom Origin の設定するGUIがあるツールでは MacOSX ユーザなら Bucket Explorer が使える
- Bucket Explorer は Invalidation の発行も GUI で可能
- もう少ししたら、Amazon Management Console で実装されそうな気がします
運用の注意点
- CMS 側のアクセス制限を忘れないように。(t1.micro で comment spam 受けたら死にます)
- Really Static がコンテンツ作成するので、サイトの IP address (localhost ではなく 割り当てられたプライベートアドレス)はアクセス許可にする事。
- 細かなアクセス制限(IP address と Basic 認証の併用)は Apache の Satisfy ディレクティブが使える
# ACL Satisfy any Order deny,allow Deny from all Allow from 127.0.0.0/255.0.0.0 ::1/128 10.xxx.xxx.xxx <IfModule mod_authn_file.c> AuthType Basic AuthName "wordpress auth" AuthUserFile /etc/wordpress/htpasswd.admin </IfModule> Require valid-user # end ACL
プライベートアドレスは boot 時に instance meta-data から取得して自動的に生成するスクリプト書きましょう
- 静的コンテンツ側も cloudfront からのアクセスのみに限定する
Announcement: Amazon CloudFront Public IP Ranges
追記
- 余りにも CloudFront の IP Range が変わる頻度が激しいので User-Agent でコントロールするのが現実的
# access only cloudfront SetEnvIf User-Agent "Amazon CloudFront" amazon_cloudfront Order deny,allow Deny from all Allow from 127.0.0.0/255.0.0.0 ::1/128 10.xxx.xxx.xxx env=amazon_cloudfront
- 動的サイトへのアクセスが制限されているので、wp-cron が機能しない。なので本物の cron で処理する
define(‘DISABLE_WP_CRON’, true);
3-59/10 * * * * root /usr/bin/wget -q -O - http://cms.example.com/blog/wp-cron.php
- Really Static の wp-cron への登録は daily になっているので、WP-Crontrol で任意のタイミングに変更する
その他
- Custom Origin の "Origin" は PATH 指定出来ない。
- つまり "http://www.example.com/blog/" ではダメで、"http://www.example.com/" 以下にコンテンツを配置する必要がある。この場合 Origin の指定は www.example.com となる。
- 当然ですが、コメント欄は不可にする。(あらゆる動的な仕組みは不可)
- CMSサーバの運用で一点だけ強調すると、t1.micro はリソースをギリギリまで制限する事がポイントとなる
- Apache の prefork 数や、MySQL の max_connections を制限する
- MySQL は skip-innodb しておく
- RSS feed
- Really Static の Settings -> Advanced で URL feed, feed/atom, feed/rss を file name を空欄で "Rewrite on create, edit or delete a post" で登録
- コンテンツの容量が増えた場合に変換処理が重くなる(はず)
- MTでよくあるような、静的コンテンツの変換処理が重い、遅いという状態になるハズ(様子見中)
- けっこう重大な問題が...
ベンチマーク
CMSサーバは us-east-1 の t1.micro
CloudFront は Japan edge location
ブラウザは Google Chrome 10.0.648.204 (MacOSX) で大阪から
- ブラウザのコンテンツキャッシュ・クッキーは削除して閲覧
- CMSサーバから
7 requests | 36.42KB transferred | 14.70s (onload: 14.70s, DOMContentLoaded: 14.08s) snapshot
CloudFrontから
7 requests | 39.27KB transferred | 847ms (onload: 957ms, DOMContentLoaded: 768ms) snapshot
- 上の状態から、ブラウザのコンテンツキャッシュ・クッキーを残して閲覧
- CMSサーバから
7 requests | 2.92KB transferred | 1.30s (onload: 1.30s, DOMContentLoaded: 1.09s) snapshot
CloudFrontから
7 requests | 7.54KB transferred | 104ms (onload: 104ms, DOMContentLoaded: 80ms) snapshot
12〜17倍高速である (ただし、CloudFrontへコンテンツが初回のキャッシュや再キャッシュするタイミングでは若干の遅延は有る)
コスト
CMSサーバ t1.micro us-east-1
- $0.02 per hour
月額 1,260円
CloudFront (per edge location の括り United States, Europe, Asia, Asia-Japan(消費税関係で別))
- First 10 TB / month $0.201 / GB (Japan edge location)
- Per 10,000 HTTP requests $0.0095 (Japan edge location)
- Per 10,000 HTTPS Requests $0.0130 (Japan edge location) (使ってなくても1回でもリクエストがあれば課金)
経験上 1 edge location で月額 $0.03 なので、Japan, United States, Europe, Hong Kong and Singapore からアクセスがあったら、$0.12 ;)
月額 10.2円
その他 EBS ディスク容量・IO Request ネットワーク転送量等々あわせても $2 は掛らない