服务网格 23:网格指标怎样用于 SLO
先选服务边界,再算错误率
frontend → orders 调用链(orders 先调用 inventory,成功后再调用 external-stub)跨越多跳。Istio 的 HTTP 请求指标可以分别由客户端代理和服务端代理报告,reporter="source" 与 reporter="destination" 并不是两个互不重叠的用户请求集合。若把两侧 istio_requests_total 直接相加,或者把库存服务的请求数当成 frontend 对用户的请求数,分母从一开始就错了。
要回答“frontend 对用户的成功率”还是“inventory 入站调用的成功率”,先选择一个明确的边界,再固定 destination_workload、命名空间、reporter、窗口和所包含的 HTTP 状态。示例固定在 service-mesh-lab 命名空间;若采集端汇聚多个集群,还须按实际暴露的集群标签限定同一目标集群,并在三个选择器中保持一致。以下 PromQL 仅是待在冻结版本核对标签与指标类型后的查询示意,不是本站抓取到的值;它衡量的是指定服务入站 HTTP 尝试中代理观测到的 5xx 比率,不自动等于完整用户 SLO:
1 | |
这个式子要先防零分母,再约定是否把代理本地拒绝、网关失败与不经目标入站代理的请求计入 SLO。版本切换后 v1/v2 都要纳入相同边界,否则部署 v2 会让计算“凭空变好”。用一个时间点的 counter 差值算请求率也不够;Prometheus 的 rate 需要观察窗口和足够样本,采集间隔、重启与缺失抓取都须记录。
p99 不能从各实例的 p99 再平均
如果冻结版以经典直方图暴露 istio_request_duration_milliseconds_bucket,服务总体 p99 应先按相同观测边界汇总各实例的桶,再在累计分布上求分位数:
1 | |
单位是毫秒;桶插值得到的是估计值,并非第 N 个请求的精确耗时。若使用 native histogram 或部署版本改变了桶/名称,必须改用对应查询,不能照抄此式。客户端真实等待时间还包括目标服务外的排队、网络、前置跳数和可能的重试;库存服务的 p99 不能直接命名为“用户 p99”。
固定输入做正负对照
先发送带唯一 ID 的固定数量正常 quote,核对客户端完成数、各代理 reporter 维度计数、库存应用日志及采集到的样本窗口。负例需在隔离测试桩中新增可控的库存侧 5xx,再配置一次真实代理重试:把逻辑请求数、客户端最终响应、各上游尝试数分别汇总,说明哪种计数变大了;现有库存 GET /quote 尚无可控 5xx 接口,也不能拿第 01 篇的应用重发冒充代理重试。延迟负例使用已有 -quote-delay,同时核对客户端 deadline 与库存实际处理时间。以同样的时间窗口和查询范围比较,不把模拟的输入数当成采集系统已成功保存的样本数。
| 验收项 | 实际计数/窗口/版本 |
|---|---|
| 正常请求及两端 reporter 对照 | NOT_RUN:无 Kubernetes/Istio/Prometheus |
| 5xx 分母与重试尝试数 | NOT_RUN |
| 跨实例桶聚合及延迟对照 | NOT_RUN |
最后才谈标签基数:response_code、工作负载、来源/目标等维度可用于聚合,但不能把每次请求的 X-Request-ID 作为指标标签,否则每个请求新增时间序列;逐请求检索交给日志或追踪。若未冻结抓取端和保留策略,不能宣称上述查询已经得到可用 SLO。
在同一采集窗口核对分母
以下命令在 examples/service-mesh 目录执行,使用 04 章 Kubernetes 1.33.4 / Istio 1.27.0 sidecar 基线,应用容器名 app。先清理前章授权、故障与出口策略;下列预期值尚不是集群实测结果。
1 | |
mainline/23/telemetry.yaml 显式选择 prometheus provider。Prometheus 使用 Istio 1.27.0 仓库的 samples/addons/prometheus.yaml;先把文件下载到证据目录、记录哈希再安装,避免把 latest 采集配置混进冻结实验。
1 | |
另一个终端保留 OUT 路径,在至少两个抓取样本之后查询。mainline/23/errors.promql 选择 destination reporter、整个 inventory Service,包含 v1/v2;分母为零时不产生健康百分比。p99.promql 先合并 le 桶,再计算分位数。
1 | |
断言首先检查 JSON status 为 success,结果非空、值不是 NaN,并记录查询时间;空结果不是 0% 错误率。100 是输入逻辑请求数,increase 的窗口边缘外推可能得到非整数,也可能包含其他请求,不能直接断言样本恰等于 100。为精确计数对照,应使用无其他流量的短实验窗口,保留抓取时间与 counter 原值。
错误组复用 15 章 fault-lab /quote?mode=fail,查询中的 destination_service_name 改为 fault-lab;预期 destination 的 5xx 分子增加。延迟组请求 mode=slow,先后比较相同桶与窗口。恢复 mode=ok 并再发送正常组,要求新短窗口错误比例下降,而不是要求包含故障历史的 5 分钟窗口立刻归零。最后删除 telemetry.yaml;仅当 Prometheus 是本章专门创建时删除保存的 addon 清单。没有真实 Prometheus 查询结果时,不能把 PromQL 语法检查算成 SLO 已验收。
固定源码入口:Istio 1.27.0 pilot/pkg/networking/telemetry/telemetry.go。该链接用于核对配置生成或执行机制;完整资源和命令保存在 examples/service-mesh/mainline/23/。静态检查通过不等于集群实验通过。
练习与参考解答
- 客户端发 100 次,目的端指标有 103 次,能直接说丢了 3 次请求吗?参考解答:不能。先检查重试是否导致多次上游尝试、指标窗口和所选维度;用户完成数与代理尝试数不是同一分母。
- 两个库存实例 p99 分别为 10ms 与 100ms,平均值 55ms 是否为整体 p99?参考解答:不是。需要同一边界、同一桶配置、同一窗口下的桶数据聚合,再计算整体分位数。
从测量值到目标与错误预算
SLI 是按上述边界得到的测量值,SLO 则还需要目标与评估窗口。假设约定“frontend 在滚动 30 天内,合格用户请求的成功率至少为 99.9%”,并预先定义合格请求和成功响应,那么基于请求数的错误预算就是该窗口合格请求数的 0.1%。若合格请求为 100 万次,预算为 1000 次失败;已有 700 次失败时剩余 300 次。这是算术示例,不是本系列实测;按请求数定义的预算也不能直接换成停机分钟数。前面的 5 分钟错误率可用于短窗口观察,单凭它无法判定 30 天目标是否达成。库存某一跳的 p99 同样不能替代 frontend 的端到端延迟 SLI。目标、窗口与指标的定义见 Google SRE 的服务级别目标说明。
官方资料与系列导航
- Istio 标准指标:请求数、延迟及
reporter等标签含义。 - Istio 查询指标:采集与查询的使用入口。
- Prometheus Histograms and Summaries:桶聚合、分位数与误差边界。
系列导航:22 访问日志怎样区分代理失败和业务失败 → 23 网格指标怎样用于 SLO(本文)→ 24 自动追踪为什么仍会断链。
