1. ホーム
  2. 記事一覧
  3. 【Terraformハンズオン】AWS CloudFront&ALB構成を実現しよう

2024.06.17

【Terraformハンズオン】AWS CloudFront&ALB構成を実現しよう

Amazon CloudFrontは、動画、アプリケーション、どのユーザーにも同じ内容を返す静的コンテンツやユーザーによって返す内容を変化させる動的コンテンツをより高速で、遅延を少なくユーザーに提供するためのCDNContents Delivery Network)サービスです。

この記事では、CloudFrontとは何かを解説し、IaCInfrastructure as Code)を実現するためのツールであるTerraformを使ってCloudFrontを構築するまでのハンズオンを行います。

Amazon CloudFrontとは

Amazon CloudFrontとは、動画や画像などのコンテンツをユーザーへ効率よく返すことを可能にする、AWSが提供するフルマネージド型のサービスです。

CloudFrontはユーザーとコンテンツ配信元となるサーバー(オリジンサーバー)の間に位置しており、サーバーが配信するコンテンツをキャッシュとして保存しておくことができます。

ユーザーへこのキャッシュしているデータを返すため、サーバーへの直接的なアクセスを減らしてサーバーへの負荷を軽減することができます。

また、CloudFrontは世界各国に配置したエッジロケーションへキャッシュを保存することで、ユーザーから最も近い場所からデータを返すことができるため、レスポンスを高速化することが可能です。

出典: Amazon CloudFront の主な特徴 https://aws.amazon.com/jp/cloudfront/features/?whats-new-cloudfront.sort-by=item.additionalFields.postDateTime&whats-new-cloudfront.sort-order=desc

CloudFrontがない場合、ユーザーからのリクエストはつどオリジンサーバーへ送られるため、ユーザーが増えれば増えるほどサーバーへの負荷が増加します。

ユーザーからオリジンサーバーが遠ければ、その分レスポンスの遅延が発生することになります。日本に住んでいる人が、日本のサーバーにデータを取りに行けば高速なレスポンスが見込めますが、日本からアメリカのサーバーへデータを取りに行く場合、それだけ時間がかかってしまいます。

CDNとは

CDN(Contents Delivery Network) とは、インターネット上のコンテンツを高速配信するために連携して動作する、地理的に分散されたサーバーのグループのことです。Webページなどのコンテンツを提供するサーバーの代わりに、アクセスしてきたユーザーに対してコンテンツを配信します。

CDNに関しては以下の記事にて詳しく解説しています。

https://envader.plus/article/40

キャッシュとは

CDNやCloudFrontで必ず出てくる「キャッシュ」とは、貯蔵所、隠し場所などの意味があり、頻繁にアクセスされるデータを一時的に保存しておく仕組みのことです。

ユーザーからの最初のリクエストでは、オリジンサーバーからデータを取得します。その際、取得したデータをキャッシュとして保存しておきます。再度ユーザーから同じリクエストが来た場合、キャッシュとして保存しておいたデータをユーザーへ返します。

このように保存しておいたデータをユーザーへ返すことで、オリジンサーバーへのデータの再取得を減らし、結果として処理速度を向上させることができます。

キャッシュには大きく分けて「ブラウザキャッシュ」と「サーバーキャッシュ」の2つがあり、CloudFrontに該当するのはサーバーキャッシュになります。

CloudFrontが必要な理由

CloudFrontを利用する実際の現場では、複数のURLごとの細かいキャッシュ設定や、細かいパスごとのリクエストの転送先変更、CloudFrontの前段にAWS WAFを配置することでのサイバー攻撃対策などが行われています。

またCloudFrontはCloudWatchと統合されているため、簡単にCloudWatchダッシュボードを作成してメトリクスを確認することができます。インフラエンジニアとして運用を行う場合、メトリクスの監視は必須項目になるためこの点もCloudFrontを使うメリットと言えるでしょう。

CloudWatchについては次の記事で解説しています。

https://envader.plus/article/358

