Amazon を使用して VPC 経由で Amazon S3 バケット内の静的コンテンツを提供する CloudFront - AWS 規範ガイダンス

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

Amazon を使用して VPC 経由で Amazon S3 バケット内の静的コンテンツを提供する CloudFront

作成:エンジェル・エマニュエル・ヘルナンデス・セブリアン

環境:PoC またはパイロット

テクノロジー: コンテンツ配信、ネットワーク、セキュリティ、アイデンティティ、コンプライアンス、サーバーレス、ウェブおよびモバイルアプリ

AWS サービス: Amazon CloudFront、Elastic Load Balancing (ELB)、AWS Lambda

[概要]

Amazon Web Services (AWS) でホストされている静的コンテンツを提供する場合、推奨されるアプローチは、Amazon Simple Storage Service (S3) バケットをオリジンとして使用し、Amazon を使用してコンテンツを配信 CloudFront することです。このソリューションには主に 2 つの利点があります。エッジロケーションで静的コンテンツをキャッシュする利便性と、 CloudFront ディストリビューションのウェブアクセスコントロールリスト (ウェブ ACLsを定義する機能です。これにより、最小限の設定と管理オーバーヘッドでコンテンツへのリクエストを保護できます。

ただし、標準的な推奨アプローチには、アーキテクチャ上の共通の制限があります。環境によっては、仮想プライベートクラウド (VPC) に仮想ファイアウォールアプライアンスをデプロイして、静的コンテンツを含むすべてのコンテンツを検査したい場合があります。標準的なアプローチでは、トラフィックを VPC 経由でルーティングして検査することはありません。このパターンは、アーキテクチャ上の代替ソリューションとなります。ディス CloudFront トリビューションを使用して S3 バケット内の静的コンテンツを提供しますが、トラフィックは Application Load Balancer を使用して VPC 経由でルーティングされます。次に、AWS Lambda 関数が S3 バケットからコンテンツを取得して返します。

前提条件と制限

前提条件

  • アクティブなAWS アカウント

  • S3 バケットにホストされた静的ウェブサイト内容

制約事項

  • このパターンのリソースは単一の AWS リージョンにある必要がありますが、異なる AWS アカウントにプロビジョニングできます。

  • 制限は、Lambda 関数が受信および送信できるリクエストとレスポンスの最大サイズにそれぞれ適用されます。詳細については、「ターゲットとしての Lambda 関数の制限」 (Elastic Load Balancing ドキュメント)」を参照してください。

  • このアプローチを使用するときは、パフォーマンス、スケーラビリティ、セキュリティ、費用対効果のバランスを取ることが重要です。Lambda はスケーラビリティが高いにもかかわらず、Lambda の同時呼び出しの数が最大クォータを超えると、一部のリクエストがスロットされます。詳細については、Lambda のクォータ(Lambda ドキュメント)を参照してください。Lambda を使用する場合は価格設定も考慮する必要があります。Lambda 呼び出しを最小限に抑えるには、 CloudFront ディストリビューションのキャッシュを適切に定義してください。詳細については、「キャッシュと可用性の最適化 (CloudFront ドキュメント)」を参照してください。

アーキテクチャ

ターゲットテクノロジースタック

  • CloudFront

  • Amazon Virtual Private Cloud (Amazon VPC)

  • Application Load Balancer

  • Lambda

  • Amazon S3

ターゲット アーキテクチャ

次の図は、 CloudFront を使用して VPC 経由で S3 バケットから静的コンテンツを配信する必要がある場合に推奨されるアーキテクチャを示しています。

トラフィックは VPC のApplication Load Balancerを経由して Lambda 関数に流れます。
  1. クライアントは、S3 バケット内の特定のウェブサイトファイルを取得するように CloudFront ディストリビューションの URL をリクエストします。

  2. CloudFront はリクエストを AWS WAF に送信します。AWS WAF は、 CloudFront ディストリビューションに適用されたウェブ ACLs を使用してリクエストをフィルタリングします。リクエストが有効であると判断された場合、フローは続行されます。リクエストが無効であると判断された場合、クライアントは 403 エラーを受け取ります。

  3. CloudFront は内部キャッシュをチェックします。受信したリクエストに一致する有効なキーがある場合、関連する値が応答としてクライアントに送り返されます。そうでなければ、フローは続行されます。

  4. CloudFront は、指定された Application Load Balancer の URL にリクエストを転送します。

  5. Application Load Balancer には、Lambda 関数に基づいてターゲットグループに関連付けられたリスナーがあります。Application Load Balancer は Lambda 関数を呼び出します。

  6. Lambda 関数は S3 バケットに接続して GetObject 操作を実行し、コンテンツをレスポンスとして返します。

自動化とスケール

このアプローチを使用して静的コンテンツのデプロイを自動化するには、CI/CD パイプラインを作成して、ウェブサイトをホストする Amazon S3 バケットを更新します。

Lambda 関数は、サービスのクォータと制限の範囲内で、同時リクエストを処理するように自動的にスケーリングします。詳細については、「Lambda 関数のスケーリング」 と「Lambda クォータ」 (Lambda ドキュメント) を参照してください。や Application Load Balancer などの他の AWS のサービス CloudFront や機能については、AWS によって自動的にスケーリングされます。 Application Load Balancer

ツール

  • Amazon CloudFront は、世界中のデータセンターネットワークを通じてウェブコンテンツを配信することで、ウェブコンテンツの配信を高速化します。これにより、レイテンシーが短縮され、パフォーマンスが向上します。

  • Elastic Load Balancing (ELB)」 は、受信するアプリケーションまたはネットワークのトラフィックを複数のターゲットに分散します。このパターンでは、Elastic ロードバランサーを通じてプロビジョニングされた 「Application Load Balancer」 を使用して、トラフィックを Lambda 関数に転送します。

  • AWS Lambda は、サーバーのプロビジョニングや管理を行うことなくコードを実行できるコンピューティングサービスです。必要に応じてコードを実行し、自動的にスケーリングするため、課金は実際に使用したコンピューティング時間に対してのみ発生します。

  • Amazon Simple Storage Service (Amazon S3) は、どのようなデータ量であっても、データを保存、保護、取得することを支援するクラウドベースのオブジェクトストレージサービスです。

  • Amazon Virtual Private Cloud (Amazon VPC) を使用すると、定義した仮想ネットワーク内で AWS リソースを起動できます。この仮想ネットワークは、お客様自身のデータセンターで運用されていた従来のネットワークに似ていますが、AWS のスケーラブルなインフラストラクチャを使用できるというメリットがあります。

エピック

タスク説明必要なスキル

VPC を作成します。

Application Load Balancer や Lambda 関数など、このパターンでデプロイされたリソースをホストするための VPC を作成します。 手順については、「 VPC の作成」 (Amazon VPC ドキュメント)を参照してください。

クラウドアーキテクト

AWS WAF Web ACL を作成する

AWS WAF Web ACL を作成する このパターンの後半では、このウェブ ACL を CloudFront ディストリビューションに適用します。手順については、「ウェブ ACL の作成」 (AWS WAF ドキュメント) を参照してください。

クラウドアーキテクト

Lambda 関数を作成します。

S3 バケットでホストされている静的コンテンツをウェブサイトとして提供する Lambda 関数を作成します。このパターンの 「追加情報」 セクションに記載されているコードを使用してください。ターゲット S3 バケットを識別するようにコードをカスタマイズします。

AWS 全般

Lambda 関数をアップロードします。

次のコマンドを入力して、Lambda 関数コードを Lambda の.zip ファイルアーカイブにアップロードします。

aws lambda update-function-code \ --function-name \ --zip-file fileb://lambda-alb-s3-website.zip
AWS 全般

Application Load Balancer を作成します。

Lambda 関数を指すインターネット向けApplication Load Balancer を作成します。手順については、「Lambda 関数のターゲットグループの作成」 (Elastic ロードバランサー ドキュメント) を参照してください。高可用性構成の場合は、Application Load Balancer を作成し、それをさまざまなアベイラビリティーゾーンのプライベートサブネットにアタッチします。

クラウドアーキテクト

CloudFront ディストリビューションを作成します。

作成した Application Load Balancer を指す CloudFront ディストリビューションを作成します。

  1. AWS マネジメントコンソールにサインインし、https://console.aws.amazon.com/cloudfront/v3/home で CloudFront コンソールを開きます。

  2. [Create Distribution] を選択します。

  3. [Create Distribution Wizard (ディストリビューションの作成ウィザード)] の最初のページで、[Web (ウェブ)] セクションの [Get Started (今すぐ始める)] を選択します。

  4. ディストリビューションの設定項目を指定します。詳細については、「ディストリビューションを作成または更新する場合に指定する値」を参照してください。次の点に注意してください。

    1. Application Load Balancer をオリジンとして設定します。

    2. ディストリビューション設定で、AWS WAF を通じて適用する既存のウェブ ACL を選択します。詳細については、「AWS WAF のウェブ ACL」を参照してください。

  5. 変更を保存します。

  6. がディストリビューション CloudFront を作成すると、ディストリビューションのステータス列の値が からデプロイ済み InProgressに変わります。ディストリビューションを有効にするように選択した場合、ステータスが [Deployed (デプロイ済み)] に切り替わると、リクエストを処理する準備ができています。

クラウドアーキテクト

関連リソース

AWS ドキュメント

AWS サービスウェブサイト

追加情報

コード

次の例のLambda 関数が Node.js で記述されます。この Lambda 関数は、ウェブサイトリソースを含む S3 バケットに対して GetObject 操作を実行するウェブサーバーとして機能します。

/** * This is an AWS Lambda function created for demonstration purposes. * It retrieves static assets from a defined Amazon S3 bucket. * To make the content available through a URL, use an Application Load Balancer with a Lambda integration. * * Set the S3_BUCKET environment variable in the Lambda function definition. */ var AWS = require('aws-sdk'); exports.handler = function(event, context, callback) { var bucket = process.env.S3_BUCKET; var key = event.path.replace('/', ''); if (key == '') { key = 'index.html'; } // Fetch from S3 var s3 = new AWS.S3(); return s3.getObject({Bucket: bucket, Key: key}, function(err, data) { if (err) { return err; } var isBase64Encoded = false; var encoding = 'utf8'; if (data.ContentType.indexOf('image/') > -1) { isBase64Encoded = true; encoding = 'base64' } var resp = { statusCode: 200, headers: { 'Content-Type': data.ContentType, }, body: new Buffer(data.Body).toString(encoding), isBase64Encoded: isBase64Encoded }; callback(null, resp); } ); };