EBS gp2→gp3で月40万円浮かせた。実測メトリクスで見つけた地雷と対策
月100万円のEBS費用を棚卸ししてわかった真実。gp2からgp3に移行して20%削減、さらにスナップショット戦略で追加削減。実装で踏んだ地雷も全部話します。
gp2が月80万円を食ってた話
うちのチームは去年の秋、AWS費用の棚卸しをしてて気づいたんです。EBSだけで月100万円超。本番環境でgp2が大量に残ってるのに気付いて、「あ、これやばい」って。
正直、gp2から移行するまで後回しにしてたんですよ。既存リソースの設定変更だし、パフォーマンスに影響ないだろうって甘く見てたんですよ。でも実測してみたら、gp3で20%コスト下げて、IOPS・スループット性能も上げられる。これやらない手はないと。
2026年時点では、gp3はすでに標準になってるし、AWSコンソールでもgp3推奨になってます。ただ、実際に移行するとなると結構手間。スナップショット戦略もセットで見直さないと、古いスナップショットで無駄が溜まったまんまなんですよね。
EBS gp2→gp3移行の現実的なプロセス
うちがやった流れはシンプルですが、落とし穴がいくつかありました。
大事なのは、gp3に単に変更するだけじゃなく、IOPS・スループット設定を「本来の使用量に合わせる」ことなんです。デフォルトのgp3は3,000 IOPS / 125 MB/sで出荷されますが、ぶっちゃけこれ過剰な場合がほとんど。
うちの本番DBはgp2で1TB、IOPS最大化してました。これをgp3に変更する際、実際のメトリクスをCloudWatchで3週間見て、ピーク時で400〜500 IOPSだってわかった。スループットは5MB/s程度。このレベルだと、gp3のデフォルトより下げられる。
// CloudWatch メトリクスから取得した実測値
{
"VolumeReadOps": {
"peak": 520,
"average": 180,
"percentile_95": 450
},
"VolumeWriteOps": {
"peak": 480,
"average": 200,
"percentile_95": 420
},
"VolumeReadBytes": {
"peak_throughput_mbps": 6.2
}
}
実測値をもとに、うちは以下の設定で進めました。
| ボリュームタイプ | サイズ | IOPS | スループット | 用途 |
|---|---|---|---|---|
| 本番DB用 | 1TB以上 | 3,000 | 125 MB/s | デフォルトのまま運用 |
| 小ぶりな環境 | 500GB未満 | 1,000 | 50 MB/s | コスト最適化重視 |
| 検索エンジン用 | - | 6,000 | 200 MB/s | パフォーマンス優先 |
実装のポイント: EC2をスナップショット→新gp3ボリュームから起動するやり方もあるし、EBS Elasticで直接変更する方法もあります。2026年ならEBS Elasticが安定してるので、本番環境に影響を最小化できるんですよね。
# AWS CLIでgp2をgp3に変更(実際に使った例)
aws ec2 modify-volume \
--volume-id vol-1234567890abcdef0 \
--volume-type gp3 \
--iops 3000 \
--throughput 125
# 進捗確認
aws ec2 describe-volumes-modifications \
--volume-ids vol-1234567890abcdef0
スナップショット管理で月40万円浮かせた話
ここが地味だけど一番効果でかかったんです。スナップショット戦略を整理する前、うちはスナップショットが「自動で増殖」してました。
毎日深夜0時と12時に自動取得、そのまま30日分保持。これが100ボリューム以上あるから、月間で数千個のスナップショットが溜まる。古いのも新しいのも一律に保存してる状態だった。S3コスト最適化と同じですよ。古いデータをずっと保有するのは金を捨ててるのと一緒。
実装した3段階スナップショット戦略は、こんな感じです。
ホットスナップショット(直近7日) 毎日取得して、RPO を4時間程度に設定。ストレージはStandardで、緊急復旧が必要になったときのために確保。
ウォームスナップショット(8〜30日) 週1回のみ取得(木曜夜中)で、RPOは3日。古いスナップショットを圧縮して保持し、監査・コンプライアンス対応に使う感じです。
コールドスナップショット(31日〜1年) 月1回のみ取得(月初)で、手動管理。RPOは30日なので、アーカイブや法務要件への対応用ですね。
# Lambda で実装したスナップショット自動削除(実際のコード)
import boto3
from datetime import datetime, timedelta
ec2 = boto3.client('ec2')
def lambda_handler(event, context):
# 7日以上前のスナップショットを削除
retention_days = 7
cutoff_date = datetime.utcnow() - timedelta(days=retention_days)
response = ec2.describe_snapshots(
OwnerIds=['self'],
Filters=[
{'Name': 'tag:ManagedBy', 'Values': ['auto-snapshot']}
]
)
for snapshot in response['Snapshots']:
snapshot_time = snapshot['StartTime'].replace(tzinfo=None)
if snapshot_time < cutoff_date:
try:
ec2.delete_snapshot(SnapshotId=snapshot['SnapshotId'])
print(f"Deleted: {snapshot['SnapshotId']} (created: {snapshot_time})")
except Exception as e:
print(f"Failed to delete {snapshot['SnapshotId']}: {str(e)}")
return {'statusCode': 200, 'deleted_count': len([s for s in response['Snapshots'] if s['StartTime'].replace(tzinfo=None) < cutoff_date])}
正直、古いスナップショットほとんど使わないんですよ。「念のため」で保持してたけど、実際に復旧が必要になったときは直近のやつ。だから段階的に削除基準を厳しくしても問題ないわけです。
AWS構成図: EBS最適化の全体像
subgraph AWS_Region["AWS リージョン"]
subgraph VPC["VPC"]
subgraph AZ_A["AZ-A"]
EC2_A["EC2インスタンス<br/>タイプ: t3.xlarge"]
EBS_A1["EBS gp3<br/>1TB<br/>3000 IOPS<br/>$52/月"]
EBS_A2["EBS gp3<br/>500GB<br/>1000 IOPS<br/>$18/月"]
EC2_A -.->|attach| EBS_A1
EC2_A -.->|attach| EBS_A2
end
subgraph AZ_B["AZ-B"]
EC2_B["EC2インスタンス<br/>タイプ: t3.large"]
EBS_B1["EBS gp3<br/>1TB<br/>3000 IOPS<br/>$52/月"]
EC2_B -.->|attach| EBS_B1
end
end
subgraph S3_Region["S3"]
Snapshots["スナップショット管理<br/>ホット: 7日<br/>ウォーム: 30日<br/>コールド: アーカイブ"]
end
subgraph Monitoring["監視・管理"]
CloudWatch["CloudWatch<br/>IOPS・スループット<br/>監視"]
Lambda["Lambda<br/>自動削除スケジュール"]
SNS["SNS通知<br/>削除実績"]
end
EBS_A1 -.->|snapshot| Snapshots
EBS_A2 -.->|snapshot| Snapshots
EBS_B1 -.->|snapshot| Snapshots
CloudWatch -->|monitor| EBS_A1
CloudWatch -->|monitor| EBS_B1
Lambda -->|delete old| Snapshots
Lambda -->|notify| SNS
end
style AWS_Region fill:#FF9900,color:#000
style Snapshots fill:#4CAF50,color:#fff
style Lambda fill:#FF9900,color:#000
style CloudWatch fill:#4CAF50,color:#fff
コスト削減の実測値
実際に2026年3月〜7月で削減がどう推移したか、データを取ってみました。
xychart-beta
x-axis [3月, 4月, 5月, 6月, 7月]
y-axis "月額コスト (万円)" 30, 110
line [100, 90, 75, 68, 60]
line [80, 80, 40, 40, 40]
legend
- EBS容量料
- スナップショット料
3月時点ではEBS容量100万円 + スナップショット80万円 = 月180万円かかってたんです。
7月時点だとEBS容量60万円 + スナップショット40万円 = 月100万円に。
削減額: 月80万円(45%削減)
この中で、gp2→gp3移行で月40万円削減、スナップショット戦略で月40万円削減。ほぼ半々ですね。スナップショット戦略を甘く見てた自分たちの失敗ですよ。
2026年のEBS最適化で気付いたポイント
1. gp3のIOPS・スループットは「実測値ベース」で設定する
デフォルトの3,000 IOPS / 125 MB/sは過剰な場合がほとんど。CloudWatchで3週間観測して、95パーセンタイルで設定すれば十分です。セーフティマージンを10%とれば本番環境でも余裕なんですよね。
2. スナップショット自動削除は必須
Lambdaで自動化しないと、だんだん古いのが溜まる。最初は手動でやってたけど、人間はミスする。環境ごと・ボリュームタイプごとに異なるポリシーを持つのが現実的です。
3. gp3はAZ間のコピーコストに注意
スナップショットをコピーするときは、クロスAZだとデータ転送料が発生する。うちは同一AZ内でのみスナップショット保有にしました。
4. io1/io2との選び分けは「本当に必要か」で判断
io系は高IOPS専用ですが、月額が跳ね上がる。実測で6,000 IOPS以上が継続的に必要でなければgp3で十分なんですよ。うちの本番DBもgp3で安定してます。
まとめ
EBS最適化は地味だけど、確実に効きます。僕たちの場合は月80万円削減できた。2026年なら自動化ツールも整ってるので、実装ハードルも低い。
次のアクションとしては、こんな流れがいいと思います。
- CloudWatchで3週間、自分たちのEBSメトリクスを計測する → IOPS・スループット実績を把握
- スナップショット保有ポリシーを書く → ホット・ウォーム・コールドの3段階で十分
- Lambda で削除を自動化 → 毎月定期実行で古いスナップショットを削除
- gp2から移行するボリュームを優先順位付け → 大容量のDBボリュームから開始
- 1ヶ月後に削減額を確認 → CloudWatch Costで実績を可視化
正直、やらないと損です。本番環境の安定性を落とさず、50%近くコスト下げられる。これ以上に効率良い最適化は少ないと思ってますよ。