ここからは、CloudFrontの特徴をもう少し詳しく振り返ります。

レスポンス遅延の解消

ユーザーがリクエストを送信してからレスポンスが返ってくるまでの遅延(レイテンシ)は、ユーザー体験に大きな影響を与えます。コンテンツ配信元のサーバーがユーザーから遠ければ遠いほど、レスポンスの遅延が発生します。CloudFrontは地理的に分散されたエッジロケーションにキャッシュを保存することで、この遅延を最小限に抑えることができます。

大量アクセスへの対応

オリジンサーバーへ多くのユーザーが同時にアクセスする場合、サーバーにかかる負荷が大きくなり、ユーザーへのレスポンスが低下する可能性があります。CloudFrontでは頻繁にアクセスされるコンテンツをエッジロケーションにキャッシュしておき、エッジロケーションからユーザーに直接提供することができます。

このようにすることでオリジンサーバーへのアクセスを減らすことができ、コンテンツ配信元のサーバーへの負荷を軽減することができます。

効率的なキャッシュ管理

CloudFrontでは、URLごとにキャッシュ保持期間(TTL)を設定することが可能です。変更の少ないロゴや画像などの静的なコンテンツではTTLを長くしておくことで、オリジンサーバーへのリクエストを減らすことができます。

逆に、頻繁に変更が必要な動的コンテンツの場合、キャッシュ期間を短くしておくことで、最新のコンテンツを迅速に提供することも可能になります。

コンテンツへのアクセス制限

CloudFrontでは署名付きURL、署名付きCookieを利用することで非公開コンテンツとし、限定したユーザーのみにアクセスさせることも可能です。

https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html

また、AWS WAF(Web Application Firewall)と連携することで、XSS(クロスサイトスクリプティング)やSQLインジェクションなどのサイバー攻撃からオリジンサーバーを保護することができます。

XSSやSQLインジェクションなどセキュリティに関する内容は、以下記事にて解説しています。

https://envader.plus/article/115

ここまでCloudFrontの特徴を挙げてきました。

CloudFrontに出てくる用語を解説

CloudFrontには特徴的な用語がたくさん出てくるため、ここからは用語を解説していきます。

エッジロケーション

エッジロケーションとは、世界中で地理的に分散して配置されたデータセンターのことです。

2024年5月時点で日本やアメリカ、ブラジルなど世界50か国以上、100以上の都市に600以上のエッジロケーションが存在します。

https://aws.amazon.com/jp/about-aws/global-infrastructure/

オリジンの情報をキャッシュしておき、ユーザーに一番近い場所から提供する仕組みがエッジロケーションです。

この仕組みのおかげで、オリジンサーバーへの負荷軽減、世界中のユーザーへの配信を高速化することが可能です。

リージョナルエッジキャッシュ

リージョナルエッジキャッシュは、エッジロケーションとオリジンサーバーの間に位置するサーバーのことです。

エッジロケーションが増えると、その分複数のエッジロケーションからオリジンへのリクエストが来ることになり、オリジンの負荷が上昇してしまいます。

リージョナルエッジキャッシュが間に入ることで、エッジロケーションが増えてもオリジンへの問い合わせはリージョナルエッジキャッシュが行うため、負荷を軽減することができます。

オリジン

動画やアプリケーション、静的コンテンツなどの配信元となるサーバーのことです。

オリジンに指定できるのは、S3バケット、ALB、EC2など複数のサービスを指定することができ、オリジンを指定する際は対象のリソースのドメインを指定します。

https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/DownloadDistS3AndCustomOrigins.html

オリジンがS3の場合には、OAC(Origin Access Control)を使ってS3へのアクセスをCloudFrontからのみに限定することができます。

ALB、EC2などのカスタムオリジンでは、オリジンカスタムヘッダーを付与するか、オリジン側のIPアドレスを公開せずにCloudFrontが利用するIPアドレスのみ許可するセキュリティグループの設定をすることでオリジンを保護することが可能です。

