CloudFront対応のWordPress、Host設定でELB直接続も可能な環境を構築してみた
はじめに
AWSチームのすずきです。
AWSが提供するCDN、CloudFront経由で公開するWordPress環境では、 管理者向けの編集機能などCDNの副作用で制限が生じる場合があります。
今回、ELBとして固定IP(EIP)に対応したNLBを採用し、 Webコンテンツの管理者は端末のHosts設定を切り替える事で、CDNの副作用なくWordPressを操作できる環境について紹介させていただきます。
構成図
AWS設定
CloudFront
- CloudFront のDistributionは2つ、ELB(WordPressのEC2)用と、S3(画像)用に準備しました。
CloudFrontDistributionElb: Type: AWS::CloudFront::Distribution Properties: DistributionConfig: Origins: - Id: CustomOrigin DomainName: !GetAtt 'NlbLoadBalancer.DNSName' CloudFrontDistributionMedia: Type: AWS::CloudFront::Distribution Properties: DistributionConfig: Origins: - Id: CustumOrigin DomainName: !Sub '${HostnamePrefix}-media-${AWS::Region}-${AWS::AccountId}.s3-website-${AWS::Region}.amazonaws.com'
- ELBオリジンのDistribution、通過させるヘッダとクッキーは下記のAWSブログを参考に設定しました。
How to accelerate your WordPress site with Amazon CloudFront
ForwardedValues: QueryString: true Headers: - Host - Origin - Access-Control-Request-Headers - Access-Control-Request-Method Cookies: Forward: whitelist WhitelistedNames: - comerment_author_* - comerment_author_email_* - comerment_author_url_* - wordpress_* - wordpress_logged_in_* - wordpress_test_cookie - wp-settings-*
- WordPressの管理画面はCloudFront経由では利用しないものとし、CloudFrontのBehevior設定により「/wp-admin/*」のリクエストはELBへの転送対象から除外しました。
- PathPattern: /wp-admin/* TargetOriginId: CustumOriginS3media
- WordPress 4.7 以降でサポートされた REST API「/wp-json」は通過させる設定としています。
- PathPattern: /wp-json/* TargetOriginId: CustomOrigin
S3
- 画像用のS3バケットは厳密なアクセス制限は不要な環境として、S3のWebホスティングを有効に設定しました。
S3BucketMedia: Type: AWS::S3::Bucket Properties: BucketName: !Sub '${HostnamePrefix}-media-${AWS::Region}-${AWS::AccountId}' WebsiteConfiguration: IndexDocument: index.html ErrorDocument: error.html
- バケットポリシーを利用して、CloudFrontを経由し、かつ、適切なリファラーをもつリクエストのみ画像S3の参照を許可する設定としました。
- Action: s3:GetObject Effect: Allow Resource: - !Sub 'arn:aws:s3:::${S3BucketMedia}/*' Principal: '*' Condition: StringEquals: aws:UserAgent: Amazon CloudFront aws:Referer: - !Sub 'https://${WPSiteURL}/*'
ELB
- ELBはNLBを採用、固定IP(EIP)を割り当てました。
NlbEIP: Type: AWS::EC2::EIP Properties: Domain: vpc NlbLoadBalancer: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: SubnetMappings: - AllocationId: !GetAtt 'NlbEIP.AllocationId' SubnetId: !Ref 'Ec2SubnetId' Type: network
EC2
- WordPressを稼働させるEC2は以下を踏襲しています。
- ELBとしてNLBを利用する為、EC2のセキュリティグループ設定はHTTP(TCP80)をインターネットに公開する設定としました。
端末設定
WordPressを操作するコンテンツ管理者は、自身が利用する端末の「hosts」を書き換える事で、CloudFront(CDN)を経由しないWordPressの利用が可能になります。
OSX設定例
$ cat /etc/hosts | grep -v "^#" 127.0.0.1 localhost 255.255.255.255 broadcasthost ::1 localhost xx.xx.xx.xx wp.example.com
xx.xx.xx.xx
は、NLBのEIP、wp.example.com
は、WordPressの公開FQDN(SITE_URL)に書き換えてください。
MacOSXでは、「hosts」設定をシステム環境設定と統合出来る「Hosts.prefpane」が便利です。
- 「Hosts.prefpane」 ダウンロード
- システム環境設定
- 設定画面
Windows
Windows OSでは、以下パスのhostsファイルをテキストエディタで編集してください。
C:\Windows\System32\drivers\etc\hosts
WordPress設定
Hosts 動作確認
- 「hosts」ファイルを設定した端末では、WordPress環境へのログインが可能になります。
S3プラグイン設定
- プラグイン一覧 WordPressのプラグイン、「WP Offload Media Lite」を有効化します。
- 「Setting」より設定画面を開き、「S3バケット」「Custom Domain (CNAME)」「Remove Files From Server」の設定を変更します。
- S3バケット設定
CloudFrontで作成したS3バケットを指定します。
S3BucketMedia: Type: AWS::S3::Bucket Properties: BucketName: !Sub '${HostnamePrefix}-media-${AWS::Region}-${AWS::AccountId}'
- Custom Domain (CNAME) 設定
画像用CloudFrontの公開FQDNを設定します。
CloudFrontDistributionMedia: Type: AWS::CloudFront::Distribution DependsOn: S3BucketMedia Properties: DistributionConfig: Aliases: - !Sub '${HostnamePrefix}-media.${DomainName}'
- Remove Files From Server
EC2のローカルからS3へのコピーが完了した画像ファイルは、EC2上から削除する設定とします。 他の画像加工を実施するWordPressプラグインと、今回導入する「WP Offload Media Lite」は干渉する可能性についてはご留意ください。
動作確認
WordPress編集
- メディアライブラリに画像ファイルを登録出来る事を確認します。
- 添付ファイルの詳細で、保存先として指定したS3バケットが利用されている事、及びリンクが画像用CloudFrontのURLに変更されている事を確認します。
- WordPressの「投稿」で記事が執筆できる事を確認します。
- ビジュアルエディタ、コードエディタ、共に利用できる事を確認します。
CloudFront 動作確認
- 「hosts」の修正を無効化し、CloudFront経由で記事が表示出来る事を確認します。
- Chromeの開発者ツールなどを利用して、「Response Headers」情報を確認し、CloudFrontにより付与されたヘッダ情報「X-Amz-Cf-Id:」「X-Cache:」が付与されている事を確認します。
性能比較
WordPressの初期サンプルページに約200KBの画像データを追加、Chromeの開発者モードで「キャッシュの廃棄とハード再読込」した所要時間を比較しました。
CloudFrontなし
- 所要時間 : 419ms
CloudFrontあり
- 所要時間 : 204ms
動的生成される「hello-world.html 」は202ms→16ms、約12倍。 S3に退避したJPEG画像も 162ms→17ms、約9倍の所要時間短縮が確認出来ました。
CloudFrontの圧縮機能が働いた「style.css」208KB→29KBまで転送容量が削減。総転送容量は363KB → 150 KBと半減しました。
今回の検証ページより多くの画像、CSS、JSなどで構成される実際のサイトでは、CloudFrontによるコンテンツ配信の最適化が期待できます。
まとめ
CloudFrontのキャッシュヒット率が高い状態を実現できれば、利用するEC2のスペックを変更しなくとも、 相当規模のリクエストを捌く事が出来る可能性があります。 コストを優先したWordPress環境が必要な場合にお試しください。
尚、今回の構成ではWordPressが動作するEC2が単一障害点となります。 高い可用性、信頼性を必要とする場合、StaticPressなどを利用して静的化したコンテンツをS3に配置して公開する利用をお試しください。
テンプレート
今回紹介した環境は、以下のCloudFormationテンプレートで展開可能です。
VPCはデフォルトVPCとそのサブネットで動作を確認しています。
Route53 の HostedZone (利用するドメイン) と、CloudFront、ELB用のACM証明書のARNは、事前に用意してご利用ください。