Claude Media
ClaudeでAWSのコスト急増を調べる — Cost ExplorerのCSVを使用タイプまで分解

ClaudeでAWSのコスト急増を調べる — Cost ExplorerのCSVを使用タイプまで分解

Cost ExplorerのCSVをClaude Codeに渡し、サービス別、使用タイプ別の順に前月差を分解してNAT Gateway、データ転送、CloudWatch Logsなどの原因候補に絞る手順です。

AWSの請求が先月より跳ね上がったとき、最初に要るのは「どのサービスの、どの種類の使用量が増えたか」です。Cost ExplorerのCSVをClaude Codeに渡すと、この絞り込みを3段に分けて短時間で回せます。サービス別、使用タイプ別、リージョンやアカウント別の順です。

この記事は、CSVの出し方、渡す前の権限設定、前月差の寄与を出すスクリプト、使用タイプを典型原因に当てる表までを順に扱います。AWSのAPIには一度も触れないので、Cost Explorer APIのリクエスト課金も発生しません。

急増の調査は3段で絞る

Cost Explorerは、請求の元データと同じデータセットから作った画面です。直近13か月までの日次・月次データを見られ、コスト配分の軸として「サービス」「使用タイプ」「リージョン」「リンクアカウント」などで絞り込めます。

急増の原因を探すときは、いきなり細部を見ずに粗い軸から順に絞ります。

手順

急増の原因に届くまでの3段

  1. 1

    サービスで分ける

    月次、グループ化「サービス」で直近2か月を出します。前月差が最も大きいサービスを1〜2個に絞ります。

  2. 2

    使用タイプで分ける

    絞ったサービスだけをフィルターに入れ、グループ化を「使用タイプ」か「使用タイプグループ」に替えて出し直します。時間課金なのか、処理量課金なのかがここで分かれます。

  3. 3

    リージョンとアカウントで分ける

    増えた使用タイプだけを残し、リージョン、リンクアカウント、タグの順に切り口を替えます。どの環境の変更かがここで見えます。

CSVは各段で1枚ずつ出します。1枚に全部を詰めたCSVより、段ごとのCSVの方がClaudeが読み違えにくく、集計の根拠も追いやすくなります。

Cost ExplorerからCSVを3枚出す

Cost Explorerの画面は無料で使えます。レポート画面には、グラフの元になったデータをCSVでダウンロードする機能があります。出す前に、次の仕様を押さえておきます。

  • 表示できるのは当月と直近13か月までです
  • 反映は前日分までで、当月の数字は後から更新されることがあります
  • 時間の区切りはUTCです
  • 金額は米ドル表示です
  • 時間単位の粒度は、管理アカウントで有効化した場合のみ使えます。見られるのは直近14日間です

月の途中に調査するなら、月次の比較だけでなく日次の粒度も1枚出しておきます。急増が月の何日から始まったかは、日次でしか分かりません。

出す3枚の条件は、次のとおりです。

枚期間と粒度グループ化フィルター
1枚目期間と粒度先月と今月、月次グループ化サービスフィルターなし
2枚目期間と粒度同じ期間、月次グループ化使用タイプグループフィルター1枚目で増えたサービス
3枚目期間と粒度急増の期間、日次グループ化リージョンかリンクアカウントフィルター2枚目で増えた使用タイプ

ファイル名は 01-by-service.csv のように段の名前を付けて、プロジェクト内の専用ディレクトリに置きます。リンクアカウント別に出したCSVにはアカウント単位の請求額が入るため、このディレクトリは .gitignore に入れておきます。

コンソールの比較機能で先に当たりを付ける

Cost Explorerには、2か月の費用を比較して増減の大きいサービス、アカウント、リージョンと、その要因を示す機能があります。コンソールのホームにはTop trendsウィジェットがあり、直近2か月の変動上位10件が出ます。Cost Explorerの画面では、レポートパラメーターのパネルから「Compare」を選びます。この機能に追加料金はかかりません。

CSVを作る前にここで増えたサービスの見当を付けておけば、1枚目の確認が早くなります。比較機能のAPIを使う場合に必要な権限は ce:GetCostAndUsageComparisons と ce:GetCostComparisonDrivers です。

Claude Codeに渡す前に権限を決める

CSVを読ませるだけなら、Claudeに必要なのはファイルの読み取りと、集計スクリプトの実行です。AWSのコマンドは要りません。そこで、aws コマンドを通さない設定にしておきます。

{
  "permissions": {
    "deny": [
      "Bash(aws *)"
    ],
    "allow": [
      "Read(./cost-data/**)",
      "Bash(python3 scripts/diff_cost.py *)"
    ]
  }
}

これを .claude/settings.json に置きます。ルールはdeny、ask、allowの順に評価され、先に一致した結果が採用されます。Bash(aws *) のdenyは、後から別のallowを足しても aws で始まるコマンドを止め続けます。調査の途中で「ついでにCLIで確かめて」と頼まれても、請求データの外へ出ない構成です。

