Istio基于EnvoyFilter实现正则回溯URL重写返回404问题
问题根因
配置返回404是三个核心错误导致的:
- EnvoyFilter作用对象选错:现有配置绑定的是标签为
app: sample的后端业务Pod Sidecar,但外部流量首先经过istio-ingressgateway网关,重写逻辑根本没在流量入口链路生效。 - VirtualService重写规则无效:Istio原生的
rewrite.uri不支持正则捕获组占位符,你配置的uri: /$2会被识别为固定字符串路径,后端收到字面量为/$2的请求必然返回404。 - 路由匹配规则错误:第一版EnvoyFilter匹配的是Sidecar入站路由(
inbound|http|80),和网关处理外部请求的路由完全不匹配;第二版虽然放开了context,但作用对象还是业务Sidecar,规则没有下发到网关。
正确配置方案
1. 修改VirtualService配置
删除无效的原生rewrite规则,仅保留路径匹配和后端路由逻辑:
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: sample-vs namespace: default spec: hosts: - "*.xyz.com" gateways: - sample-gateway http: - name: sample # 这个名字要和后续EnvoyFilter匹配的路由名一致 match: - uri: regex: ^/sample(/|$)(.*) # 加行首锚定,避免误匹配/othersample这类路径 route: - destination: host: sample port: number: 80
2. 编写正确的EnvoyFilter配置
EnvoyFilter必须部署在istio-ingressgateway所在的命名空间(默认是istio-system),直接作用于网关Pod,同时实现原Nginx的两个核心逻辑:访问/sample时301永久跳转到/sample/、路径前缀剥离重写:
apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: name: sample-rewrite-filter namespace: istio-system spec: workloadSelector: labels: istio: ingressgateway # 匹配默认Istio入口网关Pod configPatches: # 实现/sample到/sample/的永久重定向 - applyTo: HTTP_ROUTE match: context: GATEWAY routeConfiguration: vhost: # vhost名格式为{协议}.{端口}.{网关端口名}.{网关命名空间}.{网关名}:{匹配域名} name: "https.443.https.sample-gateway.default:*.xyz.com" route: name: sample # 和VirtualService里的http路由名一致,精准匹配目标路由 patch: operation: MERGE value: match: - path: exact: /sample redirect: path_redirect: /sample/ response_code: MOVED_PERMANENTLY # 实现正则路径重写,剥离/sample前缀 - applyTo: HTTP_ROUTE match: context: GATEWAY routeConfiguration: vhost: name: "https.443.https.sample-gateway.default:*.xyz.com" route: name: sample patch: operation: MERGE value: route: regex_rewrite: pattern: google_re2: max_program_size: 100 regex: "^/sample(/|$)(.*)$" substitution: "/\\2"
配置验证与注意事项
- 如果vhost名不匹配,可以执行
istioctl proxy-config routes <istio-ingressgateway的Pod名称> -n istio-system -o json查看网关实际加载的vhost名称,替换配置中对应的name字段即可。 - 如果需要同时支持80端口的重写逻辑,可以参照上述配置新增两个configPatch,匹配80端口对应的vhost(默认名称为
http.80.http.sample-gateway.default:*.xyz.com)即可。 - 配置下发后可以直接访问域名验证:访问
https://abc.xyz.com/sample会先301跳转到/sample/,最终请求转发到后端根路径;访问https://abc.xyz.com/sample/api/test会直接转发到后端的/api/test路径,和原Nginx行为完全一致。
内容的提问来源于stack exchange,提问作者Mani
相关产品推荐
相关产品推荐

