ztunnel 只看到 L4
一句话总结
Ambient 模式取消 sidecar,把工作拆分给每个节点一个的 ztunnel(L4:mTLS、身份、连接级策略)和只在需要之处部署的 waypoint(L7:HTTP 路由、HTTP 策略)。如果不清楚谁在强制执行什么就去写策略,写好的规则会悄悄丢失,或者原本正常的流量会中断。
为什么需要它
Sidecar 模式给每个 Pod 配一个 Envoy。有一千个 Pod 就有一千个 Envoy,每个都要占用内存和 CPU,而且要更换 sidecar 就得重新创建 Pod。再说,大多数服务真正想要的只有 mTLS 和基于身份的 L4 策略,却要人人都背上解析 HTTP 的沉重代理。
Ambient 把这两层拆开了。mTLS 和 L4 由节点上的 ztunnel 负责,只有需要 HTTP 的服务才部署 waypoint(Envoy)。给命名空间打上一个标签(istio.io/dataplane-mode=ambient),istio-cni 就会在 Pod 的网络命名空间内部植入拦截规则,把流量送往 ztunnel。不需要重新创建 Pod。
工作原理
ztunnel——L4。从 Pod 发出的连接由该节点上的 ztunnel 接收,并与目的地节点的 ztunnel 建立 HBONE 隧道(HTTP CONNECT 之上的 mTLS,端口 15008)。ztunnel 不知道请求路径或方法,但知道双方的 SPIFFE 身份,并在访问日志中以 src.identity、dst.identity 记录下来。用选择器附加的 AuthorizationPolicy 由目的地一侧的 ztunnel 在接收连接时强制执行,所以拒绝表现为连接被断开,而不是 HTTP 403。
如果把 HTTP 规则写进选择器策略——istiod 会去掉 ztunnel 无法强制执行的规则(方法、路径等)后再下发,并以 ZtunnelAccepted 条件把这一事实写进策略状态。ALLOW 策略只要有一条匹配就放行,所以如果其他 ALLOW 策略已经放行了该来源,那么写下的“只允许 GET”就什么作用都没有。
waypoint——L7。istioctl waypoint apply 会创建 Gateway API 的 Gateway(gatewayClassName istio-waypoint),--enroll-namespace 会给命名空间加上 istio.io/use-waypoint 标签,让这些服务使用 waypoint。此后发往服务的请求的路径是这样的。
client ─(ztunnel)─ HBONE ─▶ waypoint(Envoy: HTTP 라우팅·HTTP 정책) ─ HBONE ─▶ (ztunnel) web
这里有两处改变。
| waypoint 之前 | waypoint 之后 | |
|---|---|---|
| web 的 ztunnel 看到的来源 | client | waypoint |
| 强制执行 HTTP 规则的位置 | 无 | waypoint(用 targetRefs 附加的策略) |
所以只允许 client 的 L4 策略,在附加 waypoint 的瞬间就会切断服务流量。而且 waypoint 默认只负责发往服务的请求(istio.io/waypoint-for: service),所以直接发往 Pod IP 的请求不会经过 waypoint——这是绕过 L7 策略的路径。在 L4 策略中只允许 waypoint 的身份,这两个问题就一并解决了。
路由也由 waypoint 负责。网格内部的路由用父资源为服务的 HTTPRoute 来写(Gateway API 的 GAMMA)。处理它的是 waypoint,所以没有 waypoint 就不会生效。
在现场相遇的样子
“加了 waypoint 之后,服务全部返回 503”——这是目的地的 L4 策略原本只允许客户端的情况。waypoint 日志中会记录 tunnel_response:401。引入 waypoint 要同时审查策略。
“只允许了 GET,POST 却能通过”——把 HTTP 规则写进了选择器策略。kubectl get authorizationpolicy -o yaml 的 status 里已经说明了这一点。
“设置了 L7 策略,有些调用却仍然通过”——是直接用 Pod IP 访问的客户端(headless Service、StatefulSet 等)没有经过 waypoint 的情况。
官方文档:Ambient mode overview、Platform prerequisites — K3s、Configure waypoint proxies、Layer 4 security policy、Layer 7 features
下一项实验要做什么
在 k3s 上以 ambient profile 安装的真实 ztunnel 上,用一个标签把命名空间纳入进来,查看不重启就被纳入,以及 ztunnel 留下的两个身份。设置 L4 策略后,通过策略状态确认没有 waypoint 时 HTTP 规则是怎样被去掉的,然后附加 waypoint,亲身体验原本正常的请求变成 503,并加以修复。最后在 waypoint 上设置 HTTP 策略和 HTTPRoute。