See full diagram gallery for interactive versions
Custom Prometheus exporter that queries the AWS Cost Explorer API and exposes billing data as Prometheus gauges. Replaces the AWS/Billing CloudWatch namespace (which requires manual opt-in and only updates ~4x/day).
|
|
| Namespace |
monitoring |
| Image |
python:3.12-slim (installs boto3 + prometheus_client at startup) |
| Port |
9090 (/metrics) |
| Scrape Interval |
6 hours (Cost Explorer API, not Prometheus scrape) |
| API Cost |
~$0.04/month ($0.01 per request, 4 requests/day) |

| Metric |
Type |
Labels |
Description |
aws_cost_total_usd |
Gauge |
— |
Total blended cost for current billing month |
aws_cost_by_service_usd |
Gauge |
service |
Cost per AWS service for current month |
aws_cost_daily_usd |
Gauge |
date |
Daily blended cost (last 14 days) |
aws_cost_daily_service_usd |
Gauge |
date, service |
Daily cost per service (last 14 days) |
aws_cost_scrape_duration_seconds |
Gauge |
— |
Time to complete Cost Explorer API query |
aws_cost_scrape_errors_total |
Counter |
— |
Number of failed scrape attempts |
aws_cost_last_scrape_timestamp |
Gauge |
— |
Unix timestamp of last successful scrape |
| Resource |
Kind |
Details |
aws-cost-exporter-script |
ConfigMap |
Python exporter script + requirements.txt |
aws-cost-exporter |
Deployment |
1 replica, Recreate strategy |
aws-cost-exporter |
Service |
ClusterIP :9090 |
aws-cost-exporter |
ServiceMonitor |
300s scrape interval, release: kube-prometheus-stack |
aws-cost-exporter-alerts |
PrometheusRule |
4 alert rules (see below) |
| Env Var |
Value |
Purpose |
LISTEN_PORT |
9090 |
Metrics HTTP port |
SCRAPE_INTERVAL |
21600 |
6 hours between Cost Explorer API calls |
AWS_DEFAULT_REGION |
us-east-1 |
Cost Explorer API region |
DAILY_LOOKBACK_DAYS |
14 |
Days of daily cost history to expose |
kubectl create secret generic aws-cost-exporter-credentials -n monitoring \
--from-literal=AWS_ACCESS_KEY_ID='<key>' \
--from-literal=AWS_SECRET_ACCESS_KEY='<secret>'
IAM policy required — ce:GetCostAndUsage on *:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "ce:GetCostAndUsage",
"Resource": "*"
}]
}
| Alert |
Condition |
For |
Severity |
AWSMonthlyCostHigh |
aws_cost_total_usd > 120 |
1h |
warning |
AWSDailyCostSpike |
delta(aws_cost_total_usd[24h]) > 10 |
30m |
warning |
AWSCostExporterDown |
up{job="aws-cost-exporter"} == 0 |
10m |
warning |
AWSCostDataStale |
Last scrape > 12h ago |
30m |
warning |
|
Requests |
Limits |
| CPU |
10m |
100m |
| Memory |
64Mi |
128Mi |
kubernetes/apps/aws-cost-exporter/aws-cost-exporter.yaml