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

Envoy 内部结构

503 是集群在说话,不是路由

在 TT Lab 中继续学习

一句话总结

路由只说到集群名称为止。这个名称背后有几个地址、如何获知这些地址、其中哪些是健康的、健康的不够时怎么办,全部由集群决定。

为什么需要它

“路由是对的,却返回 503”这类报告并不是路由问题,而是说明路由所指向的集群里没有可以发送请求的地方。所以运维代理时,实际上最常看的不是路由表,而是集群列表——哪个集群有几台服务器,其中几台是健康的。

这里要区分两件事。获知端点的方式与判断其中哪些是健康的方式是两条不同的轴线。前者是集群的 type,后者是健康检查。把两者混在一起,就会在“已经从 DNS 里去掉了,为什么还在往那里发”这类问题上迷路。

工作原理

获知端点的四种方式。

type 方式 适用场景
STATIC 把地址原样写在配置中 地址固定时
STRICT_DNS 定期解析名称,把响应中的地址全部作为端点 像无头 Service 那样会返回多个地址时
LOGICAL_DNS 只抓住解析结果中的一个继续使用 需要长期保持连接的大型对端(例如外部 API)
EDS 由控制平面推送列表 服务网格。每当 Pod 启动或消失就更新

判断是否健康的两种方式。这两者的方向相反。

二者并不互斥。同时使用时,就成为“先用探测提前筛掉,漏网的再用结果筛掉”。/clusters 的 health_flags 中会分别显示不同的标记——主动检查失败显示为 /failed_active_hc。

健康的端点不够时。Envoy 有两种机制。

一种是 panic 模式。当健康比例降到阈值(默认 50%)以下时,会忽略健康信息,把请求发给所有端点。乍看很奇怪,但判断很简单——检查方也有可能出错,如果哪里都不发,就一定是故障;如果发,至少还有一部分能活下来。是否发生过,通过 cluster.<이름>.lb_healthy_panic(占位符为集群名称)统计来看。如果这个数字在上升,负载均衡实际上已经失去意义。

另一种是优先级。给每个端点分组设置 priority 后,平时只使用优先级 0,优先级 0 的健康比例下降多少,就由优先级 1 承接多少。优先级 0 全部失效时,一切都转到优先级 1。让其他区域的备用服务器平时闲置、只在故障时使用,就是这样构成的。

在现场相遇的样子

“已经从 DNS 里去掉了,却还是发到那台服务器。” STRICT_DNS 会定期重新解析,但在这个周期过去之前,仍然使用旧列表。如果是 LOGICAL_DNS,可能会抓得更久。安排操作顺序时,必须以“删除和生效之间存在时间差”为前提。

“打开健康检查后,后端 CPU 升高了。”二十台代理每秒探测一次,对服务器来说就是每秒二十次额外请求。要把周期和代理数量放在一起计算,并把健康检查路径做得轻量(使用不访问数据库的路径)。

误解 panic 模式的情况。会有人问“都死光了,为什么还一直在发”。看一下统计数据,答案就在里面。此时该修的不是 Envoy,而是健康检查的阈值或后端。

官方文档:Service discovery · Health checking · Cluster configuration

下一项实验要做什么

创建一个包含三个端点的集群,再添加一个按名称查找的集群,观察主动健康检查把故障的那一个剔除。然后分别用全部故障的集群确认 panic 模式,用设置了优先级的集群确认备用层级的接管,最后从统计数据中提取四个集群的清单表。