ビヘイビア

CloudFrontがキャッシュ動作をどう振る舞うかの設定です。頻繁にアクセスがあるデータはキャッシュを長く、あまりアクセスのないデータはキャッシュを短くするなど、細かい設定をすることが可能です。

ビヘイビアではこのTTLの値をパスごとに細かく設定することができます。

ディストリビューション

ディストリビューションとは、オリジン、ビヘイビアなど、パスパターンや配信元をどこにするかなどの設定の集まりを意味します。

このディストリビューションには、デフォルトでxxx.cloudfront.netというドメイン名が割り当てられます。ディストリビューションをxxx.cloudfront.netで公開してユーザーにアクセスしてもらうことで、ユーザーからのリクエストが近くのエッジロケーションに送られ、エッジロケーションがオリジンへリクエストを転送してくれます。

デフォルトではxxx.cloudfront.netのドメインが割り当てられますが、CNAME(代替ドメイン名)を設定することで、別のドメイン(例: www.exampledomain.com)を公開することも可能です。

https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html

ビューワー

ビューワーは、アクセスしてくるブラウザなどの通信元(クライアント)を意味します。

「コンテンツを見に来る人」というイメージです。

CloudFrontハンズオン

ここからはTerraformを使って、CloudFrontを構築していきます。

以下、今回構築する内容になります。

  • AWSが提供するManaged Prefix ListからCloudFrontのIPアドレス一覧を取得
  • Managed Prefix ListのIPアドレスからの通信を許可するセキュリティグループの作成
  • ALBをCloudFrontからのアクセスのみ許可するため、CloudFrontにカスタムヘッダーを追加
  • ALBのリスナールールにCloudFrontで追加したHTTPヘッダーを追加

今回のコード全体は次のようになっています。