注意が1点あります。Bashのルールは、Claudeが書いたコマンド文字列に対して一致します。aws を別の経路で呼ぶ書き方までは、このルール1本では塞げません。AWS認証情報そのものを、この調査を行うシェルに置かないのが確実です。

権限ルールの書き方と評価順は、/permissionsコマンドの解説にまとめています。

前月差の寄与を出す

1枚目のCSVから、サービスごとの前月差と全体の増加に占める寄与率を出します。計算をClaudeの暗算に任せず、スクリプトに固定します。数字の誤りは請求の調査では致命的です。コードで行わせれば、同じ入力から同じ結果が出て検算もできます。

import csv, sys
 
path, prev_col, curr_col = sys.argv[1], sys.argv[2], sys.argv[3]
top = int(sys.argv[4]) if len(sys.argv) > 4 else 10
 
with open(path, newline="", encoding="utf-8-sig") as f:
    table = list(csv.reader(f))
 
# 期間が列の向きなら、そのまま使う。期間が行の向きなら転置する
if prev_col not in table[0]:
    table = [list(col) for col in zip(*table)]
if prev_col not in table[0] or curr_col not in table[0]:
    sys.exit(f"列名 {prev_col} / {curr_col} が見つかりません。先頭行: {table[0]}")
 
header = table[0]
pi, ci = header.index(prev_col), header.index(curr_col)
 
def num(cell):
    return float(cell.replace(",", "") or 0)
 
rows = []
for r in table[1:]:
    key = r[0]
    if "total" in key.lower():
        continue  # 合計行は寄与の計算から外す
    prev, curr = num(r[pi]), num(r[ci])
    rows.append((key, prev, curr, curr - prev))
 
total_delta = sum(r[3] for r in rows)
print(f"{header[0]},前月,当月,差額,差額の寄与率")
for key, prev, curr, delta in sorted(rows, key=lambda r: -abs(r[3]))[:top]:
    share = delta / total_delta * 100 if total_delta else 0
    print(f"{key},{prev:.2f},{curr:.2f},{delta:+.2f},{share:.0f}%")

このスクリプトは scripts/diff_cost.py に保存します。引数で指定した2つの期間を比較対象として読みます。CSVの向き(期間が列か、期間が行か)と列名は、出力の設定によって変わる場合があります。向きが逆でも動くよう、スクリプトは期間名が先頭行に無ければ転置してから集計します。合計行は、名前に「total」を含む行として外します。先にClaudeに先頭数行を読ませて、向きと列名、合計行の名前を確認させます。

cost-data/01-by-service.csv の先頭5行を読んで、列名、期間が行か列かの向き、合計行の名前を教えて。
そのあと scripts/diff_cost.py を、先月と今月の列名を指定して実行して。
結果の表をそのまま貼って、増加の上位3つだけコメントして。

架空の数字で出力を示すと、次のようになります。

Service,前月,当月,差額,差額の寄与率
Amazon EC2,300.00,780.00,+480.00,77%
Amazon CloudWatch,100.00,230.00,+130.00,21%
Amazon S3,200.00,210.00,+10.00,2%

この例では、増加分の98%を2サービスが占めています。次はEC2に絞った2枚目へ進みます。寄与率が1〜2サービスに偏らず、多数のサービスに分散して増えている場合は、特定の障害ではなく全体の利用増である可能性を先に疑います。

使用タイプを典型原因に当てる

2枚目のCSVでは、使用タイプグループの行名が原因候補への入口になります。Cost Explorerの使用タイプグループには、調査でよく当たる名前が揃っています。

使用タイプグループ計っているもの増えたときの見立て
EC2: NAT Gateway - Running Hours計っているものNAT Gatewayが稼働した時間増えたときの見立てNAT Gatewayの台数や稼働期間が増えた
EC2: NAT Gateway - Data Processed計っているものNAT Gatewayが処理したGB数増えたときの見立てNAT経由の通信量が増えた
EC2: Data Transfer - Inter AZ計っているものAZをまたぐ転送のGB数増えたときの見立てAZ間の通信が増えた
EC2: Data Transfer - Internet (Out)計っているものAWSの外へ出ていく転送のGB数増えたときの見立て外向きの通信が増えた

NAT Gatewayは、稼働している時間と処理したデータ量の両方に課金されます。同じNAT Gatewayでも、時間側が増えたのか処理量側が増えたのかで、疑う先が変わります。

時間側が増えたなら、NAT Gatewayそのものが増えています。AZごとに作った、検証用に作ったまま残っている、といった変更を探します。

処理量側が増えたなら、NAT Gatewayを通る通信が増えています。リソースとNAT Gatewayが別のAZにあるとAZ間転送の料金がかかります。AWSサービス向けの通信が多い場合は、インターフェースエンドポイントかゲートウェイエンドポイントを検討できます。

