我编写了一个虚拟服务来测试基于标头的路由
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: http-app
namespace: default
spec:
hosts:
- http-app.default.svc.cluster.local
http:
- match:
- headers:
canary-token:
exact: haha
route:
- destination:
host: http-app.default.svc.cluster.local
subset: canary
- route:
- destination:
host: http-app.default.svc.cluster.local
subset: stable
服务正常时流量路由正确
apiVersion: v1
kind: Service
metadata:
name: http-app
namespace: default
labels:
env: prod
spec:
type: ClusterIP
selector:
app: http-app
ports:
- port: 3011
targetPort: 3011
[2023-08-28T04:00:01.156Z] "GET /mesh HTTP/1.1" 200 - via_upstream - "-" 0 78 645 644 "192.168.65.4, 127.0.0.6" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.54" "24cb1d39-33f6-4e07-8ba5-fefc4c656498" "nginx-app.local" "10.1.13.85:3011" outbound|3011|canary|http-app.default.svc.cluster.local 10.1.13.93:44452 10.104.186.154:3011 127.0.0.6:0 - -
但是当我像这样显式地将协议设置为http时
ports:
- port: 3011
targetPort: 3011
appProtocol: http
或者这个
ports:
- name: http-app
port: 3011
targetPort: 3011
流量路由将是allow_any
[2023-08-28T11:23:10.344Z] "GET /mesh HTTP/1.1" 200 - via_upstream - "-" 0 78 652 652 "192.168.113.118,192.168.65.4, 127.0.0.6" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.54" "f54af48b-6f67-4f64-ba05-2d5d9215fd8c" "nginx-app.local" "10.104.186.154:3011" PassthroughCluster 10.1.13.93:38016 10.104.186.154:3011 127.0.0.6:0 - allow_any
为什么显式设置协议后,基于标头的路由不起作用?
ports:
- port: 3011
appProtocol: http
or
- name: http-app
注意:当您配置 name 或 appProtocol 时,Istio 会将该端口上的流量视为纯 HTTP。这意味着 Istio 不会出于路由目的检查或操作 HTTP 标头,包括 canary-token 标头。这意味着 VirtualService 中定义的基于标头的路由规则将不会被应用,并且流量将被允许自由流向指定端口,而不考虑 canary-token 标头。
解决方案:
ports:
- port: 3011
targetPort: 3011
如果您希望 Istio 根据 canary-token 标头执行基于标头的路由,则不应显式将协议设置为 http 或将端口命名为 http-app。默认情况下,Istio 执行 L7 路由,检查 HTTP 标头和其他应用程序层属性来做出路由决策。
因此,要启用基于标头的路由,您应该使用服务端口的原始配置,而不指定 appProtocol 或使用名称 http-app。这样,Istio 将继续检查 HTTP 标头并应用您在 VirtualService 中定义的路由规则。