- 1 1. この記事について
- 2 2. 前提・環境・準備
- 3 3. On-Demand Capacity Reservations (ODCR) — 確実な容量確保の基礎
- 4 4. Capacity Blocks for ML — GPU (P5) の未来日予約 (★山場1)
- 5 5. EC2 Fleet & 容量最適化配分 — capacity-optimized / 混在インスタンス (★山場2)
- 6 6. Dedicated Hosts のライセンス大規模運用 — Host Resource Groups × License Manager
- 7 7. 詰まりポイント7選 図解
- 8 8. アンチパターン → 正解パターン変換演習 + シリーズ繋ぎ
1. この記事について

- On-Demand Capacity Reservations (ODCR) によるゾーン指定・インスタンスマッチング条件を使った確実な容量確保と、Organizations 経由の予約共有
- Capacity Blocks for ML による GPU (P5/P5e/P5en 等) の未来日予約と、ML 学習・ファインチューニングでの活用
- EC2 Fleet の capacity-optimized 配分による中断耐性と容量確保の両立、Dedicated Hosts の Host Resource Groups × License Manager によるライセンス大規模運用
- Vol1 (インスタンス選定 / Auto Scaling / Graviton / Spot / Nitro / 専有・配置基礎) → Vol2 (Graviton4 / 最新世代 EC2 / Nitro / arm64 移行) の次に位置する第3弾
- Vol1・Vol2 は「どのインスタンスを、どう起動・スケールするか」を扱ったが、本 Vol3 は「必要な時に必要な容量を確実に取れるか」という直交軸で補完する
- Dedicated Hosts / Placement Group の基礎(テナンシー・配置戦略)は Vol1 §6 へクロスリンク委譲し、本 Vol3 はライセンス大規模運用の角度に集中する
- 生成AI/ML学習需要の急増でGPUインスタンス(P5等)の逼迫が続いており、Capacity Blocks for MLは東京(ap-northeast-1)でp5.4xlarge/p5.48xlarge/p5e.48xlarge/p5en.48xlargeが提供済み
- 大規模ASG・バッチ処理・ML学習基盤で「スケールアウトしようとしたら容量が確保できない」という障害が本番運用の実課題として顕在化している
- 既存Computeシリーズ(Vol1/Vol2)は容量予約を主題としてカバーしておらず、ODCR/Capacity Blocks/Fleetの使い分けというコストと可用性の両立設計が空白のまま残っていた
1-1. 本記事のゴール
本記事を読み終えた時点で、読者は On-Demand Capacity Reservations (ODCR) を使い、
ゾーン指定とインスタンスマッチング条件を組み合わせて、
本番トラフィックのピーク時にも確実にインスタンス容量を確保できる設計ができるようになります。
さらに、Capacity Blocks for ML を使って P5 等の GPU インスタンスを最大8週間先まで未来日予約し、
GPU逼迫下でもML学習・ファインチューニングのスケジュールを崩さず、予定通り実行できる状態に到達します。
EC2 Fleet の capacity-optimized 配分戦略を Terraform で構築し、
複数インスタンスタイプ・複数 AZ に分散させながら中断耐性と容量確保を両立させる設計を、
自分の手で組めるようになります。
最後に、Dedicated Hosts の Host Resource Groups と License Manager を連携させ、
BYOL(Bring Your Own License)のソケット/コアベースのライセンス制約下で、
物理ホスト単位のライセンス監査証跡を残しながら大規模運用する構成を実装できる状態がゴールです。
各セクションのスコープを以下に示します。
| セクション | 扱う内容 |
|---|---|
| §2 前提・環境・準備 | 対象インスタンスタイプ・IAM権限・Terraform 3点セット |
| §3 ODCR | ゾーン指定・インスタンスマッチング条件・Organizations共有・unused課金 |
| §4 Capacity Blocks for ML(★山場1) | GPU(P5)未来日予約・利用可能日・ASG連携 |
| §5 EC2 Fleet & 容量最適化配分(★山場2) | allocation strategy・混在インスタンス・AZ分散 |
| §6 Dedicated Hosts ライセンス運用 | Host Resource Groups・License Manager連携 |
| §7 詰まりポイント7選 | 容量確保戦略でつまずく典型パターンの図解 |
| §8 アンチパターン変換・まとめ | 5問の変換演習・シリーズ総括 |
§3〜§6 は独立して読めますが、まず §2 で環境と IAM 権限を整えたうえで、
自分のワークロード特性に近いセクション(GPU学習なら §4、大規模ASGなら §3・§5)から
着手することを推奨します。
1-2. 読者像
本記事は、大規模な EC2 / Auto Scaling Group / ML 学習ワークロードを本番環境で運用しており、
需要ピーク時の容量確保に課題を感じているインフラ・プラットフォームエンジニアを主読者として想定しています。
具体的には、セール時期やイベント時のトラフィック急増でスケールアウトを迫られた際に、
「必要なインスタンスタイプの在庫が確保できない」という経験をしたことがある方、
あるいは GPU インスタンスの調達難易度の高さに直面している MLOps 担当者を想定しています。
また、Windows Server や SQL Server 等の BYOL ライセンスを Dedicated Hosts 上で大規模に運用しており、
ライセンス数の超過や監査対応に手間取った経験がある方にも実践的な内容です。
Vol1・Vol2 でインスタンス選定と Auto Scaling の基礎、最新世代 EC2 への移行を終え、
次のステップとして「容量そのものをどう確実に確保するか」という運用課題に取り組みたい読者を想定しています。
本記事では以下は扱いません。
- Auto Scaling の基本設定(動的スケーリング・起動テンプレート) — Vol1 §3 を参照してください
- Graviton / arm64 移行の判断基準 — Vol2 で体系的に扱います
- Dedicated Hosts / Placement Group の基礎(テナンシー・配置戦略) — Vol1 §6 を参照してください
AWS アカウントで EC2 インスタンスを起動した経験があり、
VPC・IAM・Auto Scaling グループの基本操作を理解していることを前提とします。
一方で、単発のPoCや小規模な検証環境でインスタンスを数台起動する程度の用途では、
本記事の内容はオーバースペックです。
ODCRやCapacity Blocksの予約コストがかえって負担になるため、
そうした場合はオンデマンド起動のままで十分です。
1-3. なぜ今これを書くか
生成AI/MLブームによるGPUインスタンスの需給逼迫は継続的な課題であり、
Capacity Blocks for ML は東京リージョン(ap-northeast-1)で p5.4xlarge / p5.48xlarge / p5e.48xlarge /
p5en.48xlarge の提供が進んでいます。
未来日予約という仕組み自体が比較的新しく、実務でどう組み込むかの情報はまだ少ない状況です。
また、大規模な ASG やバッチ処理基盤を運用する現場では、
Auto Scaling の設定は整っていても「スケールアウト先の容量が保証されていない」という
ギャップに気づいていないケースが少なくありません。
ODCR や EC2 Fleet の allocation strategy を正しく組み合わせることで、
このギャップは設計段階で解消できます。
AWS Compute 本番運用シリーズは Vol1・Vol2 でインスタンス選定・スケーリング・最新世代移行を
カバーしてきましたが、容量確保という運用の根幹に関わるテーマは未着手でした。
本 Vol3 でこの空白を埋め、シリーズとして容量確保からライセンス運用まで一気通貫でカバーします。
容量確保・GPU予約・ライセンス管理という3つのテーマは一見別々の課題に見えますが、
いずれも「必要なリソースを、必要なタイミングで、確実に使える状態にする」という
本番運用の根幹に関わる点で共通しています。
本記事ではこの3テーマを個別にではなく、容量管理という一つの設計軸として統合的に扱います。
なお、本記事のTerraformコード例はすべて hashicorp/aws >= 5.31 を前提とし、aws_ec2_capacity_block_reservation を含む最新リソースで検証済みです。
前作: AWS Compute本番運用 Vol2 (Graviton4/最新世代EC2) を読む
2. 前提・環境・準備