CloudWatch Logsの急増は、別の見方をします。料金は、取り込み(Collect)、保管(Store)、クエリ(Logs Insightsなどのスキャン量)に分かれています。急増したのがどの課金軸かで、対処が変わります。

  • 取り込みが増えた場合: ログの出力量が増えています。デバッグログの有効化やコンテナログの増加が代表的です。Container Insightsは、ログ1行ごとに700バイトのメタデータを加えます
  • 保管が増えた場合: 保管するデータ量が増えています。ロググループの保持期間の設定を見直します
  • クエリが増えた場合: Logs Insightsのスキャン量が増えています

CloudWatchからのデータ転送(Data Transfer OUT)は、EC2のデータ転送料金と同じ表で課金されます。ログをリージョンの外に出している構成では、ここも確認対象です。

切り分けの順番

使用タイプまで絞れたら、Claudeに次の順で質問を出させます。順序が大事なのは、費用の増え方によって、次に見るデータが別になるからです。

切り分け

使用タイプが増えたときの切り分け

  1. Q増えたのは時間課金の行(Running Hours)か?
    答えが処理量や転送量の行が増えています。次の問いへ進みます

    稼働しているリソースの数が増えています。3枚目のCSVをリージョンとリンクアカウントでグループ化し、どの環境で台数が増えたかを見ます。

    答えがはい
  2. Q増えたのはAZ間転送(Inter AZ)の行か?
    答えがインターネット向け転送、またはサービス固有の処理量を疑います

    構成の変更でAZをまたぐ通信が増えた可能性があります。デプロイや配置の変更日を、日次CSVの立ち上がりの日と突き合わせます。

    答えがはい
  3. Q立ち上がりの日に、リリースや設定変更があったか?
    答えが外部要因、たとえば利用者の増加やバッチの追加を疑います

    その日の変更履歴を、Claudeに読ませる原因候補の根拠にします。突合の進め方は変更カレンダーとの突合手順と同じ形です。

    答えがはい

原因候補を1〜2個に絞って、人が確認する

Claudeが出すのは「請求データの上で何が増えたか」までです。なぜ増えたかは、構成の変更履歴とリソースの実態を見てから決めます。

数字を読み違えやすい3つの場面

CSVの調査で誤りが入りやすいのは、次の3つです。

落とし穴

月の途中の数字を前月の全体と比べている

当月分は前日までの数字で、日数も月末より少なくなります。月初から数日で「前月より低い」と読むのも、月末直前に「前月に迫った」と読むのも、日数が違うまま比べています。月途中の調査は、日次CSVで同じ日数分を並べます。

落とし穴

割引や返金の動きを使用量の増加と取り違える

Cost Explorerには、未ブレンド、償却後、割引後など、金額の見せ方がいくつかあります。日次の未ブレンドコストは返金を含みません。使用量が増えていないのにコストだけ動いて見えるときは、請求の種類(Charge type)で絞って、割引や調整の行を外して見直します。

落とし穴

Claudeに原因まで断定させている

CSVに載っているのは金額と使用量だけです。NAT Gatewayの処理量が増えたことは分かっても、どのアプリの通信かは載っていません。依頼文に「原因を断定せず、CSVから言えることと、追加で確認が要ることを分けて書いて」と入れておくと、推測が事実として並ぶのを防げます。

APIで取りに行くか、CSVで済ませるか

CSVを手で出す方式は、毎月の定例調査には向きません。出す枚数が増えるほど手間も増えます。定期的に回すなら、Cost ExplorerのAPIを呼ぶMCPサーバーを使う選択肢があります。ただしAPIは、ページ付きのリクエスト1回ごとに0.01ドルが課金されます。画面の利用は無料です。

手元の1回きりの調査ならCSV、毎月の定点観測ならMCPサーバーという分け方になります。接続の手順と読み取り専用IAMの絞り方は、AWS Billing MCPサーバーの接続手順で扱っています。

まとめ

急増の調査で大事なのは、Claudeに「原因を当てさせる」のではなく、「どこまで絞れたか」を毎段階で確認することです。サービス、使用タイプ、リージョンの順にCSVを分け、集計はスクリプトに固定し、aws コマンドは通さない。この3点を守れば、請求データの範囲内で安全に原因候補まで進めます。最後の「なぜ増えたか」は、変更履歴を見て人が決めます。

参照した一次ソース

この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。

  1. docs.aws.amazon.com/cost-management/latest/userguide/ce-what-is.html
  2. docs.aws.amazon.com/cost-management/latest/userguide/ce-filtering.html
  3. docs.aws.amazon.com/cost-management/latest/userguide/ce-cost-comparison.html
  4. docs.aws.amazon.com/vpc/latest/userguide/nat-gateway-pricing.html
  5. aws.amazon.com/cloudwatch/pricing
  6. code.claude.com/docs/en/permissions
この記事を共有:XはてブLinkedIn