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

Istio 实测实验室

只要立了网关就算拦住了吗

在 TT Lab 中继续学习

一句话总结

网格中出站流量的默认值是去哪儿都放行(ALLOW_ANY)。收紧它的手段有四个——缩小代理所知范围的 Sidecar 资源、拦下未知目的地的 REGISTRY_ONLY、把外部目的地登记到服务注册表的 ServiceEntry,以及把出站路径汇聚到一处的出口网关(egress gateway)。四者拦截的对象各不相同,没有哪一个能单独拦住全部。

为什么需要它

sidecar 默认知道集群中的所有服务。服务有几千个时,每个代理都要持有几千个集群,每当有一个服务变化,istiod 就要把它推送给所有代理。而且注册表中没有的目的地(外部地址、Pod IP)会被 PassthroughCluster 直接放走——网格并不知道谁在往哪里出站。

安全要求的方向则相反。比如“只有支付服务能访问信用卡公司的 API”“出站路径只有一处可供审计”。网格要想帮上忙,首先要按名称认识外部目的地,然后把出站的节点汇聚到一处。

工作原理

Sidecar 资源——规定这个命名空间的代理知道什么。

egress:
  - hosts: ["./*", "istio-system/*"]   ← 같은 네임스페이스와 istio-system 만 안다
outboundTrafficPolicy:
  mode: REGISTRY_ONLY                  ← 모르는 곳은 BlackHoleCluster(502)

缩小范围后,代理配置会变小,再加上 REGISTRY_ONLY,范围之外的就被拦下。被拦下的请求会在访问日志中留下路由名称 block_all,状态码为 502。

ServiceEntry——把外部目的地登记到注册表。location: MESH_EXTERNAL 表示“在网格之外,不要加 mTLS”,resolution: DNS 表示用 DNS 解析端点名称。不过主机名本身(api.partner.test)在集群 DNS 中并不存在。开启 sidecar 的 DNS 代理(ISTIO_META_DNS_CAPTURE)后,sidecar 会为该名称自动分配 240.240.0.0/16 网段的虚拟 IP 来应答,这个值也会写入 ServiceEntry 的 status.addresses。

出口网关——把出站路径汇聚到一处。一个 VirtualService 负责两个区段。

区段 匹配 发往
sidecar → 网关 gateways: [mesh] istio-egressgateway(mTLS)
网关 → 外部 gateways: [partner-egress] 真正的目的地

从 sidecar 到网关的 mTLS 不会自动建立。要把 Gateway 服务器设为 HTTPS、tls.mode: ISTIO_MUTUAL,并在 sidecar 前往网关时使用的 DestinationRule 子集中指定 ISTIO_MUTUAL 和 sni(官方文档 Egress Gateways with TLS Origination 使用同样的组合)。该 DestinationRule 按客户端命名空间 → 服务命名空间 → 根命名空间的顺序查找,所以要让多个命名空间共用同一个网关,就把它放在网关一侧(istio-system)。这样通过 mTLS 连起来后,网关就知道发出请求的工作负载的身份。因此在网关上设置授权策略,就能在一处决定“谁可以出站到这个外部目的地”。

拦不住的情况。Sidecar 和 REGISTRY_ONLY 只是该命名空间代理的配置。其他命名空间的代理仍然是 ALLOW_ANY,没有 sidecar 的 Pod 则根本不知道这些配置。Istio 文档指出,仅靠出口网关无法强制所有外部流量都经过它,必须用 Kubernetes 网络策略之类的其他手段堵住网关之外的路径。

在现场相遇的样子

“开启 REGISTRY_ONLY 后,指标采集中断了”——Pod 原本访问的外部地址(监控 SaaS、云元数据等)没有登记在注册表中。正确的顺序是:开启之前,先在访问日志中统计经 PassthroughCluster 出站的请求,并用 ServiceEntry 登记好。

“建了出口网关,合作方防火墙日志里记录的却是 Pod IP”——VirtualService 缺少 mesh 一侧的规则,或者主机不一致,导致 sidecar 没有经过网关而是直接出站。接收方看到的来源是最诚实的证据。

“网关上拦了,有的团队却仍然能出去”——该团队的命名空间没有 Sidecar 配置,或者是没有 sidecar 的 Pod。网关只能拦住经过它的请求。

官方文档:Accessing External Services、Egress Gateways、Sidecar、DNS Proxying

下一项实验要做什么

在网格之外放一个扮演合作方 API 的 nginx,先统计默认值下去哪儿都能出站的情况。用 Sidecar 缩小范围,用 REGISTRY_ONLY 拦截,再用 ServiceEntry 只登记合作方,然后用出口网关汇聚路径,并以合作方看到的来源来确认。最后看到在其他命名空间中仍然存在绕过网关的路径,再用网关的授权策略缩小可以出站的身份。