本章では、本Vol3のハンズオン全体を通して前提とするAWSアカウント状態、対象インスタンスタイプ、IAM権限、Terraformワークスペースの初期構成を整えます。§3以降で実装するODCR・Capacity Blocks for ML・EC2 Fleet・Dedicated Hostsは、すべて本章で整備した環境の上に積み上げます。
2-1. 前提環境
本記事はAWS Compute本番運用シリーズVol1(インスタンス選定/Auto Scaling/Graviton/Spot/Nitro)・Vol2(Graviton4/最新世代EC2)で構築済みの本番EC2環境を前提とし、そこに容量確保とライセンス制約下のスケーリングの仕組みを積み上げる構成です。まだVol1/Vol2相当の構成を導入していない場合は、少なくとも以下と同等の環境を用意してください。
| 項目 | 前提条件 |
|---|---|
| AWSアカウント | 東京リージョン(ap-northeast-1)でEC2/Organizationsを利用可能なアカウント |
| 対象インスタンスタイプ | ODCR/Fleet/Hostは全インスタンスファミリーが対象。Capacity Blocks for MLはP5系(p5.48xlarge等)のGPUインスタンスが対象(東京リージョン提供済み) |
| IAM権限 | ec2:*CapacityReservation* / ec2:*CapacityBlock* / ec2:*Fleet* / ec2:*Host* 系アクション群(詳細は2-4) |
| AWS Organizations | ODCRの組織内共有を検証する場合、Organizations有効化済みのマルチアカウント環境が必要(単一アカウントでも本記事の大半は検証可能) |
AWS CLI/Terraformのバージョンは以下を必須とします。
| ツール | バージョン | 用途 |
|---|---|---|
| AWS CLI | v2.15以上 | create-capacity-reservation / purchase-capacity-block 等の容量管理コマンド実行 |
| Terraform | 1.9.x以上 | aws_ec2_capacity_block_reservation 等の最新リソース管理 |
| hashicorp/aws provider | 5.31以上 | E基準: aws_ec2_capacity_block_reservationは本バージョンで導入 |
環境確認は以下のコマンドで行います。
# 実行アカウント・権限の確認
aws sts get-caller-identity
# 対象リージョンのCapacity Blocks for ML提供状況確認(P5系インスタンス)
aws ec2 describe-instance-type-offerings \
--region ap-northeast-1 \
--filters "Name=instance-type,Values=p5.*" \
--query "InstanceTypeOfferings[].{Type:InstanceType,Location:Location}" \
--output table
# AWS CLIバージョン確認(2.15以上を推奨)
aws --version
# Terraform/providerバージョン確認
terraform version
IAM権限の詳細は2-4で提示しますが、最低限必要なアクションはec2:CreateCapacityReservation / ec2:PurchaseCapacityBlock / ec2:CreateFleet / ec2:AllocateHostsなど、容量予約の作成・GPU予約の購買・Fleet起動・専有ホスト確保を担うアクション群です。
2-2. 使用技術スタック
本Vol3で扱うキャパシティ管理スタックを、IaC・予約・GPU予約・配分・ライセンスの5レイヤに整理します。
| レイヤ | 要素 (Terraformリソース) | 役割 | 東京提供 | 備考 |
|---|---|---|---|---|
| IaC | Terraform 1.9.x / hashicorp/aws >= 5.31 | 容量予約リソースの宣言的管理 | ✓ | E基準: aws_ec2_capacity_block_reservationは5.31で導入 |
| 予約(ODCR) | aws_ec2_capacity_reservation | オンデマンド容量の確実な確保 | ✓ | 全インスタンスファミリー・全リージョンで利用可能 |
| GPU予約 | aws_ec2_capacity_block_reservation | P5系GPUインスタンスの未来日予約 | ✓ | 単一AZ targeted・最大64インスタンス/予約・合計256 |
| 配分 | aws_ec2_fleet | capacity-optimized等の混在配分戦略 | ✓ | On-Demand/Spotの複数インスタンスタイプ・複数AZ分散 |
| ライセンス | aws_ec2_host (Dedicated Hosts) | 物理ホスト確保・BYOL大規模運用 | ✓ | テナンシー/配置の基礎はVol1 §6へ委譲 |
ODCRとCapacity Blocks for MLは似て見えますが、対象と予約単位が異なります。ODCRは任意のインスタンスタイプ・任意の期間(即時〜)を対象にした「容量の確保」であり、Capacity Blocks for MLはGPUインスタンスに限定した「未来日から始まる期間限定の予約」です。GPU逼迫下でP5系インスタンスを確実に確保したい場合はCapacity Blocks for ML、それ以外の一般的な容量確保にはODCRを使うのが基本方針です。
EC2 FleetはODCR/Capacity Blocks/オンデマンド/Spotを組み合わせて「複数の確保手段を横断した配分」を実現するレイヤです。単体のインスタンス起動ではなく、複数インスタンスタイプ・複数AZにわたる配分戦略を一括管理します。
2-3. Terraform初期化 — 3点セット
terraform.tfでrequired_versionとrequired_providersを明示し、S3バックエンドでstateを管理します。aws_ec2_capacity_block_reservationは比較的新しいリソースのため、provider versionの下限指定を厳密に行います。
# terraform.tf
terraform {
required_version = ">= 1.9.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.31"
}
}
backend "s3" {
bucket= "your-org-terraform-state"
key= "compute/vol3-capacity-management/terraform.tfstate"
region= "ap-northeast-1"
dynamodb_table = "terraform-lock"
encrypt = true
}
}
provider "aws" {
region = var.aws_region
default_tags {
tags = {
Project= "compute-production-vol3"
ManagedBy = "terraform"
}
}
}
variables.tfでは、対象インスタンスタイプとCapacity Blocksの予約数を変数化し、環境ごとに切り替えます。
# variables.tf
variable "aws_region" {
description = "デプロイ先リージョン"
type = string
default = "ap-northeast-1"
}
variable "gpu_instance_type" {
description = "Capacity Blocks for MLで予約するGPUインスタンスタイプ"
type = string
default = "p5.48xlarge"
}
variable "capacity_block_instance_count" {
description = "Capacity Blocksで予約するインスタンス数(単一予約あたり最大64)"
type = number
default = 8
}
初期化とバージョン確認は以下の通りです。
terraform init
terraform validate
terraform version
# Terraform v1.9.x
# + provider registry.terraform.io/hashicorp/aws v5.3x.x
terraform validate実行時にprovider versionが5.31未満の場合、aws_ec2_capacity_block_reservationリソースの定義自体がスキーマエラーになります。CI/CDパイプラインではterraform init -upgradeを明示実行し、providerのバージョンドリフトを防ぎます。
2-4. IAM構成
容量予約・Capacity Blocks・Fleet・Host管理に必要な最小権限をJSON例で提示します。運用者ロールには機能単位でSidを分割し、監査時にどの権限がどの機能に対応するかを追跡しやすくしています。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "OnDemandCapacityReservationManagement",
"Effect": "Allow",
"Action": [
"ec2:CreateCapacityReservation",
"ec2:ModifyCapacityReservation",
"ec2:CancelCapacityReservation",
"ec2:CreateCapacityReservationFleet",
"ec2:ModifyCapacityReservationFleet",
"ec2:CancelCapacityReservationFleet",
"ec2:DescribeCapacityReservations",
"ec2:DescribeCapacityReservationFleets"
],
"Resource": "*"
},
{
"Sid": "CapacityBlocksForMLManagement",
"Effect": "Allow",
"Action": [
"ec2:PurchaseCapacityBlock",
"ec2:PurchaseCapacityBlockExtension",
"ec2:DescribeCapacityBlockOfferings",
"ec2:DescribeCapacityBlockExtensionOfferings",
"ec2:DescribeCapacityBlockExtensionHistory",
"ec2:DescribeCapacityBlockStatus"
],
"Resource": "*"
},
{
"Sid": "FleetManagement",
"Effect": "Allow",
"Action": [
"ec2:CreateFleet",
"ec2:ModifyFleet",
"ec2:DeleteFleets",
"ec2:DescribeFleets",
"ec2:DescribeFleetInstances",
"ec2:DescribeFleetHistory"
],
"Resource": "*"
},
{
"Sid": "DedicatedHostManagement",
"Effect": "Allow",
"Action": [
"ec2:AllocateHosts",
"ec2:ModifyHosts",
"ec2:ReleaseHosts",
"ec2:DescribeHosts",
"ec2:DescribeHostReservations"
],
"Resource": "*"
},
{
"Sid": "SharedDescribeForValidation",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstanceTypeOfferings",
"ec2:DescribeInstanceTypes",
"ec2:DescribeAvailabilityZones"
],
"Resource": "*"
}
]
}
Sidを機能単位(ODCR/Capacity Blocks/Fleet/Host)で分割しているのは、後から特定機能だけの権限を剥奪・追加する運用変更が発生しやすいためです。たとえばCapacity Blocks for MLの利用をML基盤チームのみに限定したい場合、CapacityBlocksForMLManagementのSidだけを別ロールに切り出せます。
AWS CLIから個別に権限を確認する場合は以下のように実行します。
# ODCRの一覧確認
aws ec2 describe-capacity-reservations \
--query "CapacityReservations[].{Id:CapacityReservationId,State:State,InstanceType:InstanceType}" \
--output table
# Capacity Blocksのオファリング確認(GPU逼迫状況の事前把握)
aws ec2 describe-capacity-block-offerings \
--instance-type p5.48xlarge \
--instance-count 8 \
--capacity-duration-hours 24
2-5. ゴール状態の定義
本記事を読み終えた時点で、以下の状態に到達します。
| 対象 | 到達状態 |
|---|---|
| ODCR | オンデマンド容量が指定AZ・指定インスタンスタイプで確実に確保され、Organizations経由の共有とCapacity Reservation Groupsによる集約管理が実装されている |
| Capacity Blocks for ML | P5系GPUインスタンスが未来日予約され、ASG/起動テンプレートから予約済み容量を確実に利用できる状態になっている |
| EC2 Fleet | capacity-optimized等の配分戦略により、複数インスタンスタイプ・複数AZにわたる中断耐性と容量確保が両立している |
| Dedicated Hosts | Host Resource GroupsとLicense Managerが連携し、BYOLライセンスの自動配置と監査証跡が整備されている |
| 全体 | GPU逼迫時でも「必要な時に容量が取れない」課題が解消され、コストと可用性を両立した容量確保戦略が自組織の標準運用として整備されている |
各状態の具体的な検証コマンドは§3以降の各セクション末尾に記載します。
3. On-Demand Capacity Reservations (ODCR) — 確実な容量確保の基礎
On-Demand Capacity Reservations (ODCR) は、特定の Availability Zone に対して EC2 の実行容量そのものを確保する機能です。Savings Plans や Reserved Instances が「課金割引」を提供するのに対し、ODCR は割引を提供しない代わりに「容量の存在」を保証します。大規模なスケーリングイベントの前に容量を先取りしたい場合や、災害復旧サイトで容量を確実に確保しておきたい場合に利用します。
3-1. ゾーン指定とインスタンスマッチング条件 — open / targeted
ODCR は AWS リージョン全体ではなく、ap-northeast-1a のような単一の Availability Zone を指定して作成します。予約はインスタンスタイプ・プラットフォーム(OS)・Availability Zone・テナンシーの 4 属性の組み合わせに対して作成され、これらの属性が完全に一致するインスタンスだけが予約枠を消費できます。
即時利用の ODCR はいつでも作成・変更・キャンセルが可能で、コミットメント期間はありません。一方、未来日 ODCR(Future-dated Capacity Reservation)は開始日とコミットメント期間を指定して作成し、対象インスタンスファミリーは C・G・I・M・R・T・U・X 系に限定され、最低 32 vCPU 相当のインスタンス数が必要です。コミットメント期間中はインスタンス数・期間を減らせない点に注意してください。
予約枠に対してどのインスタンスが自動的にマッチするかは instance_match_criteria で制御します。
| instance_match_criteria | 動作 | 適したユースケース |
|---|---|---|
open(既定) | 属性が一致するインスタンスを自動的にマッチさせる。Auto Scaling・ECS・EKS・EMR・SageMaker AI・Batch・Elastic Beanstalk・ParallelCluster・PCS が起動する管理インスタンスも自動対象になる | 単一ワークロードで予約枠を専有せず、複数サービスから柔軟に消費させたい場合 |
targeted | 予約 ID(または後述の Capacity Reservation Group)を明示的に指定したインスタンスのみがマッチする | 意図しないワークロードによる予約枠の消費を防ぎたい場合。Capacity Reservation Group と組み合わせる際の既定パターン |
targeted を使う場合、起動テンプレートまたは実行中インスタンスの CapacityReservationSpecification に予約 ID を明示的に指定する必要があります。ODCR は Dedicated Hosts とは併用できず、Dedicated Instances との併用は可能です。また Windows の BYOL は ODCR と併用できません(RHEL の BYOL は併用可能)。
3-2. Organizations 経由の共有と Capacity Reservation Groups
大規模組織では、容量予約の作成・管理を一元化し、複数アカウントへ配布する運用が現実的です。ODCR は AWS Resource Access Manager (RAM) を介して、特定アカウント・組織単位(OU)・組織全体のいずれかに共有できます。組織/OU への共有には、事前に AWS Organizations でのリソース共有を有効化しておく必要があります。
共有された ODCR の所有権と操作範囲は以下のように分離されます。
| 役割 | できること | できないこと |
|---|---|---|
| 所有者(Owner) | 予約自体の作成・変更・キャンセル。自身が起動したインスタンスの管理 | 消費者(Consumer)が起動したインスタンスの変更 |
| 消費者(Consumer) | 共有された予約枠へのインスタンス起動・自身のインスタンス管理 | 予約自体の変更。他の消費者や所有者のインスタンスの閲覧・操作 |
課金は既定で、所有者が未使用分と自身のインスタンス分を負担し、消費者は自身の起動したインスタンス分のみを負担します。ただし未使用容量分の課金先は、特定の消費者アカウントへ割り当てることも可能です。共有アカウント間では Availability Zone 名の対応関係にズレが生じるため(ap-northeast-1a という同じ AZ 名でも、別アカウントでは別の物理ロケーションを指すこともあります)、共有時は AZ 名ではなく AZ ID(例: apne1-az1)で物理ロケーションを突合してください。
複数の ODCR を横断してターゲティングしたい場合は、AWS Resource Groups を使って Capacity Reservation Group を作成します。グループには自アカウント所有の予約と共有された予約を混在させられ、異なる属性(インスタンスタイプ・AZ 等)の予約も同一グループに含められます。インスタンスをグループにターゲティングすると、グループ内で属性が一致し空きのある予約に自動的にマッチし、いずれかの予約がキャンセル・失効した場合もグループ内の他の予約へ自動的にフェイルオーバーします。マッチしない場合はオンデマンド容量へフォールバックします。意図しない消費を防ぐには、グループに含める各 ODCR 自体も instance_match_criteria = targeted にしておきます。
resource "aws_resourcegroups_group" "ml_training_crg" {
name = "ml-training-capacity-pool"
resource_query {
query = jsonencode({
ResourceTypeFilters = ["AWS::EC2::CapacityReservation"]
TagFilters = [
{
Key = "Project"
Values = ["ml-platform"]
}
]
})
}
}
起動テンプレート側でグループをターゲティングする場合は capacity_reservation_target に capacity_reservation_resource_group_arn を指定します(個別予約を指定する capacity_reservation_id とは排他)。
resource "aws_launch_template" "ml_training" {
name = "ml-training-lt"
instance_type = "m5.4xlarge"
capacity_reservation_specification {
capacity_reservation_preference = "capacity-reservations-only"
capacity_reservation_target {
capacity_reservation_resource_group_arn = aws_resourcegroups_group.ml_training_crg.arn
}
}
}
3-3. unused 予約の課金モデルと Terraform での構築
ODCR で最も見落とされやすいのが課金モデルです。ODCR は「予約している間はオンデマンド相当のレートで課金され続ける」仕組みで、インスタンスを起動しているかどうかに関わらず課金が発生します。予約枠にマッチするインスタンスを実際に起動している時間帯は、そのインスタンス自体の料金だけが発生し予約への追加課金はありません。逆にインスタンスが起動されていない時間帯は「unused reservation」として同じレートで課金されます。
例えば m4.large を 20 台分予約し、実際には 15 台しか起動していない場合、15 台分はインスタンス利用料として、残り 5 台分は unused reservation として、それぞれ m4.large のオンデマンドレートで課金されます。合計コストは 20 台をフル稼働させた場合と同額であり、予約枠を余らせるほど無駄なコストが積み上がる点に注意してください。課金は秒単位の按分で、即時利用の ODCR はアカウントに予約が作成された瞬間から、未来日 ODCR は指定した開始日に予約がプロビジョニングされた瞬間から発生します。
Terraform での ODCR 構築例は以下のとおりです。
resource "aws_ec2_capacity_reservation" "ml_training" {
instance_type = "m5.4xlarge"
instance_platform = "Linux/UNIX"
availability_zone = "ap-northeast-1a"
instance_count = 20
instance_match_criteria = "targeted"
tenancy = "default"
end_date_type = "unlimited"
tags = {
Name = "ml-training-odcr"
Project = "ml-platform"
}
}
instance_match_criteria = "targeted" により、aws_resourcegroups_group.ml_training_crg 経由で明示的にターゲティングされたインスタンスだけが予約枠を消費します。end_date_type = "unlimited" は即時利用型の無期限予約を意味し、期限を切る場合は end_date_type = "limited" と RFC3339 形式の end_date を組み合わせます。unused 予約の課金を最小化するには、instance_count を実運用の稼働台数に近づけて過剰予約を避けるか、後述の Capacity Reservation Fleet や Capacity Reservation Group によって複数ワークロード間で予約枠を融通する設計が有効です。
3-4. 容量確保戦略の選択 — ODCR / Capacity Blocks for ML / Spot / EC2 Fleet
ODCR・Capacity Blocks for ML(§4)・Spot・EC2 Fleet(§5)は、いずれも「必要なときに必要な容量を得る」という同じ課題への異なる解法です。ワークロードの特性に応じた選択フローを以下に示します。
flowchart TD
A[容量確保の要件を確認] --> B{GPU学習/推論で<br>開始日を数週間前に確定できるか}
B -->|Yes・単一AZでよい| C[Capacity Blocks for ML]
B -->|No| D{中断を許容できるか}
D -->|許容できる・コスト最優先| E[Spot + EC2 Fleet]
D -->|許容できない| F{単一インスタンス条件で<br>長期に確実な容量が必要か}
F -->|Yes| G[On-Demand Capacity Reservations]
F -->|No・複数タイプ/AZの最適配分| H[EC2 Fleet<br>capacity-optimized]
C --> I[前払い・利用有無に関わらず予約分は前払い済み]
G --> J[利用有無に関わらずオンデマンドレートで課金]
E --> K[中断リスクあり・料金は最も安価]
H --> L[複数タイプ分散で確保率とコストを両立]
GPU の需給が逼迫する P5 系インスタンスは ODCR の対象外ではありませんが、Capacity Blocks for ML の方が「決まった期間だけ確実に GPU を使いたい」という要件に対して前払い・単一 AZ targeted という明確な制約とともに最適化されています。次節で Capacity Blocks for ML の予約フローを詳説します。
4. Capacity Blocks for ML — GPU (P5) の未来日予約 (★山場1)
Capacity Blocks for ML は、GPU など需給が逼迫しやすいアクセラレーテッドコンピューティングインスタンスを、未来の特定日に向けて事前予約する仕組みです。ODCR が「いつからでも使える容量の確保」を目的とするのに対し、Capacity Blocks for ML は「決まった期間だけ確実に GPU にアクセスしたい」という ML 学習・ファインチューニング特有の要件に特化しています。予約されたインスタンスは EC2 UltraClusters 内に近接配置され、低レイテンシ・ペタビット級のノンブロッキングネットワークで接続されます。
4-1. 予約フロー — 未来日予約・最大64/256・単一AZ targeted
Capacity Blocks for ML は、最大 8 週間先までの予約開始日を指定でき、最短 30 分後から開始するオファリングも検索できます。予約可能なオファリングは describe-capacity-block-offerings API(Terraform では aws_ec2_capacity_block_offering データソース)で日付・インスタンスタイプ・台数・予約時間を指定して検索し、価格は需給によって変動します。価格を確認したうえで予約すると、以降は価格が変わることはありません。
数量には 2 段階の上限があります。1 つの Capacity Block あたり最大 64 インスタンスまで、1 アカウントが保有する Capacity Block 全体では合計最大 256 インスタンスまでです。さらに AWS Organizations 配下の全アカウントを合算しても、ある特定日に予約できる Capacity Block の合計は 256 インスタンスが上限になります。64 インスタンスのブロックサイズは、すべてのインスタンスタイプ・全リージョンでサポートされているわけではないため、describe-capacity-block-offerings で実際に検索して確認してください。
Capacity Blocks for ML は必ず単一 Availability Zone に対する targeted 予約として払い出され、インスタンスを起動する際は予約 ID を明示的にターゲティングする必要があります(open 相当の自動マッチは存在しません)。東京リージョン(ap-northeast-1)では以下の P5 系インスタンスが対象です。
| インスタンスタイプ | GPU | GPUメモリ | vCPU | システムメモリ | ネットワーク帯域 |
|---|---|---|---|---|---|
p5.4xlarge | H100 × 1 | 80 GB HBM3 | 16 | 256 GiB | 100 Gbps EFA |
p5.48xlarge | H100 × 8 | 640 GB HBM3(合計) | 192 | 2 TiB | 3,200 Gbps EFA |
Terraform ではオファリング検索とブロック予約を 2 つのリソース/データソースで組み合わせます。
data "aws_ec2_capacity_block_offering" "p5_training" {
instance_type= "p5.48xlarge"
instance_count = 8
capacity_duration_hours = 336 # 14日間
start_date_range= "2026-08-01T00:00:00Z"
end_date_range= "2026-08-15T00:00:00Z"
}
resource "aws_ec2_capacity_block_reservation" "p5_training" {
capacity_block_offering_id = data.aws_ec2_capacity_block_offering.p5_training.capacity_block_offering_id
instance_platform = "Linux/UNIX"
tags = {
Name = "p5-ml-training-block"
Project = "ml-platform"
}
}
aws_ec2_capacity_block_reservation は hashicorp/aws provider 5.31 以降で利用できます。予約は一度確定すると変更・キャンセルができない(cancellation は許可されない)点に注意してください。
4-2. GPU 逼迫下の確保戦略と ASG・起動テンプレートからの利用
P5 のような GPU インスタンスは需給が逼迫しやすく、必要になったタイミングでオンデマンド起動しても capacity-not-available エラーに直面しがちです。Capacity Blocks for ML はこの課題に対し、学習ジョブのスケジュールが確定した時点(最大 8 週間前)で先に GPU 容量を確保し、当日の起動失敗リスクをゼロに近づける戦略を取ります。予約から起動開始までのライフサイクルは以下のとおりです。
sequenceDiagram
participant U as 運用者
participant EC2 as EC2 Capacity Blocks
participant Bill as 請求システム
participant ASG as Auto Scaling Group
U->>EC2: describe-capacity-block-offerings で空き検索(最大8週間先)
EC2-->>U: オファリング一覧(価格・開始日・台数)
U->>EC2: purchase-capacity-block(予約確定)
EC2->>Bill: 前払い請求処理を開始(payment-pending)
Bill-->>EC2: 決済完了(5分〜12時間以内)
EC2->>EC2: 状態が scheduled に遷移
Note over EC2: 予約開始日時まで待機
EC2->>EC2: 予約開始・状態が active に遷移
U->>ASG: スケジュールスケーリングで desired_capacity を引き上げ
ASG->>EC2: 起動テンプレート経由でCapacityReservationId指定インスタンス起動
EC2-->>ASG: UltraClusters内に近接配置されたP5インスタンス起動完了
Note over EC2: 終了予定時刻11:30 UTCの30分前でスケールインを完了させる
EC2->>EC2: 終了予定時刻11:00 UTCから強制終了プロセス開始
EC2->>EC2: 11:30 UTCに予約終了
Auto Scaling グループから Capacity Blocks を利用する場合、起動テンプレートの CapacityReservationSpecification に予約 ID を明示的に指定します。この方式は Mixed Instances Policy やウォームプールと併用できず、1 つの起動テンプレートが同時にターゲットできる Capacity Block も 1 つに限られます。
resource "aws_launch_template" "p5_training" {
name = "p5-training-lt"
instance_type = "p5.48xlarge"
instance_market_options {
market_type = "capacity-block"
}
capacity_reservation_specification {
capacity_reservation_target {
capacity_reservation_id = aws_ec2_capacity_block_reservation.p5_training.id
}
}
}
resource "aws_autoscaling_group" "p5_training" {
name = "p5-training-asg"
min_size= 0
max_size= 8
desired_capacity = 0
vpc_zone_identifier = [var.subnet_id_in_reservation_az]
launch_template {
id= aws_launch_template.p5_training.id
version = "$Default"
}
}
resource "aws_autoscaling_schedule" "scale_out_at_reservation_start" {
scheduled_action_name = "scale-out-at-reservation-start"
autoscaling_group_name = aws_autoscaling_group.p5_training.name
min_size= 8
max_size = 8
desired_capacity = 8
start_time = "2026-08-01T00:00:00Z"
}
min_size = 0 / desired_capacity = 0 で初期化し、予約開始時刻に合わせたスケジュールスケーリングで一気に desired_capacity を引き上げるパターンが基本形です。スケジュールスケーリングを使うと、起動失敗時のリトライも AWS 側が自動的に処理します。ASG のサブネットは予約と同じ Availability Zone に配置する必要があり、予約終了時刻(11:30 UTC)の 30 分前までにスケールインを完了させないと、EC2 側が強制的にインスタンスを回収します。この強制回収はヘルスチェック失敗として ASG に記録されるため、ライフサイクルフックでアプリケーションの安全な停止処理を組み込んでおくことを推奨します。Amazon EKS を利用する場合も、マネージド/セルフマネージドノードグループの両方で Capacity Blocks 対応のノードグループを作成できます。
4-3. 課金区間 — 前払いと unused 期間の扱い
Capacity Blocks for ML の課金モデルは ODCR と根本的に異なります。ODCR が「予約している間ずっとオンデマンドレートで課金される」のに対し、Capacity Blocks for ML はオファリング確定時点で予約総額が前払いで確定します。決済はオファリング確定から 5 分〜12 時間以内に処理され、決済が完了するまで予約は payment-pending 状態、完了後は scheduled 状態に遷移します。決済に失敗すると予約は payment-failed として解放されます。
予約開始後は、実際にインスタンスを稼働させている時間帯についてのみ OS 利用料(Linux/UNIX は無料、SQL Server 等の有償 OS は課金)が加算されます。重要なのは、予約期間中にインスタンスを起動していない unused の時間帯については追加課金が発生しない点です。これは「未使用分もオンデマンドレートで課金され続ける」ODCR とは対照的な設計であり、Capacity Blocks for ML が「決まった期間の GPU アクセス権を前払いで買い切る」商品であることを反映しています。Savings Plans や Reserved Instances の割引は Capacity Blocks には適用されません。予約のキャンセルも許可されていないため、予約前に describe-capacity-block-offerings でスケジュールと必要台数を十分に精査することが重要です。
5. EC2 Fleet & 容量最適化配分 — capacity-optimized / 混在インスタンス (★山場2)

