CloudFront + S3のWebサイトをTerraformで構築する
概要
S3にホスティングされた静的コンテンツをCloudFront経由で配信してみようと思います。 今回はTerraformを用いてシステムの構築を行います。
CloudFrontとは
CloudFrontはAWSが提供するCDNで、世界中に配置されたエッジローケーションと呼ばれるデータセンターからコンテンツの配信を行うことでレイテンシーを抑えることができます。
S3だけでも静的コンテンツのホスティングは可能ですが、CloudFrontを用いることでより高いパフォーマンスで配信することが可能となります。 というのも、CloudFrontにはキャッシングやルーティングの最適化などが施されているためです。
詳しく知りたい方は以下の記事がおすすめです。
以下の流れ
今回使用するファイルは以下の3つです。
main.tf
s3.tf
cloud_front.tf
それぞれを順に見ていきましょう。
AWS Providerの設定
terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 3.0" } } } provider "aws" { region = "ap-northeast-1" }
ここではAWSをTerraformで使用するための設定を書いています。 これは自分の環境に合わせて書いてください。
S3
resource "aws_s3_bucket" "bucket" { bucket_prefix = "static-www" acl = "private" website { index_document = "index.html" error_document = "error.html" } } resource "aws_s3_bucket_policy" "bucket" { bucket = aws_s3_bucket.bucket.id policy = data.aws_iam_policy_document.static-www.json } data "aws_iam_policy_document" "static-www" { statement { sid = "Allow CloudFront" effect = "Allow" principals { type = "AWS" identifiers = [aws_cloudfront_origin_access_identity.static-www.iam_arn] } actions = [ "s3:GetObject" ] resources = [ "${aws_s3_bucket.bucket.arn}/*" ] } }
ここではコンテンツ(今回はHTML)を置いておくためのS3バケットの設定を行っています。個人的に重要だと思ったポイントは以下の通りです
- ACLは
private
に- 後述のAmazon CloudFront Origin Accecc Identityによってアクセスするので
private
でも問題ないです
- 後述のAmazon CloudFront Origin Accecc Identityによってアクセスするので
website
でホスティングに対応- インデックスとエラーページを設定できます
aws_cloudfront_origin_access_identity
で公開する- 極端に言うとCloudFrontのみがアクセスできればページは公開できます
aws_cloudfront_origin_access_identity
はCloudFrontが使用する認証情報ですGetObject
さえできればCloudFrontはユーザーに渡すコンテンツを入手できます
今回はバケットにコンテンツをアップロードすることを考えていませんが、適切に権限を設定した対象を作成し、バケットポリシーに追加することで可能となります。 また、Terraformを用いてオブジェクトをアップロードすることも可能です。
resource "aws_s3_bucket_object" "index_page" { bucket = aws_s3_bucket.bucket.id key = "index.html" source = "www/index.html" content_type = "text/html" etag = filemd5("www/index.html") }
ここではindex用のHTMLをバケットに追加しています。ファイルはお好きなHTMLファイルを指定してください。content_type
は目的によって適切なMIME Typeを設定しましょう。例えばPNGならimage/png
などです。
CloudFront
resource "aws_cloudfront_distribution" "static-www" { origin { domain_name = aws_s3_bucket.bucket.bucket_regional_domain_name origin_id = aws_s3_bucket.bucket.id s3_origin_config { origin_access_identity = aws_cloudfront_origin_access_identity.static-www.cloudfront_access_identity_path } } enabled = true default_root_object = "index.html" default_cache_behavior { allowed_methods = [ "GET", "HEAD" ] cached_methods = [ "GET", "HEAD" ] target_origin_id = aws_s3_bucket.bucket.id forwarded_values { query_string = false cookies { forward = "none" } } viewer_protocol_policy = "redirect-to-https" min_ttl = 0 default_ttl = 3600 max_ttl = 86400 } restrictions { geo_restriction { restriction_type = "whitelist" locations = [ "JP" ] } } viewer_certificate { cloudfront_default_certificate = true } } resource "aws_cloudfront_origin_access_identity" "static-www" {}
ここではCloudFrontの設定を行っています。個人的に重要だと思ったポイントは以下の通りです。
origin
で配信元を設定- ドメインで配信元を指定する。ここではS3のバケットのドメインになっている
s3_origin_config
内でS3ににアクセスする認証情報を指定
default_cache_behavior
でキャッシングを設定allowed_methods
で取り扱うHTTPメソッドを制御cached_methods
でキャッシュするメソッドを制御forarded_values
でクッキー、ヘッダー、クエリパラメータの転送を制御viewer_protocol_policy
でアクセス方法を制御。今回はHTTPSにリダイレクトする- ttlでキャッシュの有効期限を設定
restriction
で配信地域を制御viewer_certificate
で証明書を管理- 今回は
cloud_front
のドメインを使用しているので、cloudfront_default_certificate
で設定可能 - ACMを用いて証明書を設定することもできる
- 今回は
ここでは紹介しきれなかったCloudFrontの機能がたくさんあるので、Terraformのリファレンスで確認してみてください。
感想
CloudFront + S3という構成でWebページをホスティングすることができました。 両者ともフルマネージドサービスなので、サーバーの管理が不要なのがいいと思いました。 CloudFrontは多機能なのでこれからも勉強していきたいです。