CloudFrontキャッシュでオリジンサーバのパフォーマンス向上

目次

CloudFrontキャッシュを使用して、オリジンサーバに対するリクエスト数を抑える構成

AWS SAAの出題範囲の1つでもある、高性能アーキテクチャの設計に関する内容です。
オリジンサーバの前面にCloudFrontを配置し、コンテンツをキャッシュさせ、オリジンサーバのパフォーマンス向上を図ります。

構成する環境

Diagram of improved origin server performance with CloudFront cache.

パブリックサブネットにEC2インスタンス(Amazon Linux 2)を設置します。インスタンスにApacheをインストールし、Webサーバとして動作させます。
その前面にCloudFrontを配置し、インスタンスのコンテンツをキャッシュさせます。

CloudFormationテンプレートファイル

上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートファイルを設置しています。

https://github.com/awstut-an-r/awstut-saa/tree/main/02/005

テンプレートファイルのポイント解説

VPCのDNS機能を有効化する

EC2インスタンスにホスト名でアクセスできるように設定します。

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VPCCidrBlock
      EnableDnsHostnames: true
      EnableDnsSupport: true
Code language: YAML (yaml)

VPCではさまざまな機能を提供していますが、その内の1つにDNSに関するものがあります。

VPC 内に起動したインスタンスにパブリック IPv4 アドレスがあり、VPC の DNS ホスト名と DNS サポート属性の両方が true に設定されている場合、そのインスタンスはパブリック DNS ホスト名を受け取ります。

VPC の DNS サポート

DNS機能を設定する理由は、EC2インスタンスのパブリックDNSホスト名が必要だからです。
後述のCloudFrontのオリジンサーバの指定では、このパブリックDNSホスト名を使います。

VPCでDNS機能を有効するためには、以下の2つのパラメータをどちらも有効に設定する必要があるとされています。

enableDnsHostnames
パブリック IP アドレスを持つインスタンスが、対応するパブリック DNS ホスト名を取得するかどうか示します。

enableDnsSupport
DNS 解決がサポートされているかどうかを示します。

VPC 内の DNS 属性

上記に従い、EnableDnsHostnamesプロパティおよびEnableDnsSupportプロパティにtrueに設定します。

EC2インスタンスにEIPを付与する

EC2インスタンスを確認します。
ポイントは固定アドレスを付与する点です。

Resources:
  EIP:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc

  EIPAssociation:
    Type: AWS::EC2::EIPAssociation
    Properties:
      AllocationId: !GetAtt EIP.AllocationId
      InstanceId: !Ref Instance

  Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref ImageId
      InstanceType: !Ref InstanceType
      NetworkInterfaces:
        - DeviceIndex: 0
          SubnetId: !Ref PublicSubnet
          GroupSet:
            - !Ref InstanceSecurityGroup
      UserData: !Base64 |
        #!/bin/bash -xe
        yum update -y
        yum install -y httpd
        systemctl start httpd
        systemctl enable httpd
        ec2-metadata -i > /var/www/html/index.html


Outputs:
  InstancePublicDnsName:
    Value: !GetAtt Instance.PublicDnsName
Code language: YAML (yaml)

インスタンスに固定的にIPアドレスを割り当てます。
先述のパブリックDNSホスト名は、パブリックアドレスに基づいて作成されます。そのためパブリックアドレスが動的に変更されると、それに釣られて、パブリックDNSホスト名も変更される恐れがあります。
固定的にパブリックアドレスを付与するためには、Elastic IPを使用します。Elastic IPを定義後、EC2インスタンスに関連付けます。

CloudFrontのオリジンにEC2インスタンスを設定する

まずCloudFrontのオリジンサーバの指定方法を確認します。

Resources:
  Distribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Origins:
          - CustomOriginConfig:
              OriginProtocolPolicy: http-only
            DomainName: !Ref InstancePublicDnsName
            Id: !Ref InstancePublicDnsName
Code language: YAML (yaml)

オリジンサーバの指定は、Originsプロパティで行います。
DomainNameプロパティで、オリジンサーバのドメイン名を指定します。今回はEC2インスタンスのパブリックDNSホスト名を指定します。
CustomOriginConfigプロパティにて、CloudFrontがオリジンサーバにアクセスする際の挙動を変更することができます。今回はオリジンサーバであるEC2インスタンスは、HTTPSではなく、HTTPリクエストをリッスンしています。そのためOriginProtocolPolicyプロパティに「http-only」と設定します。
Idプロパティでオリジンサーバに割り当てるIDを指定します。今回はインスタンスのパブリックDNSホスト名を指定します。この値は、後述のキャッシュ設定で使用します。

CloudFrontのキャッシュ設定

最後にキャッシュ設定を行います。

Resources:
  Distribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        DefaultCacheBehavior:
          AllowedMethods:
            - GET
            - HEAD
          CachedMethods:
            - GET
            - HEAD
          Compress: true
          ForwardedValues:
            Cookies:
              Forward: none
            QueryString: false
          TargetOriginId: !Ref InstancePublicDnsName
          ViewerProtocolPolicy: allow-all
          DefaultTTL: !Ref CacheTTL
          MaxTTL: !Ref CacheTTL
          MinTTL: !Ref CacheTTL
Code language: YAML (yaml)