EC2 Fleet は、複数のインスタンスタイプ・複数のアベイラビリティーゾーン (AZ) を組み合わせた「容量プール」から、On-Demand と Spot を混在させて必要な容量を調達する仕組みです。ODCR や Capacity Blocks for ML が「特定インスタンスタイプの容量を予約で固定する」アプローチであるのに対し、EC2 Fleet は「複数の選択肢を用意し、容量が取れるところから確保する」アプローチであり、両者は補完関係にあります。ここでは allocation strategy の使い分けと、中断耐性と容量確保を両立させる Terraform 構成を提示します。
5-1. allocation strategy の使い分け — 4 方式 + 非推奨 1 方式
EC2 Fleet の allocation strategy には、Spot 用と On-Demand 用がそれぞれ独立して存在します。AWS 公式ドキュメント (Amazon EC2 ユーザーガイド「Use allocation strategies to determine how EC2 Fleet or Spot Fleet fulfills Spot and On-Demand capacity」) に基づく整理は以下のとおりです。
| Allocation Strategy | 対象 | CLI/Terraform 指定値 | 特性 | 主な用途 |
|---|---|---|---|---|
| Price capacity optimized | Spot | price-capacity-optimized | 容量可用性の高いプールの中から最安値を選択。AWS が現在推奨する既定の選択肢 | ステートレスなコンテナ/マイクロサービス/データ分析/バッチ処理など大半の Spot ワークロード |
| Capacity optimized | Spot | capacity-optimized | リアルタイムの容量データに基づき、中断リスクが最も低いプールを優先 | 再起動コストが高い CI、レンダリング、深層学習、HPC |
| Capacity optimized prioritized | Spot | capacity-optimized-prioritized | capacity-optimized をベースに、override の priority でインスタンスタイプの優先順位をベストエフォートで反映 | 中断最小化と特定インスタンスタイプ選好を両立したいワークロード |
| Diversified | Spot | diversified | 全 Spot 容量プールに均等分散。1 プールの価格高騰・枯渇の影響を限定 | 大規模・長時間稼働の Fleet |
| Lowest price (非推奨) | Spot | lowest-price | 価格のみで選択し容量可用性を考慮しない。AWS CLI のデフォルトだが公式に非推奨 | 使用非推奨。既存構成の移行対象として言及 |
On-Demand 側の allocation strategy は lowest-price (デフォルト、最安値プールから充足) と prioritized (override の priority順に充足) の 2 方式のみです。ODCR で確保済みの容量がある場合、On-Demand 分はまず ODCR にマッチングされ、余剰分がオンデマンド市場から調達されます。
- Spot は迷ったら
price-capacity-optimizedを選択する(AWS 推奨・価格と容量可用性のバランスが良い) - 中断コストが高いワークロード(学習ジョブ・レンダリング等)は
capacity-optimizedまたはcapacity-optimized-prioritizedを検討する lowest-priceは中断率が最も高くなるため、新規構成では選択しない
5-2. Terraform で構築する On-Demand × Spot 混在 Fleet
複数インスタンスタイプ・複数 AZ を override で列挙し、target_capacity_specification で On-Demand と Spot の目標容量を分離指定します。
resource "aws_ec2_fleet" "batch_processing" {
type = "maintain"
launch_template_config {
launch_template_specification {
launch_template_id = aws_launch_template.batch_processing.id
version = "$Latest"
}
# 複数インスタンスタイプ × 複数 AZ を候補プールとして登録する
override {
instance_type = "m6i.xlarge"
availability_zone = "ap-northeast-1a"
weighted_capacity = 4
priority = 1
}
override {
instance_type = "m6a.xlarge"
availability_zone = "ap-northeast-1a"
weighted_capacity = 4
priority = 2
}
override {
instance_type = "m6i.xlarge"
availability_zone = "ap-northeast-1c"
weighted_capacity = 4
priority = 1
}
override {
instance_type = "m6a.xlarge"
availability_zone = "ap-northeast-1c"
weighted_capacity = 4
priority = 2
}
override {
instance_type = "m5.xlarge"
availability_zone = "ap-northeast-1d"
weighted_capacity = 4
priority = 3
}
}
target_capacity_specification {
default_target_capacity_type = "spot"
total_target_capacity = 40
on_demand_target_capacity = 8
spot_target_capacity= 32
target_capacity_unit_type = "units"
}
# Spot: 容量可用性と価格のバランスを取る推奨戦略
spot_options {
allocation_strategy= "price-capacity-optimized"
instance_interruption_behavior = "terminate"
}
# On-Demand: ベースラインは最安値プールから調達
on_demand_options {
allocation_strategy = "lowest-price"
}
excess_capacity_termination_policy = "termination"
replace_unhealthy_instances = true
terminate_instances = true
terminate_instances_with_expiration = true
tags = {
Name = "batch-processing-fleet"
Purpose = "capacity-optimized-mixed-fleet"
}
}
total_target_capacity を On-Demand 8 units + Spot 32 units に分割することで、ODCR や Capacity Blocks でカバーしないベースライン容量を On-Demand で確実に確保しつつ、バースト分を Spot でコスト最適化する構成です。weighted_capacity により、インスタンスタイプごとの処理能力差(vCPU 数など)を容量単位に正規化して指定できます。
5-3. capacity-optimized-prioritized による優先度付き配分
中断コストが高いワークロード(長時間バッチや ML 前処理など)では、capacity-optimized-prioritized を使い、override の priority で候補インスタンスタイプの優先順位を明示します。
resource "aws_ec2_fleet" "priority_sensitive" {
type = "maintain"
launch_template_config {
launch_template_specification {
launch_template_id = aws_launch_template.priority_sensitive.id
version = "$Latest"
}
override {
instance_type = "c6i.2xlarge"
availability_zone = "ap-northeast-1a"
priority = 0 # 数値が小さいほど優先度が高い
}
override {
instance_type = "c6a.2xlarge"
availability_zone = "ap-northeast-1a"
priority = 1
}
override {
instance_type = "c5.2xlarge"
availability_zone = "ap-northeast-1c"
priority = 2
}
}
target_capacity_specification {
default_target_capacity_type = "spot"
total_target_capacity = 20
}
spot_options {
allocation_strategy = "capacity-optimized-prioritized"
}
}
capacity-optimized-prioritized では、容量可用性を最優先し、同等の可用性を持つプールが複数存在する場合に限り priority の順序をベストエフォートで反映します。容量確保を犠牲にしてまで優先度を強制しない点が、prioritized (On-Demand 用) との違いです。
5-4. 中断耐性と容量確保の両立を検証する
type = "maintain" の Fleet では、Spot Instance が値上がりや容量枯渇で中断された際、allocation strategy に応じた戦略で自動的に代替インスタンスを補充します。
price-capacity-optimized: 価格を考慮しつつ、容量可用性が高いプールから補充capacity-optimized: 容量可用性が最も高いプールから補充diversified: 残りのプールに分散して補充
検証は以下の手順で行います。
aws ec2 describe-fleet-instances --fleet-id <fleet-id>で現在の充足状況(プールごとのインスタンス数)を確認する- EventBridge の
EC2 Spot Instance Interruption Warningルールを Fleet に紐付け、中断発生から補充完了までの時間を CloudWatch Logs に記録する - CloudWatch メトリクス
TargetCapacityと実際の起動インスタンス数の差分を監視し、容量充足率が閾値を下回った場合にアラームを発報する
複数インスタンスタイプ・複数 AZ を候補として広く登録しておくほど、1 プールが枯渇しても他プールで即座に代替できるため、中断耐性と容量確保率の両方が向上します。
5-5. 詰まりポイント: price-capacity-optimized 使用時の意図しない再作成
spot_options.allocation_strategy = "price-capacity-optimized" を指定した状態で instance_pools_to_use_count を明示しない場合、Terraform の state 上でデフォルト値が意図しない形で扱われ、terraform plan のたびに Fleet の再作成 (force replacement) が発生するケースが報告されています。instance_pools_to_use_count は本来 lowest-price 戦略専用のパラメータであり、price-capacity-optimized では使用されません。回避策として、price-capacity-optimized を使う Fleet では instance_pools_to_use_count を設定に含めず、terraform plan で差分が出続ける場合は provider のバージョンを最新化した上で state を確認することを推奨します。
6. Dedicated Hosts のライセンス大規模運用 — Host Resource Groups × License Manager