# main.tf
locals {

   region_azs    = ["ap-northeast-1a", "ap-northeast-1c"]
   instance_type = "t2.micro"
   ami_id        = "ami-02181a724aa2ad10b"
 }

 # CloudFrontのマネージドプレフィックスリストを取得
 data "aws_ec2_managed_prefix_list" "cloudfront" {
   name = "com.amazonaws.global.cloudfront.origin-facing"
 }

 # SSMパラメータストアの値を取得
 data "aws_ssm_parameter" "cloudfront_header_value" {
   name = "/cloudfront/custom_header_key"
 }

 # VPCの作成
 resource "aws_vpc" "myapp_vpc" {
   cidr_block           = "10.0.0.0/16"
   enable_dns_support   = true
   enable_dns_hostnames = true
   tags = {
     "Name" = "myapp_vpc"
   }
 }

 # Subnetsの作成
 resource "aws_subnet" "myapp_subnet_a" {
   vpc_id            = aws_vpc.myapp_vpc.id
   cidr_block        = "10.0.1.0/24"
   availability_zone = local.region_azs[0]
   tags = {
     "Name" = "myapp_subnet_a"
   }
 }
 resource "aws_subnet" "myapp_subnet_c" {
   vpc_id            = aws_vpc.myapp_vpc.id
   cidr_block        = "10.0.2.0/24"
   availability_zone = local.region_azs[1]
   tags = {
     "Name" = "myapp_subnet_c"
   }
 }

 # Internet Gateway
 resource "aws_internet_gateway" "myapp_igw" {
   vpc_id = aws_vpc.myapp_vpc.id
 }

 # Route Table
 resource "aws_route_table" "myapp_rt" {
   vpc_id = aws_vpc.myapp_vpc.id

   route {
     cidr_block = "0.0.0.0/0"
     gateway_id = aws_internet_gateway.myapp_igw.id
   }
 }

 # Route Tableの関連付け
 resource "aws_route_table_association" "myapp_rta" {
   subnet_id      = aws_subnet.myapp_subnet_a.id
   route_table_id = aws_route_table.myapp_rt.id
 }

 resource "aws_route_table_association" "myapp_rta2" {
   subnet_id      = aws_subnet.myapp_subnet_c.id
   route_table_id = aws_route_table.myapp_rt.id
 }

 # EC2 instancesのセキュリティグループ
 resource "aws_security_group" "myapp_ec2_sg" {
   vpc_id = aws_vpc.myapp_vpc.id
   ingress {
     from_port       = 0
     to_port         = 0
     protocol        = "-1"
     security_groups = [aws_security_group.myapp_alb_sg.id]
   }
   egress {
     from_port   = 0
     to_port     = 0
     protocol    = "-1"
     cidr_blocks = ["0.0.0.0/0"]
   }
   tags = {
     "Name" = "myapp_ec2_sg"
   }
 }

 # ALBのセキュリティグループ
 resource "aws_security_group" "myapp_alb_sg" {
   vpc_id = aws_vpc.myapp_vpc.id
   ingress {
     from_port       = 80
     to_port         = 80
     protocol        = "tcp"
     prefix_list_ids = [data.aws_ec2_managed_prefix_list.cloudfront.id]
   }
   egress {
     from_port   = 0
     to_port     = 0
     protocol    = "-1"
     cidr_blocks = ["0.0.0.0/0"]
   }
   tags = {
     "Name" = "myapp_alb_sg"
   }
 }

 # key-pair
 resource "aws_key_pair" "myapp_key_pair" {
   key_name   = "myapp_key_pair"
   public_key = file("~/.ssh/xxxxx.pub")
 }

 # 起動テンプレート
 resource "aws_launch_template" "myapp_launch_template" {
   name          = "myapp-lt"
   image_id      = local.ami_id
   instance_type = local.instance_type
   key_name      = aws_key_pair.myapp_key_pair.key_name

   user_data = base64encode(<<-EOF
               #!/bin/bash
               yum update -y
               amazon-linux-extras install -y nginx1.12
               echo "Hello, world" > /usr/share/nginx/html/index.html
               systemctl start nginx
               systemctl enable nginx
 EOF
   )
   network_interfaces {
     associate_public_ip_address = true
     security_groups             = [aws_security_group.myapp_ec2_sg.id]
   }

   tag_specifications {
     resource_type = "instance"
     tags = {
       "Name" = "myapp-instance"
     }
   }
 }

 # Autoscaling Group
 resource "aws_autoscaling_group" "myapp_asg" {
   name                      = "myapp-asg"
   max_size                  = 6
   min_size                  = 1
   desired_capacity          = 4
   health_check_grace_period = 300
   health_check_type         = "EC2"
   enabled_metrics           = ["GroupInServiceInstances"]
   launch_template {
     id      = aws_launch_template.myapp_launch_template.id
     version = "$Latest"
   }
   vpc_zone_identifier = [aws_subnet.myapp_subnet_a.id, aws_subnet.myapp_subnet_c.id]
   target_group_arns   = [aws_lb_target_group.myapp_tg.arn]
 }

 # Autoscaling Policy
 resource "aws_autoscaling_policy" "myapp_scale_out" {
   name                   = "myapp-scale-out"
   autoscaling_group_name = aws_autoscaling_group.myapp_asg.name
   policy_type            = "TargetTrackingScaling"

   target_tracking_configuration {
     predefined_metric_specification {
       predefined_metric_type = "ASGAverageCPUUtilization"
     }
     target_value = 50.0
   }
 }

 # ALBのリソース定義
 resource "aws_lb" "myapp_alb" {
   name                       = "myapp-alb"
   internal                   = false
   load_balancer_type         = "application"
   security_groups            = [aws_security_group.myapp_alb_sg.id]
   subnets                    = [aws_subnet.myapp_subnet_a.id, aws_subnet.myapp_subnet_c.id]
   enable_deletion_protection = false

   tags = {
     "Name" = "myappALB"
   }
 }

 # リスナーの設定
 resource "aws_lb_listener" "myapp_listener" {
   load_balancer_arn = aws_lb.myapp_alb.arn
   port              = 80
   protocol          = "HTTP"

   default_action {
     type = "fixed-response"

     fixed_response {
       content_type = "text/plain"
       message_body = "Not found"
       status_code  = "404"
     }
   }
 }

 # リスナールールの設定
 resource "aws_lb_listener_rule" "myapp_listener_rule" {
   listener_arn = aws_lb_listener.myapp_listener.arn
   priority     = 10

   action {
     type             = "forward"
     target_group_arn = aws_lb_target_group.myapp_tg.arn
   }

   condition {
     http_header {
       http_header_name = "X-Custom-Header" # CloudFrontからのリクエストヘッダーを指定
       values           = [data.aws_ssm_parameter.cloudfront_header_value.value]
     }
   }
 }

 # ターゲットグループの定義
 resource "aws_lb_target_group" "myapp_tg" {
   name     = "myapp-tg"
   port     = 80
   protocol = "HTTP"
   vpc_id   = aws_vpc.myapp_vpc.id

   health_check {
     enabled             = true
     interval            = 30
     path                = "/"
     protocol            = "HTTP"
     healthy_threshold   = 5
     unhealthy_threshold = 2
     timeout             = 5
     matcher             = "200"
   }

   tags = {
     "Name" = "myappTG"
   }
 }

 # CloudFront
 resource "aws_cloudfront_distribution" "myapp_cloudfront" {
   origin {
     domain_name = aws_lb.myapp_alb.dns_name
     origin_id   = "myappALB"

     custom_origin_config {
       http_port              = 80
       https_port             = 443
       origin_protocol_policy = "http-only"
       origin_ssl_protocols   = ["TLSv1", "TLSv1.1", "TLSv1.2"]
     }

     custom_header {
       name  = "X-Custom-Header" # CloudFrontに追加するカスタムヘッダーを指定
       value = data.aws_ssm_parameter.cloudfront_header_value.value
     }
   }

   enabled             = true
   is_ipv6_enabled     = true
   comment             = "CloudFront for MyApp"
   default_root_object = "index.html"

   default_cache_behavior {
     allowed_methods  = ["GET", "HEAD"]
     cached_methods   = ["GET", "HEAD"]
     target_origin_id = "myappALB"

     forwarded_values {
       query_string = false

       cookies {
         forward = "none"
       }
     }

     viewer_protocol_policy = "allow-all"
     min_ttl                = 0
     default_ttl            = 3600
     max_ttl                = 86400
   }

   restrictions {
     geo_restriction {
       restriction_type = "none"
     }
   }

   viewer_certificate {
     cloudfront_default_certificate = true # CloudFrontデフォルトの証明書を使用
   }
 }

 output "cloudfront_domain_name" {
   value = aws_cloudfront_distribution.myapp_cloudfront.domain_name
 }

 output "alb_dns_name" {
   value = aws_lb.myapp_alb.dns_name
 }

 output "aws_ec2_managed_prefix_list_attribute" {
   value = data.aws_ec2_managed_prefix_list.cloudfront
 }

