NR(没有匹配的路由)--Istio访问日志ResponseFlag重现与解析08
KubeCon 2023在上海做的一个关于Istio访问日志的演讲《Detailed Parse and Reproduce Response Flags of Istio Access Log Based on Production Use Case》。解析和重现了在当时解决客户问题时碰到的各种应答日志。
第八个关注的Response Flag是NR,全称是NoRouteFound,官方定义表示No route configured for a given request in addition to 404 response code or no matching filter chain for a downstream connection.
含义:
NR表示没有匹配的路由来处理请求的流量,一般伴随“404”状态码。比如实际的访问流量的特征不匹配VirtualService中定义的路由条件,因而没有找到匹配的路由处理请求,就会报404 NR。
重现环境:
- 客户端Pod,注入了Sidecar。
- 目标服务,一个Cluster类型的Kubernetes服务,多个服务实例。服务端Pod可以注入Siecar,也可以不用注入。
重现步骤:
第一步: 从注入了网格代理的客户端Pod中通过目标名和服务端口访问目标服务,观察代理的访问日志,得到正常的200响应码。从服务端和客户端的访问日志上都可以看到服务在目标服务的多个实例上负载均衡。正常访问参照本系列的环境部分描述。
**第二步:**修改目标服务的VirtualService,在路由上添加一个HTTP 头域匹配条件,即只有满足条件的请求会发送到路由定义的后端上。
1apiVersion: networking.istio.io/v1beta1
2kind: VirtualService
3metadata:
4 name: nginx-80
5 namespace: accesslog
6spec:
7 hosts:
8 - nginx
9 http:
10 - match:
11 - headers:
12 log-flag:
13 exact: enable
14 route:
15 - destination:
16 host: nginx.accesslog.svc.cluster.local
17 subset: v1
第三步: .在客户端容器中还是使用原有方式访问目标服务,可以看到得到了一个404错误,表示请求的资源不存在。
**第四步:**在客户端的访问日志会记录404 NR的应答标记,表示没有找到匹配的路由
1[2023-08-19T11:13:06.484Z] "GET / HTTP/1.1" 404 NR route_not_found - "-" 0 0 0 - "-" "curl/7.52.1" "d9e4d779-ee2f-4dab-8546-46d61e789d35" "nginx.accesslog" "-" - - 10.246.91.131:80 10.66.0.24:35016 - -
第五步: 观察服务端日志。客户端代理没有找到匹配的路由把流量发到对应的服务端实例,因此服务端没有流量,也没有日志输出。
第六步: Configdump对应的路由会看到要求满足头域的匹配条件的请求才会转发,而curl请求中没有携带头域,没有匹配到定义的路由,因此报404。
1"routes": [
2 {
3 "match": {
4 "headers": [
5 {
6 "name": "log-flag",
7 "string_match": {
8 "exact": "enable"
9 }
10 }
11 ]
12 },
13 "route": {
14 "cluster": "outbound|80|v1|nginx.accesslog.svc.cluster.local“
15}
应对建议
和NC类似NR这类配置错误比运行期错误要好处理一些。客户端的流量满足路由中定义的流量特征,保证所有请求都有服务端定义的路由处理。
额外解析
有个困扰初学者的问题:按照对HTTP语义的理解,没有后端资源的,类似HTTP的“No page found”,应该返回“404”状态码,但为什么在前面NC的例子里返回了“503”状态码,在NR中却返回了“404”状态码?
我们把VirtualService这个虚拟服务想象成一个实际的Web服务端资源提供者或者我们写的一个Rest服务,将满足条件的请求通过其上定义的路由分发到后端服务,访问到了虚拟服务定义的网络资源。当没有匹配的路由,就是找不到服务里的资源,则返回“404”状态码;而在上一个NC场景中,若有匹配的路由定义,但是没有处理这个路由的后端,则属于HTTP服务端资源提供者内部的错误,所以返回“503”。