今回はEC2インスタンスだけがオリジンサーバです。そのためDefaultCacheBehaviorプロパティを設定することで、本CloudFrontディストリビューションのデフォルトキャッシュ設定を行います。
AlloedMethodsプロパティで本ディストリビューションで許可するHTTPメソッドを指定します。本プロパティに設定する値は、受け付けるメソッドのパターンによって定められています。

A complex type that controls which HTTP methods CloudFront processes and forwards to your Amazon S3 bucket or your custom origin. There are three choices:

・CloudFront forwards only GET and HEAD requests.
・CloudFront forwards only GET, HEAD, and OPTIONS requests.
・CloudFront forwards GET, HEAD, OPTIONS, PUT, PATCH, POST, and DELETE requests.

AWS::CloudFront::Distribution DefaultCacheBehavior

今回はGETのみ受け付けることとします。よってGETおよびHEADを指定します。

CachedMethodsプロパティも同様です。キャッシュに対応するメソッドに応じて、本プロパティに設定する値が決まります。

A complex type that controls whether CloudFront caches the response to requests using the specified HTTP methods. There are two choices:

・CloudFront caches responses to GET and HEAD requests.
・CloudFront caches responses to GET, HEAD, and OPTIONS requests.

AWS::CloudFront::Distribution DefaultCacheBehavior

こちらもGETおよびHEADを指定します。

TargetOriginIdプロパティで、本キャッシュ設定に対応するオリジンサーバを指定します。今回はEC2インスタンスをオリジンサーバとしますので、先述のOriginsプロパティ内の、Idプロパティで指定した値を、こちらにも指定します。

ViewerProtocolPolicyプロパティで、TargetOriginIdプロパティにアクセスする際に、ユーザーから受け付けるHTTPプロトコルを指定できます。今回はHTTPおよびHTTPSを受け付けます。この場合ですと「allow-all」を指定することで、両者を受け付けることができるようになります。
なお本プロパティは、ユーザー〜CloudFront間のHTTPプロトコルに関する設定です。CloudFront〜オリジンサーバ間に関しては、先述の通り、Originsプロパティの方で設定します。今回はユーザーがHTTP・HTTPSどちらのプロトコルでCloudFront向けに通信を行った場合でも、CloudFrontはHTTPでオリジンサーバと通信を行うという挙動になります。

最後にキャッシュのTTLを設定します。3つのプロパティ(DefaultTTL, MaxTTL, MinTTL)でキャッシュの生存時間を設定可能です。今回はいずれも「60(秒)」とします。

環境構築

CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。

CloudFormationスタックを作成し、スタック内のリソースを確認する

CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。

あわせて読みたい
CloudFormationのネストされたスタックで環境を構築する 【CloudFormationのネストされたスタックで環境を構築する方法】 CloudFormationにおけるネストされたスタックを検証します。 CloudFormationでは、スタックをネストす...

各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。

  • インスタンスのID:i-08665eb4768e384ec
  • インスタンスのパブリックDNSホスト名:ec2-35-74-46-156.ap-northeast-1.compute.amazonaws.com
  • CloudFrontディストリビューションのドメイン名:https://d3julxofsz7qa5.cloudfront.net

AWS Management Consoleからも、リソースの作成状況を確認します。
まずEC2インスタンスの状況を確認します。

The public DNS hostname of the EC2 instance is enabled.

EIPが割り当てられていることと、パブリックDNSホスト名が有効化されていることがわかります。

次にCloudFrontを確認します。

A domain name is assigned to the CloudFront distribution.

CloudFrontに割り当てられたドメイン名を確認することができます。

An EC2 instance is registered as the origin of CloudFront.

ディストリビューションのオリジンとして、EC2インスタンスが設定されています。

An EC2 instance is registered as the default CloudFront behavior.

デフォルトのパスパターンにEC2インスタンスが指定されています。

挙動確認1:直接EC2インスタンスにアクセス

準備が整いました。
まずEC2インスタンスに直接アクセスします。

Direct access to EC 2 instances.

インスタンスから応答が返ってきました。

HTTPリクエスト時の挙動を確認します。

Result of accessing the EC 2 instance directly.

インスタンスのパブリックDNSホスト名にアクセスすると、インスタンスのEIPに向かってトラフィックが流れていることがわかります。

挙動確認2:CloudFront経由でEC2インスタンスにアクセス

最後にCloudFrontに対してアクセスします。

Access to EC 2 instances via CloudFront.

こちらもインスタンスから応答が返ってきました。

HTTPリクエスト時の挙動も確認します。

Result 1 of accessing an EC2 instance via CloudFront.

CloudFrontにアクセスすると、エッジロケーション経由でアクセスしていることがわかります。
キャッシュの項目を見ると、「Miss front cloudfront」とあります。初回のアクセスのため、コンテンツがキャッシュされていなかった他mです。

改めてCloudFront経由でアクセスします。

Result 2 of accessing an EC2 instance via CloudFront.

2回目以降は「Hit front cloudfront」となります。
これはHTTPリクエストに対して、CloudFrontにキャッシュされたコンテンツが返されているということを意味しています。
つまりオリジンサーバであるEC2インスタンスに対しては、リクエストは届かないということになり、サーバのパフォーマンス向上が見込めます。

まとめ

EC2インスタンスの前面に、CloudFrontを配置する構成を確認しました。

目次