把数百行 proxy-config 输出当作表格来读
一句话总结
sidecar 的集群名称由 방향|포트|서브셋|호스트(占位符依次为方向、端口、子集、主机)四个字段按规则生成。DestinationRule 的一个子集对应一个集群,统计数据和错误信息全都带着这个名称出现。会读这个名称,proxy-config 输出的几百行就会变成一张表。
为什么需要它
第一次打开 istioctl proxy-config clusters <파드>(占位符为 Pod 名称)时,会看到这样的行无穷无尽地出现。
outbound|9080||reviews.default.svc.cluster.local
outbound|9080|v1|reviews.default.svc.cluster.local
outbound|9080|v2|reviews.default.svc.cluster.local
inbound|9080||
读不懂这些名称,就有两件事做不了。第一,在查看“发往 v2 的请求为什么是 503”时,无法确认 v2 子集的集群是否存在,以及有几个端点。第二,无法判断仪表板上像 cluster.outbound|9080|v2|…upstream_rq_503 这样的指标,是哪个服务的什么东西。Istio 必须在没有人工干预的情况下创建数千个集群,所以把名称定成了规则,而这条规则本身就是读取的方法。
工作原理
| 字段 | 值 | 为空的情况 |
|---|---|---|
| 方向 | outbound(该 Pod 调用别人时)/ inbound(别人调用该 Pod 时) |
无 |
| 端口 | 服务端口(9080) |
无 |
| 子集 | DestinationRule 的 subsets[].name |
没有选择子集的默认集群 |
| 主机 | 服务的 FQDN | 入站一侧(因为是发往自己的应用) |
istiod 会为网格中的每个服务和端口始终创建一个没有子集的集群,如果 DestinationRule 中有子集,就为每个子集再多创建一个。子集集群的端点,是从同一个服务的端点中筛选出标签匹配的部分集合。所以没有标签的 Pod 不会出现在任何一个子集集群中。
VirtualService 的 destination: {host: reviews, subset: v1} 会被转换为路由指向 outbound|9080|v1|reviews… 集群。这里就会出现常见的事故。如果指向了 DestinationRule 中没有的子集,istiod 就会下发指向一个不存在的集群的路由。Envoy 不会提前确认动态接收的路由所指向的集群(validate_clusters 默认值为 false),所以配置会被接受,请求到来时返回 503,访问日志中会打印 NC(no cluster)。用文件写的静态配置默认值为 true,会在启动时拒绝同样的配置——同样的错误,暴露的位置不同。
统计数据累积在 cluster.<이름>.<지표>(占位符依次为名称与指标)之下。带有 | 的名称在转换为 Prometheus 标签时比较麻烦,所以如果在网格配置的 outboundClusterStatName 中给出模式,istiod 就会为每个集群附加 alt_stat_name。路由仍使用原来的名称,只有统计名称发生变化。
在现场相遇的样子
设置了金丝雀,发往 v2 的请求全部是 503。这是先部署了 VirtualService,后部署 DestinationRule 的情况。在这几秒到几分钟里,v2 子集集群并不存在。先看 proxy-config clusters 中有没有 v2 这一行。所以顺序始终是先 DestinationRule,后 VirtualService。
子集集群的端点为 0 个。名称存在,但 proxy-config endpoints 为空,就是子集的标签与 Pod 标签对不上(version: v2 对 version: 2.0)。此时响应标记不是 NC,而是 UH(没有健康的上游),所以只看标记的两个字母,就能区分“集群不存在”和“集群存在但为空”。
仪表板突然变空了。如果有人更改了网格配置的 outboundClusterStatName,统计名称就会整体改变,用旧名称编写的查询会全部变空。路由完好无损,所以很久以后才会发现。
官方文档:Debugging Envoy and Istiod · DestinationRule
下一项实验要做什么
编写 DestinationRule,按规则推导出四个集群名称,再按这些名称原样搭建 Envoy,按子集拆分请求。把统计名称改为 alt_stat_name,指向不存在的子集来制造 503 和 no_cluster,然后通过 /clusters 统计子集是同一批端点的部分集合。