Istio跨命名空间Gateway/VirtualService路由异常:仅首个部署的应用可正常路由
从你的描述和配置来看,这个问题是Istio 1.11.x版本中跨命名空间Gateway的TLS配置合并bug导致的,具体分析和解决方式如下:
核心原因
你在foo和bar两个独立命名空间分别部署了Gateway,它们都指向同一个IngressGateway Pod(通过selector: istio: ingressgateway),并且在443端口使用了相同的credentialName: wildcard-tls配置TLS SIMPLE模式。在Istio 1.11.x版本中,控制平面处理这种场景时存在逻辑缺陷:当多个Gateway针对同一IngressGateway的相同端口配置相同的证书名称时,只有第一个部署的Gateway的hosts会被正确添加到Envoy的listener中,后续部署的Gateway的hosts会被忽略,导致对应域名的请求找不到匹配路由(也就是你日志里看到的route_not_found)。
你可以用以下命令验证这个问题:
# 替换成你的IngressGateway Pod名称,默认在istio-system命名空间 istioctl pc listeners istio-ingressgateway-xxxxxx-yyyyy -n istio-system
查看443端口的listener配置,会发现只有先部署的那个域名(比如foo.example.com或bar.example.com)出现在hosts列表里,另一个域名完全不在其中,这就解释了为什么后部署的应用无法正常路由。
解决方案
根据你的情况,有几种可行的解决方式:
1. 升级Istio到1.12+版本(推荐)
这个跨命名空间Gateway TLS配置合并的问题已经在Istio 1.12版本中被官方修复,升级到1.12或更高版本后,多个跨命名空间的Gateway可以正常共享同一端口和证书,各自的hosts都会被正确加载到Envoy listener中。
2. 合并Gateway到同一命名空间(临时Workaround)
如果暂时无法升级,可以将两个应用的Gateway配置合并成一个,放在同一个命名空间(比如istio-system或者专门的网关管理命名空间):
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: shared-gateway namespace: istio-system spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - foo.example.com - bar.example.com tls: httpsRedirect: true - port: number: 443 name: https protocol: HTTPS tls: mode: SIMPLE credentialName: wildcard-tls hosts: - foo.example.com - bar.example.com
然后修改两个VirtualService的gateways字段,跨命名空间引用这个共享Gateway:
- Foo应用VirtualService:
gateways: - istio-system/shared-gateway - Bar应用VirtualService:
gateways: - istio-system/shared-gateway
注意:确保wildcard-tls Secret存在于istio-system命名空间中,或者在对应命名空间创建相同的Secret。
3. 为每个Gateway使用不同的证书名称(另一种Workaround)
即使两个应用使用的是同一个通配符证书,你可以在foo和bar命名空间分别创建相同的Secret,但使用不同的名称(比如foo-wildcard-tls和bar-wildcard-tls),然后修改各自Gateway的credentialName:
- Foo Gateway:
credentialName: foo-wildcard-tls - Bar Gateway:
credentialName: bar-wildcard-tls
这样Istio会认为是两个独立的TLS配置,不会出现覆盖问题,两个Gateway的hosts都会被正确加载。
内容的提问来源于stack exchange,提问作者dywan666