ALB、Auto Scaling Groupの作成に関しては以下の記事にて解説しているため省略します。

https://envader.plus/article/356

https://envader.plus/article/366

今回はALBをCloudFrontからのアクセスのみ許可するよう、CloudFrontに追加するカスタムヘッダーの値を作成します。

CloudFrontはユーザーからリクエストがあった時に、キャッシュからデータを返すことでオリジンへの負荷を減らすことができます。

しかし、ユーザーが直接オリジンであるALBにアクセスできてしまっては、「負荷を軽減する」といったメリットが受けられません。

そのため今回は、CloudFrontでカスタムヘッダーを追加し、カスタムヘッダーを含むリクエストだけをターゲットグループへ転送するよう設定します。

CloudFront カスタムヘッダーの値を作成

カスタムヘッダーの値はランダムな値にする必要があるため、以下のパスワードジェネレーターなどで値を作成します。筆者は文字数を32文字で作成しました。

https://www.graviness.com/app/pwg/

カスタムヘッダーの値を保存する

作成した値はAWS Systems Manager パラメータストアに保存します。

AWS Systems Manager パラメータストアは、パスワードやデータベースの文字列など様々な値を安全に保存しておくことができる、AWS Systems Managerが提供する機能の一つです。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-parameter-store.html

今回はAWS CLIコマンドを使って、パラメータストアへ値を保存します。

