この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
概要
S3にホスティングされた静的コンテンツをCloudFront経由で配信してみようと思います。 今回はTerraformを用いてシステムの構築を行います。
CloudFrontとは
CloudFrontはAWSが提供するCDNで、世界中に配置されたエッジローケーションと呼ばれるデータセンターからコンテンツの配信を行うことでレイテンシーを抑えることができます。
S3だけでも静的コンテンツのホスティングは可能ですが、CloudFrontを用いることでより高いパフォーマンスで配信することが可能となります。 というのも、CloudFrontにはキャッシングやルーティングの最適化などが施されているためです。
詳しく知りたい方は以下の記事がおすすめです。
以下の流れ
今回使用するファイルは以下の3つです。
main.tf
s3.tf
cloud_front.tf
それぞれを順に見ていきましょう。
AWS Providerの設定
main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
ここではAWSをTerraformで使用するための設定を書いています。 これは自分の環境に合わせて書いてください。
S3
s3.tf
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を用いてオブジェクトをアップロードすることも可能です。
contents.tf
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
cloudfront.tf
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は多機能なのでこれからも勉強していきたいです。