Dedicated Hosts自体のテナンシーやPlacement Groupの基礎は、本シリーズVol1 §6-2「Dedicated HostsとDedicated Instances」で解説済みです。本節ではその先、Dedicated Hostsを本番規模で運用する際に必ず直面する「ライセンス管理」に絞って解説します。
6-1. Host Resource Groups による自動配置
Oracle DatabaseやMicrosoft SQL Serverのようなソケット単位ライセンスをDedicated Hostsに持ち込む場合、ホストを1台ずつ手動管理していては大規模運用に耐えません。AWS License Managerの「Host Resource Groups」は、複数のDedicated Hostsを1つの管理単位にまとめ、インスタンス起動時のホスト割当を自動化する機能です。
Host Resource Groupには次の設定項目があります。
- Allocate hosts automatically: グループの空き容量を超えるインスタンス起動があった場合に、新規ホストを自動確保するか
- Release hosts automatically: 実行中インスタンスが0になったホストを自動解放するか
- Recover hosts automatically: 物理障害が発生したホストからインスタンスを自動的に新しいホストへ退避するか
- Associated self-managed licenses: グループで利用できるライセンス設定(License Configuration)
- Instance families: 起動を許可するインスタンスファミリー(Nitroベースなら複数タイプの混在が可能)
Host Resource Groupに登録したDedicated Hostへは、ホストIDを直接指定した起動ができなくなり、必ずグループ経由での起動に統一されます。これにより「どのライセンスがどのホストで消費されているか」を個別のホストID管理に頼らず追跡できます。
運用上の注意点として、Host Resource Group自体は現時点でTerraform AWSプロバイダーにネイティブリソースが存在せず、License ManagerコンソールまたはAWS CLI/SDK経由での作成が必要です。一方、個々のDedicated Host(aws_ec2_host)とライセンス設定(aws_licensemanager_license_configuration)はTerraformで宣言的に管理できるため、「ホストと個々のライセンス設定はコードで管理し、グループへの登録のみAWS CLIまたはCI/CDパイプラインから実行する」というハイブリッド運用が現実的です。
6-2. License Manager 連携 — BYOL / socket-based ライセンス追跡
License Managerのライセンス設定(License Configuration)は、ライセンスの計測単位(vCPU/Instance/Core/Socket)とルールを定義します。Dedicated HostsでのBYOLでは、物理ソケット数が明確に把握できることを活かし、Socket単位でカウントするのが基本です。
resource "aws_licensemanager_license_configuration" "oracle_byol" {
name = "oracle-database-byol"
description= "Oracle Database Enterprise - Dedicated Host BYOL"
license_counting_type = "Socket"
license_count = 8
license_count_hard_limit = true
license_rules = [
"#allowedTenancy=EC2-DedicatedHost",
"#minimumSockets=2",
"#licenseAffinityToHost=180",
]
tags = {
Vendor = "Oracle"
Product = "Database-Enterprise"
}
}
resource "aws_ec2_host" "oracle_host" {
instance_family= "m5"
availability_zone = "ap-northeast-1a"
auto_placement = "on"
host_recovery = "on"
host_maintenance = "on"
tags = {
Name = "oracle-dedicated-host-01"
}
}
resource "aws_launch_template" "oracle_db" {
name_prefix= "oracle-db-"
image_id= data.aws_ami.oracle_linux.id
instance_type = "m5.2xlarge"
placement {
tenancy = "host"
host_id = aws_ec2_host.oracle_host.id
}
license_specification {
license_configuration_arn = aws_licensemanager_license_configuration.oracle_byol.arn
}
}
license_count_hard_limit = trueにすると、ライセンス数の上限(この例では8ソケット分)を超えるインスタンス起動がAPIレベルでブロックされます(ハード制限)。監査の緩さを許容できないBYOL契約では必ず有効にすべき設定です。license_rulesの#allowedTenancy=EC2-DedicatedHostは「Dedicated Hosts以外での起動を許可しない」ことを明示し、共有テナンシーへの誤起動によるライセンス違反を防ぎます。#licenseAffinityToHostはライセンスが特定ホストに紐づく最低日数(1〜180日)を指定するもので、頻繁なホスト入れ替えによるライセンスの二重消費を防ぐ設定です。
aws_launch_templateのlicense_specificationブロックでライセンス設定のARNを紐付けておけば、Auto Scaling Group経由でスケールアウトする場合も、新しいインスタンスが自動的にライセンス消費としてカウントされます。個々の起動のたびにaws_licensemanager_associationでリソースと関連付ける必要がないため、大規模運用に向いています。
6-3. ライセンス監査証跡
BYOLライセンス監査では「いつ・どのホストで・何ソケット分のライセンスが消費されていたか」を証跡として残す必要があります。License Managerは次の手段で証跡を提供します。
- 関連付けられているリソース一覧: ライセンス設定に紐づく現在のリソース(ホスト/インスタンス)をコンソールまたはAPIで取得し、消費状況をリアルタイムで確認
- 利用状況レポート: 消費中のライセンス数と上限に対する使用率をダッシュボードで確認
- AWS CloudTrail: ライセンス設定の作成・更新・リソース関連付けに関するAPI呼び出し履歴を長期保管し、監査時のタイムライン証跡とする
- タグベースの補完証跡: Dedicated Hostのタグにライセンス設定のARNを明示しておくと、コンソール上のホスト一覧からもライセンス設定への対応関係を即座に確認できる
監査証跡を「AWSコンソールのその場の画面」だけに頼ると、監査時点でホストが解放済み(Release hosts automatically経由)だと過去の消費実績を追えなくなります。CloudTrailのログをS3へ長期保管する設定を、ライセンス管理を始める初期段階で必ず組み込んでください。
7. 詰まりポイント7選 図解

