CloudFront対応のWordPress、Host設定でELB直接続も可能な環境を構築してみた

2019.05.22

この記事は公開されてから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は以下を踏襲しています。

常時HTTPSに対応したWordPress環境をCloudFormationで設置してみた

  • 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」が便利です。

  • システム環境設定

  • 設定画面

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に配置して公開する利用をお試しください。

StaticPress プラグインで静的 HTML を生成して Amazon S3 で公開してみる

テンプレート

今回紹介した環境は、以下のCloudFormationテンプレートで展開可能です。

VPCはデフォルトVPCとそのサブネットで動作を確認しています。

Route53 の HostedZone (利用するドメイン) と、CloudFront、ELB用のACM証明書のARNは、事前に用意してご利用ください。