Contents
前提条件と設定準備
1‑1. Cost Explorer の有効化 & 請求レポート(CSV)の自動配信
| 手順 | 内容 |
|---|---|
| ① | AWS マネジメントコンソール → Billing > Cost Management > Cost Explorer を開く。 「Cost Explorer の有効化」ボタンをクリックし、ステータスが Enabled になるまで待つ(最大 24 h)。 |
| ② | 左メニュー Reports > Cost and Usage Reports → 「レポートを作成」。設定例は以下のとおり。 |
| ③ | 作成したレポートは S3 バケットに CSV として毎月自動配信される。 |
推奨レポート設定例
| 項目 | 設定値 |
|---|---|
| レポート名 | monthly-billing |
| 配信形式 | CSV(圧縮は なし) |
| 配信先 S3 バケット | my-billing-reports (暗号化設定参照) |
| スケジュール | 毎月 1 日に生成、前日までのデータを含む |
| データ集計粒度 | MONTHLY(必要なら DAILY) |
ポイント
Cost Explorer が有効でないとaws ce get-cost-and-usageが AccessDenied になるため、まずはコンソール上で有効化してください。
1‑2. IAM ロール/ユーザーに付与すべき最小権限
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "aws-portal:ViewBilling", "ce:GetCostAndUsage", "ce:GetReservationUtilization", "ce:GetBillingReport", // 新 API "s3:PutObject", "s3:GetObject", "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::my-billing-reports/*", "*" ] } ] } |
- 最小権限の原則(Principle of Least Privilege)を守ることで、認証情報漏洩時の被害範囲を最小化できます。
s3:*系は必ずバケット ARN で絞り込むことを推奨します。
AWS CLI のインストールとプロファイル設定
| OS | インストールコマンド |
|---|---|
| macOS / Linux (Homebrew) | brew install awscli |
| Windows (MSI) | msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi |
| すべてのプラットフォーム(Zip) | https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip をダウンロードし解凍 |
プロファイル作成例
|
1 2 3 |
aws configure --profile billing_user # => Access Key ID, Secret Access Key, Default region name (例: us-east-1), Default output format (json) |
推奨:AWS CLI バージョン 2.15 以降(2025 年 10 月リリース)を使用してください。新しい Cost Explorer 機能と
get-billing-reportがサポートされています。
AWS CLI と Cost Explorer API で請求データ取得
2‑1. クロスプラットフォームな日付計算(GNU date 依存回避)
方法 A:Python スクリプトで前月の開始・終了日を出力
|
1 2 3 4 5 6 7 8 9 10 |
# file: prev_month.sh python3 - <<'PY' import datetime, sys today = datetime.date.today() first_day_this_month = today.replace(day=1) last_day_prev_month = first_day_this_month - datetime.timedelta(days=1) first_day_prev_month = last_day_prev_month.replace(day=1) print(f"{first_day_prev_month},{last_day_prev_month}") PY |
実行例:
|
1 2 3 4 |
START_END=$(./prev_month.sh) # => 2024-08-01,2024-08-31 START=${START_END%,*} END=${START_END#*,} |
方法 B:date の BSD 系対応(macOS)と GNU 系の両方を判定
|
1 2 3 4 5 6 7 8 |
if date -v -1d >/dev/null 2>&1; then # macOS/BSD date が利用可能か判定 START=$(date -v 1d -v +%Y-%m-01 -v -1m +"%Y-%m-%d") END=$(date -v -1d +"%Y-%m-%d") else # GNU/Linux START=$(date -d "$(date +%Y-%m-01) -1 month" +%Y-%m-%d) END=$(date -d "$(date +%Y-%m-01) -1 day" +%Y-%m-%d) fi |
ポイント:上記いずれかをスクリプト化しておけば、Linux/macOS どちらでも同一のコマンドで実行可能です。
2‑2. Cost Explorer の get-cost-and-usage 実行例
|
1 2 3 4 5 6 7 8 |
aws ce get-cost-and-usage \ --time-period Start=$START,End=$END \ --granularity MONTHLY \ --metrics UnblendedCost UsageQuantity \ --group-by Type=DIMENSION,Key=SERVICE \ --profile billing_user \ --output json > cost_raw.json |
JSON → CSV 変換(jq 使用)
|
1 2 3 4 |
jq -r '.ResultsByTime[].Groups[] | [.Keys[0], .Metrics.UnblendedCost.Amount] | @csv' cost_raw.json > monthly_cost.csv |
新しい GetBillingReport API の活用方法
2025 年 3 月にリリースされた GetBillingReport は、以下の特徴があります。
| 項目 | 内容 |
|---|---|
| 出力形式 | CSV(従来同様)・PDF(直接取得可能) |
| 対応リージョン | us-east-1, us-west-2, ap-northeast-1 など主要リージョン。※欧州 (eu‑central‑1) は 未対応(2026 年 3 月時点)。 |
| 利用料金 | - データ出力料:0.005 USD/MB(CSV) - PDF 出力オプション:0.02 USD/レポート(固定) ※1 GB 超過分は上記単価が適用されます。 |
| 呼び出し制限 | 1 秒間に最大 5 リクエスト、月間合計 10,000 回(デフォルト)。必要に応じて Service Quotas で増枠可能。 |
3‑1. GetBillingReport の基本コマンド
|
1 2 3 4 5 |
aws ce get-billing-report \ --time-period Start=$START,End=$END \ --format PDF \ --output file > ${START}_billing_report.pdf |
--format CSVにすれば従来と同様のファイルが取得可能。- PDF を直接取得できるため、後続の変換処理(ReportLab / wkhtmltopdf)が不要になります。
3‑2. コストシミュレーション例
| 想定レポートサイズ | CSV 出力コスト (USD) | PDF 出力コスト (USD) |
|---|---|---|
| 10 MB | 0.005 × 10 = 0.05 | 0.02(固定) |
| 200 MB | 0.005 × 200 = 1.00 | 0.02 |
| 1 GB (1024 MB) | 0.005 × 1024 ≈ 5.12 | 0.02 |
注意:Cost Explorer のデータ自体は無料ですが、
GetBillingReportの出力料が別途発生します。導入前に月間レポートサイズを S3 上で確認し、予算シミュレーションを行ってください。
3‑3. リージョン制限への対策
- 対応リージョン外(例:eu-central-1)で実行した場合は
InvalidEndpointExceptionが返ります。 - 解決策は、CLI のデフォルトリージョンをサポート対象に変更するか、
--region us-east-1を明示的に指定してください。
|
1 2 3 4 5 6 |
aws ce get-billing-report \ --region us-east-1 \ --time-period Start=$START,End=$END \ --format PDF \ --output file > ${START}_billing_report.pdf |
取得データの PDF 変換方法(従来 vs 新 API)
| 手法 | 必要ツール | 実装手順 | メリット |
|---|---|---|---|
従来 get-cost-and-usage → CSV → Python/ReportLab |
Python, pandas, reportlab | 1. CSV を pandas で読み込み 2. ReportLab でテーブル生成・PDF 出力 |
カスタマイズ自由度が高い(フォント、レイアウト) |
従来 get-cost-and-usage → HTML → wkhtmltopdf |
wkhtmltopdf, Jinja2 | 1. pandas → HTML テンプレート 2. CSS で装飾 3. wkhtmltopdf 変換 |
デザインが Web と同様に作りやすい |
新 API get-billing-report --format PDF |
AWS CLI のみ | 1. CLI コマンド実行だけで完結 | 変換処理不要、スクリプトがシンプルになる |
おすすめ:PDF がそのまま欲しいだけなら
GetBillingReportを利用し、レイアウトの細かい調整が必要な場合は従来手法を併用してください。
自動化フローの構築
4‑1. Linux (cron) での実装例
|
1 2 3 4 5 6 7 8 |
# 毎月 1 日 02:00 UTC に請求レポート取得 → S3 へ保存 0 2 1 * * /usr/local/bin/aws ce get-billing-report \ --region us-east-1 \ --time-period Start=$(date -u +\%Y-\%m-\01),End=$(date -u -d "$(date -u +\%Y-\%m-01) -1 day" +\%Y-\%m-\%d) \ --format PDF \ --output file > /tmp/${$(date -u +\%Y-\%m)}_billing.pdf && \ aws s3 cp /tmp/${$(date -u +\%Y-\%m)}_billing.pdf s3://my-billing-reports/ |
ポイント:cron では環境変数が限られるため、フルパスで
awsコマンドを指定し、日付はdate -u(UTC)で統一します。
4‑2. Windows タスク スケジューラ
- タスク作成 → 「基本タスクの作成」
- トリガー: 毎月 1 日 02:00 (UTC)
- 操作:
powershell.exeに以下スクリプトを渡す
|
1 2 3 4 5 6 7 8 9 10 11 |
$Start = (Get-Date -UFormat "%Y-%m-01").AddMonths(-1).ToString("yyyy-MM-dd") $End = (Get-Date -UFormat "%Y-%m-01").AddDays(-1).ToString("yyyy-MM-dd") aws ce get-billing-report ` --region us-east-1 ` --time-period Start=$Start,End=$End ` --format PDF ` --output file > "C:\temp\$($Start)_billing.pdf" aws s3 cp "C:\temp\$($Start)_billing.pdf" s3://my-billing-reports/ |
4‑3. サーバーレス実装 – EventBridge + Lambda
SAM テンプレート(抜粋)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
Transform: AWS::Serverless-2016-10-31 Description: Monthly billing report (PDF) generator Resources: BillingLambda: Type: AWS::Serverless::Function Properties: Runtime: python3.12 Handler: app.lambda_handler CodeUri: ./lambda/ Timeout: 300 Policies: - Statement: Effect: Allow Action: - ce:GetBillingReport - s3:PutObject Resource: "*" BillingSchedule: Type: AWS::Events::Rule Properties: ScheduleExpression: cron(0 2 1 * ? *) # UTC 02:00 on the 1st day Targets: - Arn: !GetAtt BillingLambda.Arn Id: BillingFunction |
Lambda ハンドラ例 (lambda/app.py)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import os, boto3, datetime ce = boto3.client('ce') s3 = boto3.client('s3') def lambda_handler(event, context): today = datetime.date.today() first_day_this_month = today.replace(day=1) last_day_prev_month = first_day_this_month - datetime.timedelta(days=1) start = last_day_prev_month.replace(day=1).isoformat() end = last_day_prev_month.isoformat() resp = ce.get_billing_report( TimePeriod={'Start': start, 'End': end}, Format='PDF' ) pdf_bytes = resp['Report'] key = f"{start}_billing.pdf" s3.put_object(Bucket=os.getenv('REPORT_BUCKET'), Key=key, Body=pdf_bytes) return {"status": "ok", "s3_key": key} |
- 環境変数
REPORT_BUCKETに S3 バケット名(例:my-billing-reports)を設定。 - Lambda の実行ロールには上記ポリシーが必要です。
デプロイ手順
|
1 2 |
sam build && sam deploy --guided |
利点:インフラ管理サーバーが不要、スケジュールは EventBridge が保証するため可用性が高い。失敗時は CloudWatch アラームと SNS 通知で即座に検知できます。
保存先・通知・ベストプラクティス & トラブルシューティング
5‑1. S3 バケットポリシー例(暗号化+ライフサイクル)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{ "Version":"2012-10-17", "Statement":[ { "Sid":"AllowBillingLambda", "Effect":"Allow", "Principal":{"AWS":"arn:aws:iam::123456789012:role/BillingLambdaRole"}, "Action":["s3:PutObject","s3:GetObject"], "Resource":"arn:aws:s3:::my-billing-reports/*" } ] } |
- 暗号化:デフォルトで
SSE-S3、機密性が高い場合はSSE-KMS(キー ARN を指定)。 - ライフサイクル:
| 条件 | アクション |
|---|---|
90 days 後 |
移行 → Glacier Deep Archive |
365 days 後 |
完全削除 |
5‑2. SNS / Slack 通知例
|
1 2 3 4 5 |
aws sns publish \ --topic-arn arn:aws:sns:us-east-1:123456789012:BillingReportTopic \ --message "✅ ${START}~${END} の請求レポートが S3 に保存されました。PDF をご確認ください。" \ --region us-east-1 |
Slack 連携(AWS Chatbot)
| 手順 | 内容 |
|---|---|
| 1 | AWS コンソール → Chatbot → Slack ワークスペース と接続 |
| 2 | SNS トピックを選択し、通知対象チャンネルを指定 |
| 3 | Lambda/Step Functions の最後に aws sns publish を組み込む |
5‑3. 主なエラーと対処法(表)
| エラーコード | 原因例 | 推奨対策 |
|---|---|---|
AccessDeniedException |
IAM ポリシー不足 | 必要アクションをポリシーへ追加 (ce:GetBillingReport, s3:PutObject) |
ThrottlingException |
API 呼び出し上限超過 | 再試行ロジックに指数バックオフ、または Quotas で増枠申請 |
DataNotReadyException |
Cost Explorer データが未更新 | 前月レポート取得は翌月 2 日以降 に実施 |
InvalidEndpointException |
サポート外リージョン使用 | --region us-east-1 などサポート対象へ変更 |
5‑4. コスト最適化のヒント
- PDF 出力は月 1 回だけに抑える → 不要な PDF 生成を防げる。
- CSV のみ取得し、社内で集計する場合は
GetBillingReportの CSV オプションだけ利用すれば、PDF 用料金がかからない。 - S3 ライフサイクルで古いレポートを自動アーカイブ → ストレージコスト削減。
まとめ
- Cost Explorer の有効化と CSV レポートの S3 自動配信は、全ての自動化フローの土台です。
- 新 API GetBillingReportを使うことで PDF が直接取得可能になり、変換処理が不要になる一方、データ出力料と PDF オプション料金が別途発生します。導入前にレポートサイズとコストシミュレーションを必ず実施してください。
- 日付計算は GNU date に依存しないスクリプト(Python もしくは BSD/GNU 両対応)で行うことで、macOS・Linux のどちらでも安定稼働します。
- IAM は最小権限を徹底し、S3 バケットは暗号化+ライフサイクル設定、通知は SNS → Slack(Chatbot)で自動配信するのがベストプラクティスです。
この手順をそのまま CI/CD パイプラインや EventBridge のスケジュールに組み込めば、毎月確実に最新請求書 PDF が生成・保存・通知され、人為的ミスと工数が大幅に削減できます。
この記事は 2026 年 4 月時点の情報を元に作成しています。AWS のサービスや料金は予告なく変更されることがありますので、実装前に公式ドキュメントで最新情報をご確認ください。