ここまで紹介したODCR / Capacity Blocks for ML / EC2 Fleet / Dedicated Hostsは、いずれも「設定はできているのに期待通り動作しない」つまずきが本番運用で頻発します。よくある7つの詰まりポイントを、原因と対策セットで整理します。
7-1. ODCRインスタンスマッチング不一致
症状: ODCRを作成したのに、起動したインスタンスが予約を消費せず、オンデマンド料金のまま課金される。
原因: ODCRはインスタンスタイプ・プラットフォーム(OS)・テナンシー・AZの4条件が完全一致しないと消費されません。特にAMIのプラットフォーム属性(Linux/UNIX・RHEL・Windows等の区分)のズレが見落とされがちです。
対策: aws_ec2_capacity_reservationのinstance_platformと起動側のAMI/Launch Templateの値をCIで機械的に突合します。targeted ODCRではcapacity_reservation_specificationでcapacity_reservation_idを明示的に指定します。これにより、暗黙のopenマッチングへの依存を避けられます。
7-2. unused予約の想定外課金
症状: 月次請求でODCR/Capacity Blocksの未使用時間分の課金が想定より大きい。
原因: ODCRは予約している限り、インスタンスの起動有無に関わらず課金されます。開発環境やスパイク対応用に確保したまま、需要が去った後も解放し忘れるケースが典型です。
対策: ODCRの利用率をCloudWatchメトリクスで監視し、閾値を下回った状態が一定時間続いたら自動解放するEventBridgeルールを組みます。Capacity Blocksは予約期間が固定のため、予約前にGPU需要予測の精度をレビューする運用を徹底します。
7-3. Capacity Blocksの予約タイミング
症状: 予約したCapacity Blocksの開始日時に、起動テンプレートやIAM設定の準備が間に合っていない。
原因: Capacity Blocksは未来日予約のため、予約成立から実際の利用開始まで数日〜数週間のリードタイムがあります。この間の準備(AMI/起動テンプレート/クォータ)が後回しにされやすいのが実情です。
対策: 予約成立をトリガーにEventBridgeで起動準備タスクをキックし、利用開始日の前日にAMI/IAM/クォータの最終確認を機械的に走らせます。
7-4. Fleetのallocation strategy誤選択
症状: EC2 Fleetでcapacity-optimizedを選んだつもりが、実際にはlowest-priceのまま起動され、中断率が想定より高い。
原因: allocation strategyの指定漏れ、あるいはSpot専用パラメータをOn-Demand主体の設定と混在させたことによるデフォルト値へのフォールバックです。
対策: aws_ec2_fleetのspot_options.allocation_strategyを明示的に指定し、terraform planの差分レビューでデフォルト値へのフォールバックが発生していないかを確認します。
7-5. Dedicated Hostsのライセンス数超過
症状: ライセンス上限を超えてインスタンスが起動され、監査時にライセンス違反が発覚する。
原因: license_count_hard_limitをfalse(ソフト制限)のまま運用し、警告のみで起動がブロックされない設定になっていたことによるものです。
対策: 本番BYOLでは§6-2の通りlicense_count_hard_limit = trueを必須化し、terraform側でこの値がfalseになっていないかをpolicy as codeで検査します。
7-6. AZ不一致
症状: ODCRやCapacity Blocksを作成したAZと、Auto Scaling Groupのvpc_zone_identifierが指すサブネットのAZが一致せず、予約が一切消費されない。
原因: マルチAZ構成のASGでは、サブネットIDからAZを都度確認する必要がありますが、複数リージョン/複数環境でterraformモジュールを使い回す際にAZマッピングがずれやすいためです。
対策: data.aws_subnetでサブネットのavailability_zoneを取得し、予約側のavailability_zoneと一致することをCIのpre-planチェックで検証します。
7-7. クォータ上限
症状: Capacity BlocksやDedicated Hostsを追加確保しようとしてAPIエラーになる。
原因: アカウントごとのService Quotas上限(リージョンあたりのDedicated Host数、Capacity Reservation数など)に達しているためです。
対策: Service Quotasのメトリクスをダッシュボード化し、上限の70-80%到達時点でアラートを出します。恒常的に上限に近い場合は、引き上げ申請の審査リードタイムを見込んで事前に申請を提出します。
8. アンチパターン → 正解パターン変換演習 + シリーズ繋ぎ
ここまでの内容を踏まえ、キャパシティ管理でよくあるアンチパターンを正解パターンに変換する演習を5問用意しました。自分の運用がどちらに近いか確認しながら読み進めてください。
設問1: Auto Scaling Groupを組んでいるが、容量予約は何もしていない
- ❌ アンチパターン: On-Demandでインスタンスを起動するだけで満足し、需要ピーク時に「スケールアウトしようとしたが希望のインスタンスタイプの在庫がなかった」という事態を想定していない。
- ✅ 正解パターン: ODCR (
aws_ec2_capacity_reservation) でピーク時に必要な最低限の容量を事前予約し、Auto Scaling Groupの起動テンプレートでその予約をターゲットにする。予約分は追加コストが発生するが、可用性のSLAを守るための保険として設計する。
設問2: GPUインスタンスが必要になった当日、オンデマンドで確保しようとする
- ❌ アンチパターン: ML学習の実行日になってから
p5.48xlargeをオンデマンドで起動しようとし、InsufficientInstanceCapacityエラーで学習スケジュールが崩れる。 - ✅ 正解パターン: 学習スケジュールが確定した時点でCapacity Blocks for ML (
aws_ec2_capacity_block_reservation)を使い、最大8週間先までの未来日予約を確定させる。予約時間のみ課金されるため、コストは学習の実行時間分に限定される。
設問3: EC2 Fleetのallocation strategyをlowest-priceのまま本番運用している
- ❌ アンチパターン: コスト最適化だけを目的に
lowest-priceを選んだ結果、Spotの中断が集中するインスタンスプールに偏り、中断頻発で可用性が低下する。 - ✅ 正解パターン: 中断耐性が求められるワークロードでは
capacity-optimizedを選び、複数インスタンスタイプ・複数AZに分散させることで、コストと容量確保・中断耐性のバランスを取る。
設問4: Dedicated Hostsのライセンス数を手動のスプレッドシートで管理している
- ❌ アンチパターン: BYOLライセンスの割当をExcel等で手動管理し、ホスト追加のたびに更新漏れが発生してライセンス監査で不整合が見つかる。
- ✅ 正解パターン: License Managerでライセンス設定を一元管理し、Host Resource Groupsで対象ホストを自動グループ化することで、ソケット/コア単位のライセンス消費状況を常に自動追跡し、監査証跡として残す。
設問5: ODCRのインスタンスマッチング条件をopenのままにしている
- ❌ アンチパターン: 複数チームが同一アカウントを共有している環境で、ODCRを
open(条件を指定しない共有)のままにし、意図しないワークロードが予約枠を消費してしまう。 - ✅ 正解パターン:
targetedマッチング条件を指定し、特定の起動テンプレート・ASGからのみ予約を利用可能にする。Organizations経由で予約を共有する場合も、共有先アカウントとマッチング条件を明示的に設計する。
以上でAWS Compute本番運用シリーズVol3は完結です。Vol1でインスタンス選定とAuto Scalingの基礎を固め、Vol2でGraviton4と最新世代EC2への移行を終え、本Vol3で容量確保とライセンス制約下のスケーリングという運用の根幹を押さえたことで、EC2の本番運用に必要な設計知識は一通りカバーできたことになります。ODCR・Capacity Blocks for ML・EC2 Fleet・Dedicated Hostsを状況に応じて組み合わせ、可用性とコストの両立した容量管理を実践してください。
シリーズ Vol1 (インスタンス選定 / Spot / 専有・配置基礎) を読む