最終確認: 2026年5月
SAA-C03 試験の対象となる AWS サービスを、プレーンな Terraform を使用して構築します。1 ブロックずつ、それぞれ試験ドメインに関連付けられています。同じコードが OpenTofu でも動作します。
このラボの終了時には、プレーンなTerraformを使って、典型的なマルチAZ高可用性ウェブスタック(2つのAZにわたるパブリックおよびプライベートサブネットを持つカスタムVPC、インターネットに接続するApplication Load Balancer、プライベート層のEC2インスタンスのAuto Scaling Group、アプリケーションが通信するマルチAZ RDSデータベース)をプロビジョニングできます。5つの試験の柱を5つのステップで学びます。
すべてのリソースはプレーンなTerraformであり、同じコードはOpenTofuでも変更なく動作します。変数、モジュール、リモートステートは使用しません。スニペットを単一の main.tf にドロップし、一度 terraform init を実行してから、terraform apply をステップバイステップで実行してください。
>= 1.5 または OpenTofu >= 1.6。us-east-1 で認証済みのAWS CLI(このラボのデフォルトリージョン — 任意のリージョンを選択できますが、ステップ3のAMIルックアップは、そのリージョンにAmazon Linux 2023があることを前提としています)。skip_final_snapshot = true を設定しているため、クリーンに削除できます — この設定は本番環境では絶対に使用しないでください。db.t3.micro はアイドル状態でも月額約30ドルかかります。ラボ終了後は必ず削除してください。このラボのほとんどは無料利用枠またはそれに近いものです。VPC、ALB、ASG、セキュリティグループ、IAM、CloudWatchモニタリングは無料です。アイドル中に料金が発生する項目は以下の通りです。
db.t3.micro Multi-AZ: 月額約30ドル(Multi-AZはシングルAZの2倍の料金がかかります。SAA-C03の主要なHAパターンは無料ではありません)。t3.micro × 2: 月間合計1,500時間。無料利用枠は1インスタンスあたり750時間をカバーするため、2つを実行すると超過します。コストに敏感な場合は、ラボ用に db_instance.multi_az = false を設定し、Multi-AZのドキュメントを別途お読みください。完全なHAパターンを実行しなくても、試験ではその属性を知っていることが評価されます。完了したら削除してください。
AWSプロバイダーを ~> 5.60 に固定し、us-east-1 を選択します(少なくとも2つのAZを持つ任意のリージョンで動作します)。data ブロックは、計画時に利用可能なAZリストを取得します。us-east-1a のようなAZ名をハードコーディングすることは、AZ名と物理ゾーンのマッピングがアカウント固有であるため(あなたの us-east-1a は私のものとは異なる物理AZである可能性があります)、SAA-C03のアンチパターンです。
ダウンストリームで作成するすべてのリソースは、default_tags を介して単一のプロジェクト名にタグ付けされます。Cost ExplorerとAWS Configルールはどちらもタグに基づいて機能し、試験ではすべてにタグを付けることが期待されます。
terraform {
required_version = ">= 1.5"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.60"
}
}
}
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
Project = "certlabpro-saa-c03"
ManagedBy = "terraform"
}
}
}
data "aws_availability_zones" "available" {
state = "available"
}すべてのSAA-C03の高可用性に関する質問は、ワークロードを少なくとも2つのアベイラビリティゾーンに分散させることを前提としています。ここでは、/16 VPCを作成し、4つの/20サブネット(ALB用のパブリック2つ、EC2インスタンスとRDS用のプライベート2つ)を切り出します。インターネットゲートウェイはVPCにアタッチされ、パブリックルートテーブルは 0.0.0.0/0 を介してルーティングします。
このラボでは、プライベートサブネットにNATゲートウェイは意図的に設定していません。NAT GWはアイドル状態でも月額約32ドル(AZあたり)課金され、SAA-C03はこのトレードオフをコストに関する質問で明確に問うています。本番環境でプライベートサブネットからアウトバウンドインターネットが必要な場合は、NAT(またはSAA-C03でより安価な代替手段であるNATインスタンス)を追加することになります。
このステップで作成するVPC + サブネット + IGW + ルートテーブルは、これに続くすべての基盤となります。ALBはパブリックサブネットに接続され、ASGインスタンスはプライベートサブネットに配置され、ステップ5のRDSサブネットグループは両方のプライベートAZにまたがります。
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
tags = { Name = "certlabpro-saa-c03-vpc" }
}
resource "aws_subnet" "public" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = "10.0.${count.index}.0/24"
availability_zone = data.aws_availability_zones.available.names[count.index]
map_public_ip_on_launch = true
tags = { Name = "certlabpro-saa-c03-public-${count.index}" }
}
resource "aws_subnet" "private" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = "10.0.${count.index + 10}.0/24"
availability_zone = data.aws_availability_zones.available.names[count.index]
tags = { Name = "certlabpro-saa-c03-private-${count.index}" }
}
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
}
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
}
resource "aws_route_table_association" "public" {
count = 2
subnet_id = aws_subnet.public[count.index].id
route_table_id = aws_route_table.public.id
}Application Load Balancerは、SAA-C03が「HTTP / HTTPS」や「パスベースルーティング」、「特定のサービスをターゲットにする」といったキーワードが質問に含まれる際に選択することを期待するロードバランサーです。Network Load BalancerはTCP/UDPと超低レイテンシーを扱い、Classicはレガシーです。ALBを選択します。
ALBはステップ2で作成した2つのパブリックサブネット内に配置されます。これが構造的に「マルチAZ」を意味します。そのセキュリティグループはどこからでもHTTP(ポート80)を受け入れ、ターゲットグループはステップ4で作成するASGからメンバーを取得します。ヘルスチェックはALBとターゲット間の契約であり、/ が200番台以外のステータスコードを返した場合、ALBはそのインスタンスへのトラフィック送信を停止します。
このラボではHTTPSは使用しません。HTTPSにはACM証明書とDNS名が必要ですが、これはHAパターンを可視化するために不要な2つのサービスです。本番環境ではACMを追加してください。
resource "aws_security_group" "alb" {
name = "certlabpro-saa-c03-alb"
description = "ALB ingress on port 80 from the internet"
vpc_id = aws_vpc.main.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_lb" "web" {
name = "certlabpro-saa-c03-alb"
load_balancer_type = "application"
internal = false
subnets = aws_subnet.public[*].id
security_groups = [aws_security_group.alb.id]
}
resource "aws_lb_target_group" "web" {
name = "certlabpro-saa-c03-tg"
port = 80
protocol = "HTTP"
target_type = "instance"
vpc_id = aws_vpc.main.id
health_check {
path = "/"
matcher = "200-299"
interval = 30
timeout = 5
healthy_threshold = 2
unhealthy_threshold = 3
}
}
resource "aws_lb_listener" "http" {
load_balancer_arn = aws_lb.web.arn
port = 80
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.web.arn
}
}Auto ScalingはAWS Well-Architectedの「弾力性」の柱であり、SAA-C03ではマルチAZに次いで2番目に多く出題されるトピックです。ステップ3のALBと組み合わせることで、ASGは耐障害性(インスタンスが失敗した場合に交換される)とスケーラビリティ(インスタンス数が需要に合わせて追跡される)の両方を提供します。これらはSAA-C03で繰り返し問われる2つの成果です。
起動テンプレートは、新しい各インスタンスがどのようなものになるかを定義します。最新のAmazon Linux 2023 AMI、t3.micro インスタンス、ALB SGからのみトラフィックを受け入れる(ネットワーク層での最小特権)ステップ2と同等のSG、およびヘルスチェックが通過するようにnginxを起動する最小限のユーザーデータを使用します。
ASGは3つのことを結びつけます。インスタンスが実行される場所(vpc_zone_identifier = 私たちのプライベートサブネット、両AZ)、存在するべきインスタンスの数(min_size = 2、max_size = 4 — HA用に2つ、スケーリングの余裕)、そして新しいインスタンスがロードバランサーに参加する方法(target_group_arns)。ASGがインスタンスを起動すると、ステップ3のターゲットグループに自動的に登録されます。
resource "aws_security_group" "app" {
name = "certlabpro-saa-c03-app"
description = "App instances accept traffic only from the ALB SG"
vpc_id = aws_vpc.main.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
security_groups = [aws_security_group.alb.id]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
data "aws_ami" "al2023" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-kernel-6.1-x86_64"]
}
}
resource "aws_launch_template" "app" {
name_prefix = "certlabpro-saa-c03-app-"
image_id = data.aws_ami.al2023.id
instance_type = "t3.micro"
vpc_security_group_ids = [aws_security_group.app.id]
metadata_options {
http_tokens = "required"
}
user_data = base64encode(<<-EOT
#!/bin/bash
dnf install -y nginx
systemctl enable --now nginx
EOT
)
}
resource "aws_autoscaling_group" "app" {
name = "certlabpro-saa-c03-app-asg"
vpc_zone_identifier = aws_subnet.private[*].id
target_group_arns = [aws_lb_target_group.web.arn]
health_check_type = "ELB"
min_size = 2
max_size = 4
desired_capacity = 2
launch_template {
id = aws_launch_template.app.id
version = "$Latest"
}
}SAA-C03のマルチAZストーリーの目玉は、マルチAZ RDSデータベースです。multi_az = true の設定は、試験全体で最も多く問われる属性の1つです。これは、RDSに2番目のAZに同期スタンバイレプリカをプロビジョニングするよう指示します。プライマリが失敗した場合、RDSは自動的にスタンバイを昇格させます。一般的なフェイルオーバーはデータ損失なしで約60秒かかります。2つのシングルAZデータベースではそれが得られません。手動レプリケーションでも得られません。マルチAZは、「1分未満のフェイルオーバー、データ損失なし」という質問に対する答えです。
DBサブネットグループには少なくとも2つのAZにサブネットが必要です。ここではステップ2のプライベートサブネットを使用します。セキュリティグループは、アプリSGからのみデータベースポート(PostgreSQLの場合は5432)を受け入れ、ステップ4の多層セキュリティパターンを反映しています。
この最後の要素が配置されると、スタックは完成します。トラフィックはいずれかのパブリックAZのALBに入り、いずれかのプライベートAZのASGインスタンスに分散され、それらのインスタンスはRDSプライマリ(別のAZでホットスタンバイが待機している)と通信します。リージョン全体の障害を除き、あらゆる障害に回復パスがあります。
resource "aws_db_subnet_group" "main" {
name = "certlabpro-saa-c03"
subnet_ids = aws_subnet.private[*].id
}
resource "aws_security_group" "db" {
name = "certlabpro-saa-c03-db"
description = "DB accepts traffic only from the app SG"
vpc_id = aws_vpc.main.id
ingress {
from_port = 5432
to_port = 5432
protocol = "tcp"
security_groups = [aws_security_group.app.id]
}
}
resource "aws_db_instance" "main" {
identifier = "certlabpro-saa-c03"
engine = "postgres"
engine_version = "16"
instance_class = "db.t3.micro"
allocated_storage = 20
storage_encrypted = true
multi_az = true # the SAA-C03 headline
db_subnet_group_name = aws_db_subnet_group.main.name
vpc_security_group_ids = [aws_security_group.db.id]
username = "appuser"
password = "ChangeMe-Not-For-Prod-1234" # use Secrets Manager in production
skip_final_snapshot = true # lab-only setting; never use on prod
apply_immediately = true
}terraform destroy はこのラボ内のすべてを削除します。2点注意してください。
skip_final_snapshot = true が設定されているため、destroy は数分で完了し、スナップショットを残しません。このフラグを本番データベースに決して設定しないでください。最終スナップショットを失うことは永続的なデータ損失につながります。destroy は、すべてのインスタンスが消えるまで完了せず、2〜3分かかることがあります。お待ちください。destroy の途中で Ctrl-C を押さないでください。完了するまで待ってください。SAA-C03は、単一のラボで示せるよりも多くのアーキテクチャパターンをカバーしています。グローバルコンテンツ配信のためのCloudFront、DNSベースのフェイルオーバーのためのRoute 53、S3クロスリージョンレプリケーション、Auroraグローバルデータベース、Direct Connect、VPCピアリング、Transit Gateway、ElastiCache、EFS、FSxなど、その他多数です。
私たちは意図的に、試験で最も多く出題される単一のパターンである、1つのリージョン内でのマルチAZ HAに焦点を当てています。これは、すべてのソリューションアーキテクトの面接や、SAA-C03の質問の約30%で登場するアーキテクチャです。残りの70%(グローバルパターン、キャッシング、高度なネットワーキング、ハイブリッドクラウド)は、この認定ページにある閲覧およびEditorialセクションで概念的にカバーされています。各クロスリージョンまたは高度なネットワーキングのトピックは、それぞれ独自のラボに値します。1つの巨大なスタックを構築すると、この形式が依存する構築ストーリーの規律が希薄になります。
クロスリージョンパターン(S3 CRR、Auroraグローバル、Route 53ヘルスチェック)をハンズオンで実践したい場合は、それらも同じプレーンなTerraformの形式にきれいにマッピングでき、次のラボの優れた候補となります。