nameではパラメータストアに保存する際の名前をパスで記述します。任意の名前にすることが可能です。

typeSecureStringとすることで、機密データとして保存することができ、valueで先ほど作成したランダムな値を入力します。

aws ssm put-parameter --name "/cloudfront/custom_header_key" --type "SecureString" --value "xxxxxxxxxxxx"

コマンドを実行できたら、パスを指定してパラメータが作成できたか確認します。正常に作成されていれば、値が表示されます。

aws ssm get-parameter --name "/cloudfront/custom_header_key"

Managed Prefix ListとSSM パラメータストアの値を取得する

Terraformのファイルを編集します。

dataブロックを使って、CloudFrontのManaged Prefix Listの値、パラメータストアに保存した値を取得します。

# CloudFrontのマネージドプレフィックスリストを取得
 data "aws_ec2_managed_prefix_list" "cloudfront" {
   name = "com.amazonaws.global.cloudfront.origin-facing"
 }

 # SSMパラメータストアの値を取得
 data "aws_ssm_parameter" "cloudfront_header_value" {
   name = "/cloudfront/custom_header_key"
 }

Managed Prefix Listとは、CloudFrontやDynamo DBなどのCIDRブロックの一覧のことで、この値を参照することでセキュリティグループやルートテーブルの設定が楽になります。

今回はCloudFrontのManaged Prefix Listを取得し、セキュリティグループルールにこのIPアドレスを許可するよう設定します。

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/managed-prefix-lists.html

ALB用セキュリティグループの設定

ALBにアタッチするセキュリティグループのインバウンドルールに、先ほど取得したManaged Prefix ListのIPアドレスを指定します。

こうすることで、インバウンドルールにCloudFrontからのIPアドレスを追加することができます。

# ALBのセキュリティグループ
 resource "aws_security_group" "myapp_alb_sg" {
   vpc_id = aws_vpc.myapp_vpc.id
   ingress {
     from_port       = 80
     to_port         = 80
     protocol        = "tcp"
     prefix_list_ids = [data.aws_ec2_managed_prefix_list.cloudfront.id]
   }
   egress {
     from_port   = 0
     to_port     = 0
     protocol    = "-1"
     cidr_blocks = ["0.0.0.0/0"]
   }
   tags = {
     "Name" = "myapp_alb_sg"
   }
 }

注意点として、CloudFrontのManaged Prefix Listを利用すると、セキュリティグループルールに55追加したことになり、この他にルールを追加できる数が5個となってしまいます。

これは追加できるセキュリティグループルールの上限がデフォルトでは60とされているためで、さらに追加したい場合はAWSへのセキュリティグループルールの上限緩和が必要となります。

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/working-with-aws-managed-prefix-lists.html

CloudFrontディストリビューションの作成

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

