我设置了一个入口网关,一切都运行良好,并且可以通过 VirtualServices 将流量路由到服务。我还使用 jwt_authn_filter 设置了 EnvoyFilter,以对集群传入流量的某些路由执行一些身份验证。此 EnvoyFilter 还根据 JWT 中的声明之一向流量添加自定义标头:
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: jwt-auth-filter
namespace: istio-system
spec:
workloadSelector:
labels:
istio: ingress-gateway
configPatches:
- applyTo: HTTP_FILTER
match:
context: GATEWAY
listener:
portNumber: 443
filterChain:
filter:
name: envoy.filters.network.http_connection_manager
subFilter:
name: envoy.filters.http.router
patch:
operation: INSERT_FIRST
value:
name: envoy.filters.http.jwt_authn
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication
providers:
x:
...
claim_to_headers:
- header_name: x-custom
claim_name: custom
...
这一切都工作正常,我可以看到日志中添加了标头,并且我的服务被路由以接收此标头。但是,如果我尝试在虚拟服务中使用此标头,它不起作用,我会收到
404 NR route_not_found
错误。
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: vs1
namespace: ns1
spec:
gateways:
- istio-system/ingress-gateway
hosts:
- 'mydomain.com'
http:
- name: vs1
match:
- headers:
x-custom:
exact: value
route:
- destination:
host: s1.ns1.svc.cluster.local
port:
number: 80
似乎路由的标头是在上述过滤器运行之前确定的。这是正确的吗?如果是,是否有更好的替代方法?
VirtualService 本身工作正常,如果我在对入口网关的请求上手动设置该标头,它会正确路由,因此不会出现任何问题。
事实证明有一个未记录的选项
clear_route_cache
可以解决这个问题。