指标会被数两次,标签要花钱
一句话总结
sidecar 会对每个请求上报标准指标(istio_requests_total、istio_request_duration_milliseconds 等)并留下访问日志。Telemetry API 是在命名空间、工作负载级别修改它们的机制——增加标签(tagOverrides)、删除标签(REMOVE)、关闭指标(disabled),以及按条件过滤日志(filter)。
为什么需要它
网格的承诺之一是“不修改代码,就能用同样的格式看到所有服务的请求数、错误率和延迟”。因为所有请求都要经过 sidecar,所以这是可行的。不过放着不管会出现两个问题。
第一是成本。标准指标带有来源、目的地、响应码、协议等多个标签,延迟直方图的每个桶都会产生一条时间序列。服务有几百个时,首先不堪重负的是 Prometheus。第二是不足。“这是哪个客户(tenant)的请求”这样业务所需的维度,在标准标签里是没有的。
Telemetry API 用一份配置就能处理这两点。可以按整个网格(istio-system)、命名空间、工作负载选择器的顺序逐步收窄地应用。
工作原理
指标会被计数两次。在 sidecar 模式下,一个请求会由发送方 sidecar(reporter="source")和接收方 sidecar(reporter="destination")各计一次。两者都在网格内时,同一个数量会累积两次,所以求和时必须把 reporter 固定为一个。以接收方(destination)为准,通常更接近“服务收到的请求”。
Prometheus 是抓取的。发行包的 Prometheus 插件会根据 Pod 注解,定期(这套配置是 15 秒)抓取 sidecar 合并后的指标端口。所以发送请求后要过大约一个周期,才会出现在查询结果中。sidecar 现在持有的值,可以用 pilot-agent request GET stats/prometheus 直接查看。
用 Telemetry 修改的内容
| 配置 | 作用 |
|---|---|
tagOverrides: {tenant: {value: "request.headers['x-tenant']"}} |
用请求属性创建新标签 |
tagOverrides: {request_protocol: {operation: REMOVE}} |
删除标准标签 |
match: {metric: REQUEST_DURATION}, disabled: true |
不生成该指标 |
accessLogging: [{filter: {expression: "response.code >= 400"}}] |
只对符合条件的请求留下日志 |
如果把取值无限增长的东西(用户 ID、请求 ID)做成标签,时间序列就会爆炸。增加标签时,先考虑取值的个数。而且计数器不会被清除,所以修改配置的效果只体现在新产生的时间序列上。
用 PromQL 算出比率。错误率是 sum(5xx) / sum(전체)(占位符为全部请求)。生产仪表板用 rate(…[5m]) 看最近一个窗口的比率,但在请求很少的实验中,直接用计数器相除也可以。两种情况下,分子和分母都必须指向同一个 reporter、同一个目的地。
在现场相遇的样子
“仪表板上的请求数是负载均衡器的两倍”——没有过滤 reporter 就直接相加了。
“加了 tenant 标签后,Prometheus 的内存飙升”——客户有几万个。这是应该用日志或跟踪而不是标签来查看的维度。
“缩减访问日志之后,故障分析变难了”——只留下错误的话,就看不到“原本正常的请求是从什么时候开始变慢的”。条件表达式里常常也会同时加入延迟(response.duration)。
官方文档:Telemetry API、Customizing Istio Metrics、Istio Standard Metrics、Envoy Access Logs、Prometheus addon
下一项实验要做什么
在随发行包的 Prometheus 插件一同部署的网格中,发送请求并用 HTTP API 查询 istio_requests_total,看到同一个请求被按 source、destination 计数两次。用 Telemetry API 添加 tenant 标签、删除不用的标签、关闭延迟指标、把访问日志过滤为只留下错误,最后用一行 PromQL 算出错误率。