AWSとCDNの話。 - CloudFrontを使ってアクセス元の国ごとにコンテンツを振り分ける構成を組む -

記事タイトルとURLをコピーする

こんにちは。2016年1月より、法人営業課で修行中の橋本です。

昨年担当した案件で、掲題の要件を検証する機会に恵まれましたので、その内容を記事にしてみました。

結論としては、国ごとでコンテンツを振り分ける実装は、ELBオリジンを活用することで条件付きで実現が可能です。

はじめに

この記事ではCloudFrontとS3を使ったWebサイトの構築を題材にしています。 CloudFrontやS3について、ある程度理解のある読者の方をターゲットにしています。

CloudFront

AWSが提供するCDN(Contents Derivery Network)サービスです。 コンテンツのオリジンとして、S3とELBを持つことができます。

CDNには akamai ION や akamai Dynamic Site Accelerator などの素晴らしいプロダクトがありますが、 CloudFrontを利用する大きな動機は、AWSサービスのみで実装を完結できる点や他のAWSサービスとの連携が良いことであると考えています。

後者についての例を補足すると、バックエンドのS3に対して直接アクセスされることを避けたい、といったユースケースが考えられます。 CloudFrontではOAI (Origin Access Identity)を作ってS3のバケットポリシーに反映することで簡単に実装が可能です。実装は全てマネジメントコンソール上で行えますし、バケットポリシーの適用もCloudFront側で数回ポチポチすればオッケーです。ハードルはそう高くないでしょう。

S3

これからCloudFrontを使ってみよう、という読者の方にはS3を今更説明することもないでしょう。

地味な話ですが、S3のWebsite-Hostingは有効/無効のどちらに設定していてもCloudFrontのオリジンとして設定可能です。

両者の間にはできることに違いがあります。それについては下記の公式ドキュメントに記載がありますので、そちらに譲ります。 > https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/DownloadDistS3AndCustomOrigins.html

やりたいこと

CloudFrontで受けたHTTP(S)リクエストを、アクセス元の国に応じてルーティングします。

ここでは、ルートパスへのアクセスを自動的にユーザの言語日本からのアクセスを /jp にルーティングし、 それ以外の国からのアクセスを /en にルーティングする構成を作ってみます。今回の実装によって、トップページ(ルートパス)へのアクセス時にユーザーを対応言語サイトに誘導できるようになります。

構成

下図のような構成を取ります。 ユーザーからルートパスへのリクエストがあった時(図中青色の矢印)、そのユーザーに表示すべき言語のトップページにリダイレクトします。 ユーザーはリダイレクト先をリクエストし、適切な言語でページを閲覧することが可能になります(図中緑色の矢印)。

cf-country-based-routing

S3では、日本語サイトと英語サイトのコンテンツを保持してます。ルートに /jp と /en の言語別ディレクトリがあり、それぞれの下に同じ構造を持ったコンテンツが配置されている想定です。

ELB配下のEC2には Nginx をインストールします。 Nginxの役目は、ユーザーがアクセスしてきた国を認識し、言語別サイトのトップに誘導(リダイレクト)することです。

ポイント

アクセス元の国に関する情報は、CloudFront側でCloudFront-Viewer-Countryヘッダを付与することで取得できるようになります。ただし、CloudFront自身はこのヘッダの値に基づいて、動的にリクエストのルーティングを行う手段を持ち合わせていません。執筆時点でルーティングに使える手段はリクエストパスをベースにした機能のみです。よって、CloudFront-Viewer-CountryヘッダをELBオリジンに転送し、自前のプロキシ(Nginx)によってルーティングのルールを規定してやる必要があります。

手順

今回はルートパスに対してのアクセスを振り分けられればよいので話はシンプルです。

  • VPCの構築
  • ELBの設定
  • EC2のセットアップ
    • Nginxのインストール
    • 自動起動の設定
  • ELBへのインスタンス紐付け
  • S3へのコンテンツの配置(Website-Hosting の有効/無効は問わず)

これらの作業は完了している前提とします。

全体の手順は以下のようになります。

  1. CloudFront側の設定
    1. デフォルトオリジンの設定
    2. ヘッダの転送設定
    3. S3オリジンの追加とバケットポリシーの更新
    4. Default Root Object の設定
  2. Nginxの設定

CloudFrontの設定

(1) CloudFrontのWebディストリビューションを作成します。最初のOrigin設定についてはELBを選択しましょう。

(2) ヘッダの転送設定

CloudFront-Viewer-CountryヘッダをELBオリジンに転送する設定を行います。下図の要領です。

cf-settings-cf-viewer-country

(3) S3オリジンの追加

S3バケットをOriginに追加します。 "Origin Domain Name" の項目をクリックし、コンテンツを配置するバケットを選択します(入力補完が効くため簡単に選択可能です)。

今回はCloudFront経由のアクセスのみ許可するように設定します。 "Restrict Bucket Access" の項目を "Yes" にし、OAIを割り当てます。 "Grant Read Rermssions on Bucket" の項目で "Yes, Update Bucket Policy" を選択すると、バケットポリシーが更新されるようになります。

cf-update-bucket-policy

(4) Default Root Object の設定

名前の通り、ルートパスをリクエストされた時に返すべきオブジェクトを指定する設定項目です。必須ではありませんが、これをやらないと "/" へのリクエストを正常に処理できなくなってしまいますので、必要であれば "index.html" などの値を設定すると良いでしょう。

Nginxのリダイレクトルール設定

virtual.confを設定します。下記のような記述が一例です。

server {
listen 80 default_server;
listen   localhost:80;
server_name  default.proxy;


index index.html;

# JP routing

if ($http_cloudfront_viewer_country = JP) {
rewrite ^(.*)$ http://mysite.com/jp$1 permanent;
}

# Other(EN)

rewrite ^(.*)$ http://mysite.com/en$1 permanent;

access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
}

CloudFront-Viewer-Countryヘッダは $http_cloudfront_viewer_country で参照できます。 ヘッダの値を条件に if文 で分岐させ、rewriteによって日本(英語)サイトのサブディレクトリにリダイレクトさせる処理を行っています。

設定を反映したら、Nginxの再起動を行いましょう。以上で手順は完了です。

※AutoScalingを使う場合は、ここで設定したインスタンスからAMIを作成し、AutoScaling Group, Launch Configuration を設定します。

 

まとめと次回予告

今回は、「CloudFrontを使ってアクセス元の国ごとにコンテンツを振り分ける構成」の構築を行いました。 HTTPヘッダ(CloudFront-Viewer-Country)の値を元に、プロキシに振り分け先を判断させるところがポイントかと思います。

さて。 今回の構成では、HTTPヘッダに基づき、リクエストをルーティングするためのプロキシが必要でした。 できれば、ここはフルマネージドなクラウドサービスを使ってすべての実装を済ませてしまいたいところです。

この要件は、CDNサービスの1つであるFastlyを使うことで実現が可能です。Fastlyでは、VCL(Varnish Configurtion Language)という言語を使用し、リクエストヘッダ等による条件分岐の記述が可能です。

次回はこのFastlyを始めるための記事を書いてみようと思います。