こちらの記事では、CloudFrontとACM(AWS Certificate Manager)を使って、独自で発行したSSL証明書をCloudFrontにアタッチする方法を解説します。
CloudFrontを作成する際、デフォルトのSSL証明書をアタッチすることが可能ですが、独自に発行したSSL証明書をアタッチすることでカスタムドメインを使用することができます。
実際の現場では、独自のSSL証明書をCloudFrontにアタッチし、カスタムドメインを使用することが多いと思います。
IaCツールであるTerraformを使ってハンズオンを行いますので、一緒に理解を深めていきましょう。
CloudFrontとは
CloudFrontは、AWSが提供するCDN(Contents Delivery Network)サービスです。
CloudFrontでは、動画やアプリケーション、静的コンテンツなどのデータをエッジロケーションと呼ばれる場所にキャッシュしておきます。エッジロケーションは世界中に分散して配置されており、ユーザーの近くからコンテンツを提供することが可能なため、レスポンスを高速化することができます。
また、それぞれのデータの配信元となるサーバー(オリジン)のデータをキャッシュしておくため、オリジンに対する負荷を軽減することが可能です。
CloudFrontに関連する用語は、以下の記事で解説しています。
https://envader.plus/article/403
ACMとは
ACM(AWS Certificate Manager)は、AWSが提供するSSL/TLS証明書の管理サービスで、証明書の発行、管理、更新を簡単に行えます。SSL証明書は、ウェブサイトとユーザー間の通信を暗号化し、データの安全性を確保する役割を果たします。
ACMを使えば迅速にSSL/TLS証明書を取得し、CloudFrontやALBにアタッチして通信の暗号化を実現できます。また、パブリック証明書が無償で発行できるため、コストを抑えたい場合や個人プロジェクトにも最適です。
ただ、ドメイン検証型(DV)証明書のみを提供しているため、より信頼性の高い証明書を必要とするプロジェクトには向いていないといった側面もあります。
SSL証明書の種類に関しては、次の記事で詳しく解説しています。
https://envader.plus/article/288
CloudFrontに独自のSSL証明書を使う意味とは
CloudFrontに独自で発行したSSL証明書をアタッチすることで、カスタムドメインを使用することができます。
デフォルトのSSL証明書
CloudFrontではデフォルトのSSL証明書が用意されており、この証明書を利用することも可能です。デフォルトのSSL証明書を利用した場合、ドメイン名はCloudFrontのデフォルトドメイン名(xxxxxxxx.cloudfront.net
)を使用することになります。
デフォルトでも問題ありませんが、ドメイン名を見て分かる通り自身のサービスをアピールする要素が欠けてしまい、どの企業のドメイン名なのかがわかりにくくなってしまいます。
また、SEO(検索エンジン最適化)の観点からも、独自ドメインの方が有利とされています。
カスタムドメインとは
カスタムドメイン名とは、自分で取得したオリジナルのドメイン名のことです。(dev.example.com
)
ACMでSSL証明書を発行し、CloudFrontにアタッチすることでカスタムドメインを使用することが可能になります。
カスタムドメインを使用することで、ユーザーから見てもどの企業のドメイン名なのかがわかりやすくなります。
学習目的でハンズオンを行う場合は、デフォルトの証明書でも問題ありません。企業ブランドを意識しなくてはいけない場合にはカスタムドメインを使用することが必要になってきます。
カスタムドメインとSSL証明書の関係
SSL証明書をリクエストするときには、取得しているドメイン名を入力し証明書を発行します。
CloudFrontでカスタムドメインを使用するためには、証明書のドメイン名と一致する必要があります。
例えば、dev.example.com
をCloudFrontのカスタムドメインにしたい場合には、証明書リクエスト時にワイルドカード証明書として*.example.com
とする必要があります。dev.example.com
をカスタムドメインとして使用したいのに、証明書リクエスト時にexample.com
とした場合適用できなくなってしまうため注意が必要です。
CloudFrontとALBに証明書をアタッチするメリット
今回の記事では、CloudFront、ALBの両方に証明書をアタッチするため、このメリットについて考えます。
まず、CloudFrontに証明書をアタッチすることでユーザーとCloudFront間の通信を暗号化することができます。
さらにALBにも証明書をアタッチすることで、AWS上のCloudFrontとALB間の通信もHTTPS化が可能になります。
こうすることで、ユーザーからオリジンまでの全ての通信が暗号化されるため、より信頼性の高い通信を実現できます。
CloudFrontにアタッチする証明書の注意点
ACMの証明書はリージョンごとに発行することが可能で、CloudFrontはグローバルなリソースなためバージニア北部(us-east-1)リージョンで証明書をリクエストする必要があります。
筆者はここでハマった経験があるため注意が必要です。
ALBにアタッチするための証明書を東京リージョンで発行していた場合、これとは別にバージニア北部でCloudFront用の証明書を発行する必要があります。
CloudFrontにアタッチする証明書は、東京リージョンで作成したものは適用できないため注意しましょう。
https://docs.aws.amazon.com/ja_jp/acm/latest/userguide/acm-regions.html
Terraformで実践してみよう
ここからはTerraformで実践していきます。
はじめにTerraformのバージョン、プロバイダーを指定するためversions.tf
を作成します。
# versions.tf
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "5.3.0"
}
}
}
provider "aws" {
alias = "ap-northeast-1" # リージョンのエイリアスを作成
region = "ap-northeast-1"
}
provider "aws" {
alias = "us-east-1" # リージョンのエイリアスを作成
region = "us-east-1"
}
前述した通り、CloudFrontにアタッチする証明書はus-east-1のACMでリクエスト、インポートする必要があり、Terraformのプロバイダー設定にもus-east-1を追加する必要があります。
ACMの証明書はリージョナルリソースです。CloudFrontでACM証明書を使用するには、米国東部 (バージニア北部)リージョンで証明書をリクエストまたはインポートする必要があります。
AWS公式ドキュメントより引用
versions.tf
で定義したaliasは、CloudFrontにアタッチする証明書をdataリソースで参照するときに使用します。
main.tfの作成
main.tf
の内容を記載します。
ACMでの証明書リクエスト方法や、今回のコードの詳細は以下の記事にて解説しています。証明書のリクエスト方法を知りたい方は確認しましょう。
https://envader.plus/article/422
AutoScalingGroupに関しては別記事にて解説しています。
https://envader.plus/article/356
# 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"
}
# CloudFront用us-east-1のACM証明書のARNを取得
data "aws_acm_certificate" "us_east_1_cert" {
provider = aws.us-east-1 # CloudFrontの証明書はus-east-1リージョンになければならないため、version.tfでus-east-1を指定
domain = "*.dev.xxxxxxx.com"
}
# ap-northeast-1のACM証明書のARNを取得
data "aws_acm_certificate" "ap_northeast_1_cert" {
provider = aws.ap-northeast-1 # ALBの証明書はap-northeast-1リージョンになければならないため、version.tfでap-northeast-1を指定
domain = "*.dev.xxxxxxx.com"
}
# Route53のホストゾーンを取得
data "aws_route53_zone" "service_domain" {
name = "dev.xxxxxxx.com"
}
# 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 Association
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用のセキュリティグループ
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] # ALBのセキュリティグループからの通信を許可
}
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 = 443
to_port = 443
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/bastion.pub")
}
# Launch Template
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"
}
}
# HTTPSリスナーの設定
resource "aws_lb_listener" "myapp_https_listener" {
load_balancer_arn = aws_lb.myapp_alb.arn
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS-1-2-2017-01"
certificate_arn = data.aws_acm_certificate.ap_northeast_1_cert.arn # 東京リージョンの証明書をアタッチ
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_https_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 = 20
matcher = "200"
}
tags = {
"Name" = "myappTG"
}
}
# CloudFront用のRoute53レコードの定義
resource "aws_route53_record" "myapp_cloudfront_dns" {
zone_id = data.aws_route53_zone.service_domain.zone_id
name = "myapp.dev.xxxxxxx.com"
type = "A"
alias {
name = aws_cloudfront_distribution.myapp_cloudfront.domain_name
zone_id = aws_cloudfront_distribution.myapp_cloudfront.hosted_zone_id
evaluate_target_health = false
}
}
# ALB用のRoute53レコードの定義 証明書をアタッチするためにALBのDNS名をレコードに登録する必要がある
resource "aws_route53_record" "myapp_alb_dns" {
zone_id = data.aws_route53_zone.service_domain.zone_id
name = "myapp-lb.dev.xxxxxxx.com"
type = "A"
alias {
name = aws_lb.myapp_alb.dns_name
zone_id = aws_lb.myapp_alb.zone_id
evaluate_target_health = false
}
}
# CloudFront
resource "aws_cloudfront_distribution" "myapp_cloudfront" {
aliases = ["myapp.dev.xxxxxxx.com"]
origin {
domain_name = "myapp-lb.dev.xxxxxxx.com" # HTTPリクエストを受けるALBのDNS名を指定
origin_id = "myappALB"
custom_origin_config {
http_port = 80
https_port = 443
origin_protocol_policy = "https-only" # CloudFrontからALBへのリクエストはHTTPSのみ
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 = "https-only"
min_ttl = 0
default_ttl = 3600
max_ttl = 86400
}
restrictions {
geo_restriction {
restriction_type = "none"
}
}
viewer_certificate {
cloudfront_default_certificate = false # CloudFrontデフォルトの証明書を使用しない
acm_certificate_arn = data.aws_acm_certificate.us_east_1_cert.arn # us_east_1の証明書をアタッチ
ssl_support_method = "sni-only"
}
}
output "cloudfront_domain_name" {
value = aws_cloudfront_distribution.myapp_cloudfront.domain_name
}
output "alb_dns_name" {
value = aws_lb.myapp_alb.dns_name
}
output "myapp_cloudfront_dns_name" {
value = aws_route53_record.myapp_cloudfront_dns.name
}
output "myapp_alb_dns_name" {
value = aws_route53_record.myapp_alb_dns.name
}
証明書をdataリソースで参照する
はじめに筆者はここでハマりました。
Terraformでは、CloudFrontにアタッチする証明書、ALBにアタッチする証明書それぞれをdataリソースで参照します。
このときに、versions.tf
で指定したproviderのaliasを指定します。
ここでaliasを指定しないと、CloudFrontでエラーが発生するため注意が必要です。
# CloudFront用us-east-1のACM証明書のARNを取得
data "aws_acm_certificate" "us_east_1_cert" {
provider = aws.us-east-1 # CloudFrontの証明書はus-east-1リージョンになければならないため、version.tfでus-east-1を指定
domain = "*.dev.xxxxxxx.com"
}
# ap-northeast-1のACM証明書のARNを取得
data "aws_acm_certificate" "ap_northeast_1_cert" {
provider = aws.ap-northeast-1 # ALBの証明書はap-northeast-1リージョンになければならないため、version.tfでap-northeast-1を指定
domain = "*.dev.xxxxxxx.com"
}
ALBリスナーに東京リージョンの証明書をアタッチ
今回はSSL証明書をアタッチしてHTTPS通信のみを実現するため、ALBのリスナーに東京リージョンで発行した証明書をアタッチします。
# HTTPSリスナーの設定
resource "aws_lb_listener" "myapp_https_listener" {
load_balancer_arn = aws_lb.myapp_alb.arn
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS-1-2-2017-01"
certificate_arn = data.aws_acm_certificate.ap_northeast_1_cert.arn # 東京リージョンの証明書をアタッチ
default_action {
type = "fixed-response"
fixed_response {
content_type = "text/plain"
message_body = "Not Found"
status_code = "404"
}
}
}
Route53でCloudFrontとALBのドメインを登録
CloudFrontにACMで発行した証明書をアタッチすることで、カスタムドメインを指定することが可能になります。
そのため、Route53でレコードを作成し、カスタムドメインとCloudFrontで作成されるデフォルトのドメイン名を紐付けます。
# CloudFront用のRoute53レコードの定義
resource "aws_route53_record" "myapp_cloudfront_dns" {
zone_id = data.aws_route53_zone.service_domain.zone_id
name = "myapp.dev.xxxxxxx.com"
type = "A"
alias {
name = aws_cloudfront_distribution.myapp_cloudfront.domain_name
zone_id = aws_cloudfront_distribution.myapp_cloudfront.hosted_zone_id
evaluate_target_health = false
}
}
続いてALBのドメイン名との紐付けを行うため、Route53のレコードを作成します。
ここでも筆者はハマりました。
ALBにSSL証明書をアタッチする際、発行した証明書が*.dev.example.com
の場合にはオリジンのドメイン名も証明書のドメイン名と一致させる必要があります。
今回、Route53のレコードをmyapp-lb.dev.xxxxxxx.com
として作成し、エイリアスでALBのDNS名を指定しています。
# ALB用のRoute53レコードの定義 証明書をアタッチするためにALBのDNS名をレコードに登録する必要がある
resource "aws_route53_record" "myapp_alb_dns" {
zone_id = data.aws_route53_zone.service_domain.zone_id
name = "myapp-lb.dev.xxxxxxx.com"
type = "A"
alias {
name = aws_lb.myapp_alb.dns_name
zone_id = aws_lb.myapp_alb.zone_id
evaluate_target_health = false
}
}
この設定をせず、CloudFrontのオリジンドメイン名にデフォルトのALBドメイン名を指定してディストリビューションを作成した場合、通信が失敗し502エラーが返ってきます。必ずALBのドメイン名に対してエイリアスとしてレコードを作成しましょう。
https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/http-502-bad-gateway.html
# CloudFront
resource "aws_cloudfront_distribution" "myapp_cloudfront" {
aliases = ["myapp.dev.xxxxxxx.com"]
origin {
domain_name = "myapp-lb.dev.xxxxxxx.com" # HTTPリクエストを受けるALBのDNS名を指定
origin_id = "myappALB"
custom_origin_config {
http_port = 80
https_port = 443
origin_protocol_policy = "https-only" # CloudFrontからALBへのリクエストはHTTPSのみ
origin_ssl_protocols = ["TLSv1", "TLSv1.1", "TLSv1.2"]
}
疎通確認
ソースコードを作成後、plan
結果を確認しapply
を実行しましょう。
リソースの作成完了後、疎通確認を行います。
今回はcurl
コマンドを使って接続できるかを確認します。
# コマンド参考例
curl https://myapp.dev.xxxxxxx.com
Hello, world
Hello Worldが返ってくれば疎通確認完了です。
まとめ
今回の記事ではTerraformを使用して、CloudFrontとACMで発行したSSL証明書をアタッチする方法を解説しました。
実際の現場ではCloudFront、ALBの構成は非常に多くなっています。今回解説した中での注意点を理解しておくことで、実際の業務でも活かすことができると思います。
CloudFrontにはus-east-1で発行したSSL証明書が必要になり、ディストリビューションのオリジンドメインにはRoute53で登録したALBのドメイン名が必要です。
今回のハンズオンを通じて、CloudFront、ALB、SSL証明書の理解につながっていただければ幸いです。
【番外編】USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話
プログラミング塾に半年通えば、一人前になれると思っているあなた。それ、勘違いですよ。「なぜ間違いなの?」「正しい勉強法とは何なの?」ITを学び始める全ての人に知って欲しい。そう思って書きました。是非読んでみてください。
「フリーランスエンジニア」
近年やっと世間に浸透した言葉だ。ひと昔まえ、終身雇用は当たり前で、大企業に就職することは一種のステータスだった。しかし、そんな時代も終わり「優秀な人材は転職する」ことが当たり前の時代となる。フリーランスエンジニアに高価値が付く現在、ネットを見ると「未経験でも年収400万以上」などと書いてある。これに釣られて、多くの人がフリーランスになろうとITの世界に入ってきている。私もその中の1人だ。数年前、USBも知らない状態からITの世界に没入し、そこから約2年間、毎日勉学を行なった。他人の何十倍も努力した。そして、企業研修やIT塾で数多くの受講生の指導経験も得た。そこで私は、伸びるエンジニアとそうでないエンジニアをたくさん見てきた。そして、稼げるエンジニア、稼げないエンジニアを見てきた。
「成功する人とそうでない人の違いは何か?」
私が出した答えは、「量産型エンジニアか否か」である。今のエンジニア市場には、量産型エンジニアが溢れている!!ここでの量産型エンジニアの定義は以下の通りである。
比較的簡単に学習可能なWebフレームワーク(WordPress, Rails)やPython等の知識はあるが、ITの基本概念を理解していないため、単調な作業しかこなすことができないエンジニアのこと。
多くの人がフリーランスエンジニアを目指す時代に中途半端な知識や技術力でこの世界に飛び込むと返って過酷な労働条件で働くことになる。そこで、エンジニアを目指すあなたがどう学習していくべきかを私の経験を交えて書こうと思った。続きはこちらから、、、、
エンベーダー編集部
エンベーダーは、ITスクールRareTECHのインフラ学習教材として誕生しました。 「遊びながらインフラエンジニアへ」をコンセプトに、インフラへの学習ハードルを下げるツールとして運営されています。
関連記事
2020.02.25
完全未経験からエンジニアを目指す爆速勉強法
USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話
- キャリア・学習法
- エンジニア
2024.08.31
AzureにはNATゲートウェイはいらない?AWSとの違いとAzureでの使いどころ
この記事では、Azureの「NATゲートウェイが不要」とされる理由を詳しく探ります。具体的には、Azureがどのようにデフォルト設定でインターネット接続を提供しているのか、その利便性や制約について解説します。
- AWS
- Azure
- ネットワーク
2023.11.21
【Part 1/4】AWSの環境構築で学ぶトラブルシューティング【VPC Peering】
今回は、異なるVPCにいるインスタンス間同士の通信を行える環境を構築します。VPCピアリングを用いて、インターネットを介さない安全な通信を実現する方法を学習します。
- AWS
2022.12.26
【AWS】Amazon S3のストレージクラスの使い分けと選択のポイント
S3には様様な使用用途に合わせた6つのストレージクラスが用意されており、それぞれ機能や料金に違いがあるため詳しく説明を行います。
- AWS