TT Lab
开始
学习 学习路径 课程

Envoy 内部结构

从五百个数字里只取你要的

在 TT Lab 中继续学习

目标

把统计名称的结构分为三个分支来看,依次掌握取出的方法、拆分的规则和去掉的方法,然后亲自确认修改名称后会有什么消失。

为什么重要

统计是仪表板和告警赖以立足的基础。而这个基础是由名称构成的,如果不了解名称的规则,就无法把在 /stats 中看到的值转换为仪表板查询,随手改动名称还会让图表整个变空。此外,如果分不清计数器和 gauge,就会卡在“重置了却没有变化”上;如果不了解排除列表的性质,就会拖延说“需要了再打开”,结果到真正需要的时候才发现没有过去的值。

步骤

  1. 启动两个上游——8093 为 ok,8094 为 fail。在 /root/envd-stats/stats.yaml 中放置 stat_prefix 为 shop 的监听器以及集群 good、bad 并启动(管理端口 9971,监听器 127.0.0.1:10071)。请求五次 /hello、一次 /bad/x 之后,在 /root/envd-stats/01-names.txt 中写入 cluster=、http=、listener= 三行——分别是 cluster.good.upstream_rq_total、http.shop.downstream_rq_total,以及该监听器的 downstream_cx_total 统计的完整名称。
  2. 给 /stats 加上 filter,只取出包含 upstream_rq_total 的统计,再同时加上 format=json,保存到 /root/envd-stats/02-filter.json。并在 /root/envd-stats/02-filter.txt 中写入 total_stats=(不加过滤器时得到的行数)和 matched=(经过过滤器缩小后的统计个数)两行。
  3. 获取 /stats/prometheus,把对应 cluster.good.upstream_rq_total 的那一行保存到 /root/envd-stats/03-prom.txt。并在 /root/envd-stats/03-prom.map 中写入 envoy_name=(在 Prometheus 中的指标名称)、label_key=(包含集群名称的标签的键)、value=(其值)三行。
  4. POST /reset_counters 之后,重新读取两个统计,在 /root/envd-stats/04-reset.txt 中写入 counter_before=、counter_after=(cluster.good.upstream_rq_total)和 gauge_before=、gauge_after=(cluster.good.membership_total)四行。
  5. 创建 /root/envd-stats/stats-tags.yaml——与 stats.yaml 相同,但在最顶层放置 stats_config.stats_tags,用正则表达式 ^cluster\.((.+?)\.) 提取标签名称 envd_cluster。启动并请求两次 /hello 之后,把 /stats/prometheus 中带有 envd_cluster 标签的一行保存到 /root/envd-stats/05-tags.txt。
  6. 创建 /root/envd-stats/stats-trim.yaml——用 stats_config.stats_matcher.exclusion_list 排除前缀为 cluster.bad. 的统计。启动后,在 /root/envd-stats/06-trim.txt 中写入 before=(第 5 步配置中的全部统计行数)、after=(此配置中的行数)、bad_stats=(此配置中以 cluster.bad. 开头的行数)三行。
  7. 创建 /root/envd-stats/stats-rename.yaml——在第 1 步的配置中只把 stat_prefix 从 shop 改为 checkout。启动并请求两次 /hello 之后,在 /root/envd-stats/07-rename.txt 中写入 old_prefix_stats=(以 http.shop. 开头的统计行数)、new_prefix_stats=(以 http.checkout. 开头的行数)、new_rq_total=(http.checkout.downstream_rq_total 的值)三行。
  8. 在 /root/envd-stats/08-report.md 中写入 counter_after_reset=、gauge_after_reset=(第 4 步)、prom_label=(第 5 步添加的标签名称)、trim_removed=(第 6 步的 before 减去 after 的值)、renamed_lost=(第 7 步中旧前缀的统计消失了则为 yes)五行,并在下面至少写四行学到的内容。

参考

名称从三个分支开始

启动两个上游——8093 为 ok,8094 为 fail。在 /root/envd-stats/stats.yaml 中放置 stat_prefix 为 shop 的监听器以及集群 good、bad 并启动(管理端口 9971,监听器 127.0.0.1:10071)。请求五次 /hello、一次 /bad/x 之后,在 /root/envd-stats/01-names.txt 中写入 cluster=、http=、listener= 三行——分别是 cluster.good.upstream_rq_total、http.shop.downstream_rq_total,以及该监听器的 downstream_cx_total 统计的完整名称。

Envoy 的统计名称用前缀说明这个数字是关于什么的。cluster. 是上游一侧,http. 是该 HTTP 连接管理器所处理的请求一侧,listener. 是套接字一侧。同一个请求会在三个地方分别被统计,所以当三个数字对不上时,差异本身就是线索。监听器名称中包含地址和端口,有的位置会用下划线代替点,请自行确认。

从五百个中只取出需要的

