クラウドに移行して半年、1年と経過すると、「毎月の請求額がじわじわ上がっている気がする」という悩みを耳にする機会が増える。原因をAWS Cost Explorerで調べてみると、インスタンス費用ではなく「EBS」「Elastic IP」「スナップショット」といった地味なリソースが積み重なっていることが少なくない。
オンプレミスでは電源を落とせばコストはほぼゼロになるが、クラウドでは「存在しているだけで課金が発生し続ける」リソースがある。誰も使っていないディスクボリュームが月々数千円、関連付けられていないIPアドレスが積み重なり、気づけば数万円の無駄が生まれていた、というのは現場あるあるだ。
この記事では、月額費用を静かに押し上げる「放置リソース」の種類と料金感覚、AWS CLIやマネジメントコンソールを使った洗い出しの具体的な手順、安全に削除するための確認ポイント、そして定期棚卸しを仕組み化する方法まで、実務ベースで順に解説する。
なぜクラウドでは「放置」がコストになるのか
オンプレミスのサーバーは、電源を落としてラックに刺さったままでも、追加の電気代と設置スペース代くらいしかかからない。購入費は減価償却で固定コストとして扱われ、使わなければ維持費が膨らむことはない。
AWSの料金体系は根本的に異なる。リソースが「プロビジョニングされている(割り当てられている)」時点で課金が発生するものが多く、実際に使っているかどうかは関係ない。
代表例を挙げると次のとおりだ。
・EBSボリューム: EC2にアタッチされていなくても、ボリュームが存在する限りGB単位で課金
・Elastic IP: EC2やNAT Gatewayに関連付けられていない状態では、1件あたり約$0.005/時間(月約$3.6)の課金
・スナップショット: 増分保存ではあるが、長期放置すると累積データ量に比例して積み上がる
・ロードバランサー(ALB/NLB): 定額のLCU料金が存在し、トラフィックゼロでも基本料金がかかる
・NAT Gateway: 削除しない限り時間課金が続く
こうした「放置コスト」は、1件1件は小さくても、開発環境・本番環境・ステージング環境が混在するアカウントでは気づかないうちに積み重なる。インフラエンジニアとして定期的な棚卸しの習慣を持つことが、クラウド運用コスト管理の第一歩だ。
月額コストを発生させる主な未使用リソースの種類
棚卸しの対象となる主要な放置リソースを、料金の目安とともに整理しておく(料金は2026年7月時点・東京リージョン ap-northeast-1 の目安)。
1. 未アタッチEBSボリューム
EBSボリュームはEC2インスタンスを削除しても、デフォルト設定では自動削除されないケースがある(特にルートボリューム以外の追加ボリューム)。インスタンス削除後もボリュームだけが残り続ける。
料金の目安は以下のとおり。
| ボリュームタイプ | 料金(GB/月) | 100GBで月額 |
|---|---|---|
| gp3(汎用SSD) | $0.096/GB | 約$9.6 |
| gp2(旧汎用SSD) | $0.12/GB | 約$12 |
| st1(スループット最適化HDD) | $0.048/GB | 約$4.8 |
開発・テスト用の500GBボリュームがそのまま残っていれば、月$48~$60相当が無駄になる計算だ。
2. 未関連付けElastic IP
Elastic IPはEC2インスタンスや NAT Gatewayに関連付けられていない場合に課金が発生する。関連付けられている間は無料だが、解放し忘れるとじわじわ積み上がる。
・1件あたり $0.005/時間(未関連付け時のみ)
・月換算で約 $3.6(1件)
・10件放置なら月 $36 の無駄
「確保だけしておいて後で使おう」と思ったまま忘れるケースが典型的だ。
3. 古いEBSスナップショット
スナップショットはEC2 AMIの作成や手動バックアップ時に生成される。増分保存のため1回のサイズは小さくても、数か月分が積み重なると無視できないコストになる。
・$0.05/GB/月(東京リージョン)
・AMI 1本あたり50GBのスナップショットが10本あれば 500GB = 月$25
特に「テスト用AMIを念のため取っておいた」ケースでは、AMIと紐づくスナップショットが削除されずに残ることが多い。
4. 停止中のEC2インスタンス(EBSコストに注意)
EC2インスタンスを「停止(Stop)」しても、アタッチされたEBSボリュームの課金は継続する。「とりあえず止めておいた」インスタンスが実はコストを発生させている、という盲点になりやすい。
5. 未使用のロードバランサー(ALB/NLB)
Application Load Balancer(ALB)はターゲットが0件でも基本料金がかかる。
・ALB固定料金: $0.0243/時間(東京リージョン)
・月換算で約$17.5(トラフィックゼロでも)
検証環境でALBを作ったまま放置するとじわじわ積み上がる。
AWS CLIで未使用リソースを洗い出す
AWS CLIを使えば、各リソースの状態をコマンド一発でリスト化できる。アカウント全体の棚卸しには以下のコマンドが役立つ。
1. 未アタッチEBSボリュームの一覧取得
# ステータスが "available"(未アタッチ)のEBSボリュームを一覧表示 aws ec2 describe-volumes \ --filters "Name=status,Values=available" \ --query "Volumes[*].{ID:VolumeId,Size:Size,Type:VolumeType,AZ:AvailabilityZone,Created:CreateTime}" \ --output table \ --region ap-northeast-1
出力されたボリュームIDとサイズを確認し、本当に不要なものをリストアップする。削除コマンドは後述の「安全な削除手順」で行う。
2. 未関連付けElastic IPの一覧取得
# 関連付けされていないElastic IPを一覧表示 aws ec2 describe-addresses \ --query "Addresses[?AssociationId==null].{AllocationId:AllocationId,PublicIP:PublicIp,Domain:Domain}" \ --output table \ --region ap-northeast-1
AssociationId が null のものが未関連付けのIPだ。
3. 古いスナップショットの一覧取得
# 自分のアカウントのスナップショット一覧(起動時刻・サイズ付き) aws ec2 describe-snapshots \ --owner-ids self \ --query "Snapshots[*].{ID:SnapshotId,Size:VolumeSize,Desc:Description,Started:StartTime}" \ --output table \ --region ap-northeast-1
# AMIに紐づいていないスナップショットだけを抽出する場合 # (先に現在のAMIのスナップショットIDリストを取得) aws ec2 describe-images \ --owners self \ --query "Images[*].BlockDeviceMappings[*].Ebs.SnapshotId" \ --output text > /tmp/ami-snaps.txt # その後、上記リストに含まれないスナップショットを手動確認
4. 停止中のEC2インスタンス一覧
# 状態が "stopped" のEC2インスタンスを一覧表示 aws ec2 describe-instances \ --filters "Name=instance-state-name,Values=stopped" \ --query "Reservations[*].Instances[*].{ID:InstanceId,Type:InstanceType,State:State.Name,Name:Tags[?Key=='Name']|[0].Value,Stopped:StateTransitionReason}" \ --output table \ --region ap-northeast-1
停止中インスタンスはEC2の時間課金はかからないが、アタッチされたEBSは課金継続であることを忘れずに。
5. 未使用のロードバランサー(ターゲットなし)
# ALBの一覧を取得 aws elbv2 describe-load-balancers \ --query "LoadBalancers[*].{Name:LoadBalancerName,DNS:DNSName,State:State.Code,Created:CreatedTime}" \ --output table \ --region ap-northeast-1 # 特定ALBのターゲットグループを確認 aws elbv2 describe-target-groups \ --load-balancer-arn
\ --query "TargetGroups[*].{Name:TargetGroupName,Protocol:Protocol,Port:Port}" \ --output table \ --region ap-northeast-1
AWS Trusted AdvisorとCompute Optimizerの活用
CLIによる棚卸しは網羅的だが、手動確認の手間が大きい。マネージドサービスを組み合わせることで、自動的に「無駄なリソース」を検出できる。
AWS Trusted Advisorのコストチェック項目
AWS Trusted Advisorは「コスト最適化」カテゴリで以下の項目を自動チェックする。
・使用率の低いEC2インスタンス: CPU使用率が14日間で平均10%以下のインスタンスを検出
・関連付けされていないElastic IP: 未関連付けEIPを一覧表示
・アイドル状態のロードバランサー: トラフィックがほぼゼロのALB/ELBを検出
・使用率の低いEBSボリューム: 読み書きがほぼないボリュームを検出
Business/EnterpriseサポートプランではTrusted Advisorの全チェックが利用できる。Developerプラン以下では一部のコアチェックのみとなるが、EIPチェックなど基本的なものは無料枠でも確認できる。
Trusted Advisorの使い方の詳細はAWS Trusted Advisor入門|コスト削減・セキュリティ改善チェックを自動化する実践ガイドも参照してほしい。
AWS Compute Optimizerの活用
AWS Compute Optimizerは機械学習を使って「オーバースペックなEC2インスタンス」「使用率の低いEBS」を自動検出し、サイズダウン推奨を提示してくれる。未使用リソースの直接検出は得意ではないが、「停止しても影響のないインスタンス」の判断材料として活用できる。
AWS Compute Optimizer入門|EC2インスタンスを自動最適化してコストを削減する実践ガイドで詳しく解説している。
Cost Explorerで「見えないコスト」を発見する
月次コストが想定より高い場合、まずCost Explorerで「サービス別コスト」を確認する。
AWS Cost ExplorerとAWS Budgets入門でも解説しているが、棚卸しの観点では以下のフィルタリングが有効だ。
・フィルタ「使用タイプ」で「EBS:VolumeUsage」を選択: EBSのGB/月コストをサービス別に確認
・「Elastic IP」で絞り込み: ElasticIP:IdleAddress というコードで未関連付けIPの費用を確認
・「グループ化」をリソースIDに設定: どの特定ボリューム/IPが費用を出しているかを特定
Cost Explorerの「リソースID別」ビューはデフォルトでは無効なので、設定から「リソースIDの詳細を有効化」をオンにしておく(有効化後、翌日からデータ収集開始)。
削除前の確認ポイントと安全な手順
「不要そうだから削除」は危険だ。特にEBSボリュームとスナップショットは削除すると元に戻せない(S3バックアップがない限り)。以下の確認フローで安全に進める。
EBSボリューム削除前のチェックリスト
・タグを確認する: Name、Project、Env、Owner タグが付いているか
・作成日を確認する: 最後にアタッチされたのはいつか(CreateTime と Attachment 履歴)
・スナップショットを先に取る: 確信が持てない場合は削除前にスナップショットを一時保存
・OwnerのSlack/メールに確認を入れる: Ownerタグがあれば必ず事前確認
安全な削除コマンド
# 削除前に最後のスナップショットを取得(任意だが推奨) aws ec2 create-snapshot \ --volume-id vol-0abc1234def56789 \ --description "pre-deletion-backup-20260720" \ --region ap-northeast-1 # EBSボリュームの削除 aws ec2 delete-volume \ --volume-id vol-0abc1234def56789 \ --region ap-northeast-1 # Elastic IPの解放 aws ec2 release-address \ --allocation-id eipalloc-0abc1234def56789 \ --region ap-northeast-1 # スナップショットの削除 aws ec2 delete-snapshot \ --snapshot-id snap-0abc1234def56789 \ --region ap-northeast-1
削除後は Cost Explorer で翌日以降にコストが消えていることを確認する習慣をつけよう。
タグ戦略で「誰のリソースか」を明確にする
放置リソースが生まれる根本原因の一つは「誰が作ったかわからない」状態だ。タグ設計として最低限以下を徹底することを推奨する。
| タグキー | 値の例 | 目的 |
|---|---|---|
| Owner | yamada@example.com | 担当者特定 |
| Project | web-app-v2 | プロジェクト紐づけ |
| Env | dev / stg / prod | 環境区別 |
| ExpiresAt | 2026-09-30 | 有効期限(一時リソース向け) |
AWSコスト配分タグと組み合わせることで部門別コスト可視化も可能だ。詳細はAWSコスト配分タグ入門を参照してほしい。
定期棚卸しを自動化する仕組み
月1回の手動棚卸しでは漏れが出る。EventBridgeとLambdaを組み合わせることで、毎週自動的に未使用リソースをSlackやメールに通知する仕組みを作れる。
アーキテクチャのイメージ
・EventBridge: 毎週月曜9時にLambdaをトリガー
・Lambda(Python): CLIと同等のdescribe-volumes / describe-addresses をSDKで実行、未使用リソースを集計
・Amazon SES または SNS: 担当者にメール通知(EBSボリューム○件、Elastic IP○件の未使用リソースあり)
# Lambda関数内(Python + boto3)のコア部分のイメージ import boto3 def lambda_handler(event, context): ec2 = boto3.client('ec2', region_name='ap-northeast-1') # 未アタッチEBSの取得 volumes = ec2.describe_volumes( Filters=[{'Name': 'status', 'Values': ['available']}] )['Volumes'] # 未関連付けEIPの取得 addresses = ec2.describe_addresses()['Addresses'] unassociated_eips = [a for a in addresses if 'AssociationId' not in a] # 通知メッセージを組み立てて送信(SNS等で通知) ...
完全実装にはIAMロールへの権限付与(ec2:DescribeVolumes、ec2:DescribeAddresses 等の読み取り権限)も必要だ。削除は通知のみにとどめ、実際の削除は人間の判断で行う設計が安全だ。
削減効果の試算(実例シナリオ)
中規模チームでありがちな「放置状態」を想定した試算例を示す。
| 放置リソース | 内訳 | 月額コスト目安 |
|---|---|---|
| 未アタッチEBSボリューム | 500GB(gp3)× 3本 | 約 $144 |
| 未関連付けElastic IP | 5件 | 約 $18 |
| 古いスナップショット | 1,000GB累積 | 約 $50 |
| 未使用ALB | 2台 | 約 $35 |
| 合計 | — | 約 $247/月(年間約 $2,964) |
これは1ドル150円換算で月約3.7万円、年間約44万円の無駄になる。決して珍しくない状況だ。
よくあるトラブルと対処法
Q: EBSを削除したらEC2が起動しなくなった
ルートボリュームを誤って削除したケースで起こる。削除前にルートボリュームかどうかを必ず確認する。describe-volumesの出力で Attachments[0].Device が “/dev/xvda” や “/dev/sda1” になっているものはルートボリュームだ。
Q: Elastic IPを解放したがEIPのコストが翌日も出ている
Cost Explorerのデータ反映に24~48時間かかる場合がある。数日待って確認する。解放後に billing で「Elastic IP」のコードが残っていなければ正常に処理されている。
Q: スナップショットを削除しようとしたが「InvalidSnapshot.InUse」エラーが出た
AMIに紐づいているスナップショットは、先にAMIの登録解除(deregister-image)を行ってからスナップショットを削除する必要がある。
# 1. AMIの登録解除 aws ec2 deregister-image \ --image-id ami-0abc1234def56789 \ --region ap-northeast-1 # 2. その後でスナップショットを削除 aws ec2 delete-snapshot \ --snapshot-id snap-0abc1234def56789 \ --region ap-northeast-1
Q: 複数リージョンに放置リソースがある場合、一括確認できるか
AWS Configを有効化することで、全リージョンにわたるリソースの変更履歴と現在の状態を一元管理できる。AWS Config入門と組み合わせると、マルチリージョンでの棚卸しを効率化できる。
本記事のまとめ
クラウドの「放置リソース」コストは、1件1件は小さくても積み重なると無視できない金額になる。オンプレミスの感覚のままでは気づきにくい罠だが、棚卸しの手順と自動化の仕組みを一度作ってしまえば、継続的に削減効果を維持できる。
まとめとして、放置リソース棚卸しの実施ステップを整理する。
| ステップ | 作業内容 | 使うツール |
|---|---|---|
| ① 発見 | 未アタッチEBS・未関連付けEIP・古いスナップショットを洗い出す | AWS CLI / Trusted Advisor |
| ② 確認 | Ownerタグ・作成日・依存関係を確認 | マネジメントコンソール |
| ③ 削除 | 確認済みのものから削除(必要ならスナップショットを先取り) | AWS CLI |
| ④ 確認 | 翌日以降にCost Explorerでコスト消滅を確認 | Cost Explorer |
| ⑤ 予防 | タグ設計の強制・Lambda定期通知で再発防止 | EventBridge + Lambda |
月1回の棚卸しを習慣にするだけで、クラウドコストの10~20%程度を削減できるケースは珍しくない。まずは今日、AWS CLIで未アタッチEBSを一覧表示するところから始めてみてほしい。
PR
放置リソースの棚卸しからReserved Instance戦略、FinOpsの実践まで、AWSコスト削減の全体像をカバーした一冊。現場で使える試算シートと削減施策のチェックリストが充実しており、コスト管理を組織的に進めたいエンジニア・チームリーダーに特に向いている。
