16. Auto Scaling Group / Launch Template
EC2 を自動で増減させる仕組み。トラフィック変動への対応、健全性ベースの自動入れ替え、ローリングデプロイ等の基盤。
登場人物
| 用語 | 役割 |
|---|---|
| Launch Template | 「どのインスタンスをどう起動するか」のテンプレート(AMI、type、user_data 等) |
| Auto Scaling Group (ASG) | 「N 台を維持」「死んだら作り直す」「需要に応じて増減する」を司る |
| Scaling Policy | 「いつ何台に増減するか」のルール(CPU 70% で +1 など) |
| Target Group | ALB / NLB がトラフィックを送る先プール。ASG がここに自動登録 |
aws_launch_template
# Launch Template:起動時のスペック雛形
resource "aws_launch_template" "web" {
name_prefix = "web-"
image_id = data.aws_ami.al2023.id
instance_type = "t3.micro"
key_name = aws_key_pair.deployer.key_name
vpc_security_group_ids = [aws_security_group.app.id]
# EC2 が AWS API を叩くためのロール(instance_profile 経由)
iam_instance_profile {
name = aws_iam_instance_profile.ec2.name
}
# 起動時に走るスクリプト(user_data は base64 必須)
user_data = base64encode(<<-EOT
#!/bin/bash
dnf install -y nginx
systemctl enable --now nginx
echo "Hello from $(hostname)" > /usr/share/nginx/html/index.html
EOT
)
# ルートディスク設定
block_device_mappings {
device_name = "/dev/xvda"
ebs {
volume_size = 20
volume_type = "gp3"
encrypted = true
delete_on_termination = true # インスタンス終了でボリュームも削除
}
}
# 起動するインスタンスにタグを付与
tag_specifications {
resource_type = "instance"
tags = { Name = "web", Tier = "frontend" }
}
# IMDS(メタデータサービス)の設定
metadata_options {
http_tokens = "required" # IMDSv2 強制(v1 拒否、セキュリティ向上)
http_put_response_hop_limit = 1 # コンテナからメタデータ取得を防ぐ
}
lifecycle {
create_before_destroy = true # 更新時に新版を先に作成
}
}
aws_autoscaling_group
# Auto Scaling Group:N 台維持と自動増減を担うマネージャ
resource "aws_autoscaling_group" "web" {
name_prefix = "web-"
# 配置する subnet(複数 AZ にまたがると高可用性)
vpc_zone_identifier = [for s in aws_subnet.private : s.id]
min_size = 2 # 最低キープする台数
desired_capacity = 3 # 平常時の希望台数
max_size = 10 # スケール上限
health_check_type = "ELB" # ALB のヘルスチェックを基準に(EC2 単体より厳密)
health_check_grace_period = 300 # 起動から N 秒は失敗を無視(起動完了待ち)
# 上で作った Launch Template を参照("$Latest" は最新版、版番号も可)
launch_template {
id = aws_launch_template.web.id
version = "$Latest"
}
# ALB の Target Group に自動登録(起動時 attach、終了時 detach)
target_group_arns = [aws_lb_target_group.web.arn]
# ASG 自身のタグ(インスタンスにも伝播)
tag {
key = "ManagedBy"
value = "Terraform"
propagate_at_launch = true
}
lifecycle {
create_before_destroy = true
ignore_changes = [desired_capacity] # スケーリングポリシーが管理する
}
}
スケーリングポリシー
Target Tracking(推奨)
「平均 CPU 50% を維持して」のように 目標値 を伝えるだけ。AWS が自動で増減を計算。
# Target Tracking:目標値だけ伝えれば AWS が自動計算
resource "aws_autoscaling_policy" "cpu" {
name = "target-cpu"
autoscaling_group_name = aws_autoscaling_group.web.name
policy_type = "TargetTrackingScaling"
target_tracking_configuration {
predefined_metric_specification {
predefined_metric_type = "ASGAverageCPUUtilization" # 平均 CPU
}
target_value = 50.0 # 50% を維持するように増減
}
}
Step Scaling(細かく制御したい時)
# Step Scaling:「閾値超過量に応じて何台増やすか」を段階的に指定
resource "aws_autoscaling_policy" "scale_out" {
name = "scale-out"
autoscaling_group_name = aws_autoscaling_group.web.name
policy_type = "StepScaling"
adjustment_type = "ChangeInCapacity" # 台数で増減(PercentChange も可)
# 閾値から +0〜+20 超過なら +1 台
step_adjustment {
metric_interval_lower_bound = 0
metric_interval_upper_bound = 20
scaling_adjustment = 1
}
# +20 超過なら +3 台(急増対応)
step_adjustment {
metric_interval_lower_bound = 20
scaling_adjustment = 3
}
}
# Step Scaling は alarm が発火しないと動かない。アラームを別途定義
resource "aws_cloudwatch_metric_alarm" "cpu_high" {
alarm_name = "asg-cpu-high"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 2
metric_name = "CPUUtilization"
namespace = "AWS/EC2"
period = 60
statistic = "Average"
threshold = 70
dimensions = {
AutoScalingGroupName = aws_autoscaling_group.web.name
}
# アラーム発火時に scale_out ポリシーを発動
alarm_actions = [aws_autoscaling_policy.scale_out.arn]
}
ALB と連携
resource "aws_lb_target_group" "web" {
name = "web"
port = 80
protocol = "HTTP"
vpc_id = aws_vpc.main.id
health_check {
path = "/health"
healthy_threshold = 2
unhealthy_threshold = 3
interval = 30
timeout = 5
matcher = "200"
}
}
# Listener は 10 章 (ALB) を参照
# ASG の target_group_arns に ARN を渡せば自動登録
Instance refresh(ローリング更新)
Launch Template を新版に更新した後、既存インスタンスを ローリングで入れ替え る機能。Terraform からは Apply 時に自動で発火させられます。
# 既存 ASG に instance_refresh ブロックを追加(Rolling 更新を有効化)
resource "aws_autoscaling_group" "web" {
# ...
instance_refresh {
strategy = "Rolling"
preferences {
min_healthy_percentage = 90 # 入れ替え中も 90% 以上の台数を維持
instance_warmup = 300 # 新インスタンスを healthy 判定するまでの秒
}
# tag/launch_template が変更されたら自動で refresh を発火
triggers = ["tag", "launch_template"]
}
}
tip
"$Latest" や "$Default" ではなく 具体的な version 番号を指定 すると、apply 時の差分が明確になり、誤って即時新版にロールアウトする事故を防げます。