# CloudFront
 resource "aws_cloudfront_distribution" "myapp_cloudfront" {
   origin {
     domain_name = aws_lb.myapp_alb.dns_name # コンテンツを取得するドメイン名
     origin_id   = "myappALB" # オリジンの識別子 任意のIDを指定できる

     custom_origin_config {
       http_port              = 80 # オリジンにリクエストを送る際のポート番号を指定
       https_port             = 443
       origin_protocol_policy = "http-only" # オリジンとの通信に仕様するプロトコル
       origin_ssl_protocols   = ["TLSv1", "TLSv1.1", "TLSv1.2"] # オリジンとのSSL/TLS通信で使用するプロトコルを指定
     }

     custom_header {
       name  = "X-Custom-Header" # CloudFrontに追加するカスタムヘッダーを指定
       value = data.aws_ssm_parameter.cloudfront_header_value.value
     }
   }

   enabled             = true # ディストリビューションを有効にするかの設定
   is_ipv6_enabled     = true
   comment             = "CloudFront for MyApp" # ディストリビューションの説明部分
   default_root_object = "index.html"

   default_cache_behavior { # デフォルトのキャッシュ動作を設定
     allowed_methods  = ["GET", "HEAD"]
     cached_methods   = ["GET", "HEAD"]
     target_origin_id = "myappALB" # 対象のオリジンIDを指定

     forwarded_values { # オリジンに対してクエリ文字列やクッキーを転送するかの設定
       query_string = false

       cookies {
         forward = "none"
       }
     }

     viewer_protocol_policy = "allow-all" # クライアントがCloudFrontにアクセスする際に使用するプロトコルを指定
     min_ttl                = 0 # データがキャッシュされる最小の時間
     default_ttl            = 3600 # オリジンのデータがキャッシュ制御のヘッダーを返さない場合のキャッシュ保持期間
     max_ttl                = 86400 # データがキャッシュされる最大の時間
   }

   restrictions { # 配信するコンテンツへのアクセス制限を設定
     geo_restriction { # 地理的制限をするかの設定
       restriction_type = "none" # 今回は設定しない
     }
   }

   viewer_certificate { # ディストリビューションで使用するSSL/TLS証明書を設定
     cloudfront_default_certificate = true # CloudFrontデフォルトの証明書を使用
   }
 }

コード内にコメントで解説を入れましたが、特に重要なポイントを解説します。

viewer_protocol_policy

クライアントがCloudFrontにアクセスする際に使用するプロトコルを指定します。

設定値と内容を以下にまとめました。

設定値説明
allow-allクライアントはHTTPおよびHTTPSのどちらでもアクセス可能。
https-onlyクライアントはHTTPSでのみアクセス可能。
redirect-to-httpsクライアントがHTTPでアクセスした場合、HTTPSにリダイレクトされる。

min、default、max、3つのttlについて

ttlの設定では、データがCloudFrontにキャッシュされる期間を指定することができます。

設定項目役割効果利用シナリオ
min_ttlデータがキャッシュに保持される最低時間(秒単位)を指定。この時間が経過するまで、CloudFrontはキャッシュされたオブジェクトを削除したり、オリジンに新しいリクエストを送信したりしない。短期間で頻繁に変更されるコンテンツや、常に最新のデータを返す必要がある場合に有効。
default_ttlデータがCloudFrontキャッシュに保持されるデフォルト時間を指定。オリジンが特定のキャッシュ制御ヘッダー(Cache-ControlやExpiresなど)を返さない場合、この値が使用される。数時間ごとに更新されるニュース記事などに有効。
max_ttlデータがCloudFrontキャッシュに保持される最大時間を指定。この時間を超えてキャッシュにデータは保持されない。
必ずオリジンに新しいリクエストが送信される。長期間変更されない画像ファイルなどに有効。

restrictions

ディストリビューションで配信するコンテンツへのアクセス制限を設定します。

この設定の中で、指定した国からのアクセスの許可、拒否を設定できます。

設定項目説明意味と使用例
restriction_type地理的制限のタイプを指定。none、whitelist、 blacklistnone = 制限しない

whitelist = 指定した国からのアクセスのみを許可

blacklist = 指定した国からのアクセスを拒否 | | locations | アクセスを許可、拒否する国のリストを指定。 restriction_typeがwhitelistかblacklistの時に指定する。 | 国コードのリストを指定 | ["US", "JP", "DE"] |

リソースの作成とcurlコマンドでのアクセス

コードの作成が完了したら、terraform planterraform applyを実行しリソースを作成します。

outputブロックでCloudFront、ALBのドメイン名を表示しているため、それぞれをブラウザやcurlコマンドでアクセスします。

CloudFrontのドメイン名でのみアクセスできることが確認できるはずです。

まとめ

