
CloudFront対応のWordPress、Host設定でELB直接続も可能な環境を構築してみた
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
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は、事前に用意してご利用ください。











