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

Istio 服务网格

把代理从 Pod 里拿出来,得到什么又要拆分什么

在 TT Lab 中继续学习

一句话总结

Ambient 是把原本每个 Pod 都有的代理移到节点的 L4 代理上,只把需要查看请求内容的功能交给名为 waypoint 的独立 L7 代理的设计——所以迁移不是从一行标签开始,而是从功能清单开始。

为什么需要另一种数据平面

边车模型的代价有三项。第一,每个 Pod 都要多出一个容器。2000 个 Pod 就是 2000 个代理,并预留相应的请求资源。第二,要加入、移除或升级代理版本,就必须重启 Pod。接入网格变成了一次部署事件,所以引入本身就被绑定在各团队的部署计划上。第三,代理与应用位于同一个 Pod 中,启动顺序、终止顺序、资源争用之类的问题也随之而来。

Ambient 一次性避开了这三项。它在每个节点上部署两样东西——从 Pod 中拦截流量的组件,以及把拦截到的流量通过双向认证的隧道送出去的 L4 代理。Pod 保持不动,只需一行命名空间标签就能加入或退出网格。不需要重启。

分为两层的功能

这里有一点必须准确理解。节点上的 L4 代理不查看请求的内容,所以哪些能做、哪些不能做,界限分明。

功能 仅靠 L4 代理 需要 waypoint
工作负载之间的双向认证与加密 可以 —
按调用方身份允许或拒绝(L4) 可以 —
按端口、身份的策略 可以 —
基于 HTTP 路径、请求头的路由 不行 需要
按方法、路径粒度的授权 不行 需要
重试、超时、流量拆分 不行 需要

waypoint 不是 Istio 专用的对象,而是表示为 Gateway API 的 Gateway。网关类为 istio-waypoint 的那个 Gateway 就成为 waypoint,其监听器直接接收 Ambient 在 Pod 之间使用的隧道协议。这个 waypoint 是为什么而设,由标签 istio.io/waypoint-for 说明——是放在服务前面、放在工作负载前面、两者都放,还是都不放。

如何切换

陷阱在于有两个标签。边车使用注入 Webhook 所看的标签,Ambient 使用节点组件所看的标签。两者互不知情。 所以即使在命名空间上同时打了两个标签,也不会报错,该命名空间的 Pod 用哪种数据平面就处于未确定的状态。istioctl analyze 会用 IST0123 捕捉这种情况——这就是为什么要把这条命令放进切换工作的检查项中。

顺序是这样安排的。首先写下该命名空间实际使用的网格功能。只要有一项 L7 功能,就先建立 waypoint。然后去掉边车标签,打上 Ambient 标签。回退则按相反的顺序。切换期间,两种模式会在一个集群中共存,所以最好制作一个脚本,统计哪个命名空间处于哪种模式,这比靠人来记忆更可靠。

在现场相遇的样子

最常见的事故是“迁到 Ambient 之后,基于请求头的路由不生效了”。规则还在,也没有报错。只是强制执行这条规则的 L7 代理不在那个位置上。不了解这两层就迁移,一定会碰到。

这个事故之所以特别讨厌,是因为它悄无声息。L4 层照常工作,所以连接可以建立,双向认证也会生效。断掉的只是按请求内容分流的路径,表面上看网格运转良好,只是本该去往特定版本的流量走到了别处。日志里也不会留下错误。所以切换计划中一定要包含“该命名空间使用的网格对象清单”,其中只要有一个要求 L7,就要先建立 waypoint,然后再改标签。

第二种是没有去掉标签,而是另外加了标签的情况。如果边车标签还在,新启动的 Pod 仍然会被注入代理。界面上看起来切换已经完成,实际上只迁移了一半,而且这种状态每次部署时都会稍有不同。

本实验环境的局限

在这个环境中,无法真正启动 ztunnel 和 waypoint。 因此,流量通过隧道的场景,或者 L4 授权真正被强制执行的场景,都看不到。另外,这个集群没有 Gateway API 的 CRD,所以 waypoint 清单可以生成,却无法应用。 这个事实不加掩饰,在实验中亲自确认——因为应用失败的报错句子,最清楚地说明了 waypoint 建立在什么之上。不过,profile 渲染、标签及其冲突判定、waypoint 清单的字段,都可以用真正的工具和真正的 API 服务器确认。

下一项实验要做什么

渲染 Ambient profile,与边车 profile 比较组件和身份,看网格配置中多开启了什么。用命名空间标签制造两种模式,确认把两者叠加时分析器会抓到什么,然后生成 waypoint 清单,阅读其字段,并看应用为什么会失败。最后制作一张按模式统计集群中命名空间的检查清单。