给 /stats 加上 filter,只取出包含 upstream_rq_total 的统计,再同时加上 format=json,保存到 /root/envd-stats/02-filter.json。并在 /root/envd-stats/02-filter.txt 中写入 total_stats=(不加过滤器时得到的行数)和 matched=(经过过滤器缩小后的统计个数)两行。

统计在默认配置下也超过五百个。所以管理端口有查询参数——?filter= 是正则表达式,?format=json 则改成机器可读的形态。二者可以用 & 一起使用。在 shell 中 ? 和 & 是特殊字符,所以请把整个地址用引号括起来。JSON 一侧的个数用 jq '.stats | length' 统计。

同一个值以不同的名称输出

获取 /stats/prometheus,把对应 cluster.good.upstream_rq_total 的那一行保存到 /root/envd-stats/03-prom.txt。并在 /root/envd-stats/03-prom.map 中写入 envoy_name=(在 Prometheus 中的指标名称)、label_key=(包含集群名称的标签的键)、value=(其值)三行。

Prometheus 中没有“用点连接的长名称”这个概念,而是用指标名称和标签集合来表达。所以 Envoy 在导出时会拆分名称——cluster.good.upstream_rq_total 会被拆成一个指标名称,加上一个包含集群名称的标签。了解这条规则,才能把在 /stats 中看到的名称转换为仪表板查询。标签在大括号内,以 열쇠="값"(占位符依次为键与值)的形式出现。

重置按钮只对一半有效

POST /reset_counters 之后,重新读取两个统计,在 /root/envd-stats/04-reset.txt 中写入 counter_before=、counter_after=(cluster.good.upstream_rq_total)和 gauge_before=、gauge_after=(cluster.good.membership_total)四行。

统计有不同的种类。计数器是只会不断增加的累积值,gauge 是此刻的状态,直方图是值的分布。/reset_counters 正如其名,只会把计数器重置为 0——gauge 是“现在有几台健康的服务器”这样的当前状态,没有什么可重置的。不了解这个区别,就会卡在“重置了,值却没有变”上。POST 用 curl -X POST 发送。

亲自确定拆分名称的规则

创建 /root/envd-stats/stats-tags.yaml——与 stats.yaml 相同,但在最顶层放置 stats_config.stats_tags,用正则表达式 ^cluster\.((.+?)\.) 提取标签名称 envd_cluster。启动并请求两次 /hello 之后,把 /stats/prometheus 中带有 envd_cluster 标签的一行保存到 /root/envd-stats/05-tags.txt。

默认的标签规则 Envoy 已经内置了多条(集群名称、监听器地址等)。在此基础上再添加规则,就能把你所在组织的命名规则提取为标签——例如,如果在集群名称前加了团队名称作为前缀,就可以只把它单独做成标签,这样在仪表板上就能按团队汇总查看。正则表达式的第一个括号是要从名称中切掉的部分,第二个括号是标签的值。字段名称是 stats_tags(不是 stat_tags)。

选出不导出的内容

创建 /root/envd-stats/stats-trim.yaml——用 stats_config.stats_matcher.exclusion_list 排除前缀为 cluster.bad. 的统计。启动后,在 /root/envd-stats/06-trim.txt 中写入 before=(第 5 步配置中的全部统计行数)、after=(此配置中的行数)、bad_stats=(此配置中以 cluster.bad. 开头的行数)三行。

统计占用内存,而导出到 Prometheus 后,时间序列有多少,存储成本就有多少。在有几百个集群的代理中,这个数字很快就会变得难以承受。所以有一种选择导出内容的机制——用排除列表或包含列表来指定前缀、精确名称、正则表达式。需要注意的是,被排除的统计不是从界面上消失,而是根本不会被记录。需要了再恢复,这期间的值也不存在。

改一个单词,仪表板就会变空

创建 /root/envd-stats/stats-rename.yaml——在第 1 步的配置中只把 stat_prefix 从 shop 改为 checkout。启动并请求两次 /hello 之后,在 /root/envd-stats/07-rename.txt 中写入 old_prefix_stats=(以 http.shop. 开头的统计行数)、new_prefix_stats=(以 http.checkout. 开头的行数)、new_rq_total=(http.checkout.downstream_rq_total 的值)三行。

stat_prefix 是用于名称的值,对流量没有任何影响。所以在重构时很容易随手改掉,而那一刻,所有使用该前缀的仪表板和告警都会变成空图表。而且值不是掉到 0,而是时间序列本身消失了,对于不把“无数据”当作故障处理的告警,没有人会知道。名称就是接口——修改时必须先找出使用它的一方。

留下统计运维备忘

在 /root/envd-stats/08-report.md 中写入 counter_after_reset=、gauge_after_reset=(第 4 步)、prom_label=(第 5 步添加的标签名称)、trim_removed=(第 6 步的 before 减去 after 的值)、renamed_lost=(第 7 步中旧前缀的统计消失了则为 yes)五行,并在下面至少写四行学到的内容。

这份备忘是下次制作仪表板或重构代理配置时你自己要读的文字。尤其是最后一行,最好写成“名称就是接口”这条规则——值取自前面步骤创建的文件。