今回はCloudFrontの基本的な特徴と、Terraformを使った構築方法を解説しました。

今回のハンズオンではALBへ証明書を紐づけていないためHTTPSでの通信を行っていませんが、証明書を取得しALBへ紐づけることでHTTPSのみでの通信を実現できます。

まずは今回の記事で基本を身につけ、今後の発展に繋げていきましょう。

【番外編】USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話

IT未経験者必見 USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話

プログラミング塾に半年通えば、一人前になれると思っているあなた。それ、勘違いですよ。「なぜ間違いなの?」「正しい勉強法とは何なの?」ITを学び始める全ての人に知って欲しい。そう思って書きました。是非読んでみてください。

「フリーランスエンジニア」

近年やっと世間に浸透した言葉だ。ひと昔まえ、終身雇用は当たり前で、大企業に就職することは一種のステータスだった。しかし、そんな時代も終わり「優秀な人材は転職する」ことが当たり前の時代となる。フリーランスエンジニアに高価値が付く現在、ネットを見ると「未経験でも年収400万以上」などと書いてある。これに釣られて、多くの人がフリーランスになろうとITの世界に入ってきている。私もその中の1人だ。数年前、USBも知らない状態からITの世界に没入し、そこから約2年間、毎日勉学を行なった。他人の何十倍も努力した。そして、企業研修やIT塾で数多くの受講生の指導経験も得た。そこで私は、伸びるエンジニアとそうでないエンジニアをたくさん見てきた。そして、稼げるエンジニア、稼げないエンジニアを見てきた。

「成功する人とそうでない人の違いは何か?」

私が出した答えは、「量産型エンジニアか否か」である。今のエンジニア市場には、量産型エンジニアが溢れている!!ここでの量産型エンジニアの定義は以下の通りである。

比較的簡単に学習可能なWebフレームワーク(WordPress, Rails)やPython等の知識はあるが、ITの基本概念を理解していないため、単調な作業しかこなすことができないエンジニアのこと。

多くの人がフリーランスエンジニアを目指す時代に中途半端な知識や技術力でこの世界に飛び込むと返って過酷な労働条件で働くことになる。そこで、エンジニアを目指すあなたがどう学習していくべきかを私の経験を交えて書こうと思った。続きはこちらから、、、、

note記事3000いいね超えの殿堂記事 今すぐ読む

エンベーダー編集部

エンベーダーは、ITスクールRareTECHのインフラ学習教材として誕生しました。 「遊びながらインフラエンジニアへ」をコンセプトに、インフラへの学習ハードルを下げるツールとして運営されています。

RareTECH 無料体験授業開催中! オンラインにて実施中! Top10%のエンジニアになる秘訣を伝授します! RareTECH講師への質疑応答可

関連記事

2020.02.25

完全未経験からエンジニアを目指す爆速勉強法

USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話

  • キャリア・学習法
  • エンジニア

2023.10.31

TerraformとEventBridge Schedulerを活用したEC2インスタンスの時限起動によるコスト削減

EC2インスタンスを指定した時間帯だけ起動・停止するスケジュールの設定方法などを説明しています。

  • AWS

2024.04.14

手を動かして身につける AWSでサーバレスのハンズオン

サーバレスコンピューティングの最大のメリットは、インフラの管理から解放されることです。開発者はサーバーのプロビジョニングや保守に関する心配をする必要がなく、アプリケーションのコードの作成とその実行に専念できます。より迅速にアプリケーションを市場に投入することが可能となり、イノベーションの速度を高めることができます。

  • AWS
  • ハンズオン

2024.01.28

Undifferentiated Heavy Liftingとは?重労働から解放されるクラウド時代の新戦略

クラウドコンピューティングの文脈でよく使われるこの用語は、企業や開発者が自社のコアビジネスやイノベーションに集中する代わりに、基本的でありながら重要なインフラストラクチャやシステム管理などの作業に多くの時間とリソースを費やしている状況を指します。

  • AWS
  • インフラエンジニア