之前在 AWS 上搞监控,如果你用了 OpenTelemetry(OTel),通常需要这样一条链路:
应用 → OTel Collector → Prometheus(自建)→ Grafana
或者:
应用 → OTel Collector → CloudWatch Agent → CloudWatch Custom Metrics(按指标数计费,贵)
现在 CloudWatch 直接支持 OTLP 协议接收指标、用 PromQL 查询,还按 GB 计费。翻译成人话:不需要自建 Prometheus 了,也不用担心指标数爆炸账单飞起。
这次更新具体给了什么
- 原生 OTLP 端点 —— 应用直接往 CloudWatch 发 OTel 格式的指标
- PromQL 查询 —— 不用学 CloudWatch 那套查询语法,直接写 PromQL
- Prometheus 兼容 API —— Grafana 直连 CloudWatch 当 Prometheus 数据源
- 按 GB 计费 —— 不再按指标数(metric count)收费
- 15 个月存储 —— 自动保留,不需要额外配置 retention
- 70+ AWS 服务的 vended metrics —— 和你的自定义指标放一起查
对比一下老方案
| 维度 | 自建 Prometheus | CloudWatch 旧方案 | CloudWatch + OTel(新) |
|---|---|---|---|
| 部署 | EC2/EKS + 运维 | 托管 | 托管 |
| 接入协议 | Prometheus scrape | CloudWatch Agent/PutMetricData | OTLP(推送) |
| 查询语言 | PromQL | CloudWatch Metrics Insights | PromQL |
| 计费模型 | EC2 成本 | 按指标数($0.30/metric/mo) | 按 GB 接入量 |
| 存储 | 自己管 | 15 个月(标准分辨率) | 15 个月(含) |
| 高可用 | 自己搭 | 内置 | 内置 |
| Grafana 兼容 | 原生 | 需插件 | 原生(Prometheus API) |
关键变化:计费从"按指标数"变成"按 GB"。
这对微服务架构来说太重要了——之前每个 Pod 暴露几百个指标,服务一多指标数轻松过万,每月光 CloudWatch Custom Metrics 就几百刀。现在按 GB 算,指标数不再是负担。
怎么接入
方案 1:OTel Collector 直推 CloudWatch
# otel-collector-config.yaml
receivers:otlp:protocols:grpc:endpoint: "0.0.0.0:4317"http:endpoint: "0.0.0.0:4318"exporters:awscloudwatch:region: "us-east-1"namespace: "MyApp"# 新的 OTLP 模式,不再需要转换为 EMFmode: "otlp_native"service:pipelines:metrics:receivers: [otlp]exporters: [awscloudwatch]
方案 2:应用直接发 OTLP
from opentelemetry import metrics
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter# 直接指向 CloudWatch OTLP 端点
exporter = OTLPMetricExporter(endpoint="https://otlp.monitoring.us-east-1.amazonaws.com:4317",headers={"x-aws-region": "us-east-1"}
)reader = PeriodicExportingMetricReader(exporter, export_interval_millis=60000)
provider = MeterProvider(metric_readers=[reader])
metrics.set_meter_provider(provider)# 正常使用 OTel API 记录指标
meter = metrics.get_meter("my-service")
request_counter = meter.create_counter(name="http_requests_total",description="Total HTTP requests",unit="1"
)# 在业务代码中
request_counter.add(1, {"method": "GET", "path": "/api/users", "status": "200"})
方案 3:Grafana 直连 CloudWatch(Prometheus API)
# grafana datasource 配置
apiVersion: 1
datasources:- name: CloudWatch-PromQLtype: prometheusurl: https://aps.us-east-1.amazonaws.com/workspaces/YOUR_WORKSPACE_IDaccess: proxyjsonData:sigV4Auth: truesigV4Region: us-east-1
配好之后,在 Grafana 里直接写 PromQL:
# 查询过去 5 分钟的请求率
rate(http_requests_total{service="my-api"}[5m])# P99 延迟
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket{service="my-api"}[5m]))# AWS vended metrics 也能用 PromQL 查
aws_ec2_cpu_utilization{instance_id="i-0123456789abcdef0"}
迁移路径
如果你现在是自建 Prometheus:
- 不需要改应用代码 —— OTel SDK 不变,只改 exporter 目标地址
- 不需要改 Grafana dashboard —— PromQL 查询不变,只改数据源
- 不需要改告警规则 —— 基于 PromQL 的 alert 直接迁移
实际操作就三步:
# 1. 改 OTel Collector 的 exporter
sed -i 's/prometheus_remote_write/awscloudwatch/' otel-collector-config.yaml# 2. 改 Grafana 数据源 URL
# 从 http://prometheus:9090 → CloudWatch Prometheus 兼容端点# 3. 关掉 Prometheus 实例
kubectl delete statefulset prometheus
什么场景用新方案
适合的:
- 微服务 50+ 个,指标数上万,自建 Prometheus 运维成本高
- 已经在用 OTel SDK,想减少基础设施
- 团队不想管 Prometheus 的存储扩容、高可用、备份
- 希望 AWS 服务指标和应用指标统一查询
不适合的:
- 指标量很小(< 100 个),按指标数计费可能更便宜
- 需要 Prometheus 的 recording rules、federation 等高级功能(CloudWatch 未必全支持)
- 合规要求数据不能出自己的 VPC(需要确认 OTLP 端点的网络路径)
注意事项
- 区域限制 —— 除 UAE、Bahrain、Tel Aviv 外的所有商用区域可用
- 计费细节 —— "按 GB" 指的是接入数据量,不是存储量。具体定价看 CloudWatch pricing 页面
- 和 AMP 的关系 —— Amazon Managed Prometheus(AMP)仍然存在,新功能是 CloudWatch 原生集成。如果你已经在用 AMP 跑得好好的,不一定要迁
- Collector vs 直推 —— 生产环境建议保留 OTel Collector 做缓冲和批处理,别让应用直连
总结
CloudWatch 这次更新做了一件正确的事:拥抱开源标准,而不是强推私有协议。
对于已经在 OTel + Prometheus 生态的团队来说,现在多了一个"把 Prometheus Server 卸掉、用 CloudWatch 托管"的选项。该不该迁,看你们自建 Prometheus 的运维成本——如果团队有专职 SRE 盯着,自建可能更灵活;如果是开发团队兼职运维,CloudWatch 托管能省不少心。
文档:https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/working_with_metrics.html
定价:https://aws.amazon.com/cloudwatch/pricing/
