Istio SNI透传示例未按预期工作,请求排查帮助
我按照Istio的SNI透传Ingress示例配置后,请求一直返回404错误,相关环境和日志信息如下:
环境详情
- Kubernetes版本:1.15.8
- Istio版本:
❯ istioctl version client version: 1.4.0 control plane version: 1.4.0 data plane version: 1.4.0 (5 proxies)
错误日志片段
2020-01-29T17:21:12.551246Z info accesslog.instance.istio-system {"apiClaims": "", "apiKey": "", "clientTraceId": "", "connection_security_policy": "unknown", "destinationApp": "", "destinationIp": "0.0.0.0", "destinationName": "unknown", "destinationNamespace": "default", "destinationOwner": "unknown", "destinationPrincipal": "", "destinationServiceHost": "nginx.foo.bar.us", "destinationWorkload": "unknown", "grpcMessage": "", "grpcStatus": "", "httpAuthority": "nginx.foo.bar.us", "latency": "146.827µs", "method": "GET", "permissiveResponseCode": "none", "permissiveResponsePolicyID": "none", "protocol": "http", "receivedBytes": 243, "referer": "", "reporter": "source", "requestId": "dd1b7b2b-10b1-9c36-ae64-cce9825773d2", "requestSize": 0, "requestedServerName": "", "responseCode": 404, "responseFlags": "NR", "responseSize": 0, "responseTimestamp": "2020-01-29T17:21:12.551334Z", "sentBytes": 60, "sourceApp": "istio-ingressgateway", "sourceIp": "100.108.31.87", "sourceName": "istio-ingressgateway-5b794cc7c9-82z4h", "sourceNamespace": "istio-system", "sourceOwner": "kubernetes://apis/apps/v1/namespaces/istio-system/deployments/istio-ingressgateway", "sourcePrincipal": "", "sourceWorkload": "istio-ingressgateway", "url": "/", "userAgent": "curl/7.64.1", "xForwardedFor": "192. 168.0.1,172.31.0.156"}
问题分析与修复方案
从日志里能看到几个关键线索:responseFlags: "NR"(表示Ingress网关找不到匹配的路由)、requestedServerName为空(请求没携带SNI信息)、connection_security_policy: "unknown"(请求可能不是HTTPS)。我帮你梳理几个排查步骤:
1. 确认IngressGateway的TLS透传配置是否正确
SNI透传要求Gateway监听443端口,并且设置为PASSTHROUGH模式。检查你的Gateway资源:
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: my-gateway namespace: istio-system spec: selector: istio: ingressgateway servers: - port: number: 443 name: https protocol: HTTPS tls: mode: PASSTHROUGH hosts: - "nginx.foo.bar.us"
重点确认mode: PASSTHROUGH,端口和协议是443/HTTPS,hosts和你的目标域名一致。
2. 检查VirtualService是否正确关联后端
VirtualService需要精准匹配Gateway的host,并且通过SNI指向后端服务:
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: nginx-vs namespace: default spec: hosts: - "nginx.foo.bar.us" gateways: - istio-system/my-gateway # 注意带上Gateway所在的命名空间 tls: - match: - port: 443 sniHosts: - "nginx.foo.bar.us" route: - destination: host: nginx.default.svc.cluster.local # 后端服务的完整FQDN port: number: 443 # 后端服务的TLS端口
这里要注意:
sniHosts必须和请求的SNI名称完全一致- 后端服务必须实际监听443端口(配置了TLS证书)
- VirtualService的
gateways字段要明确指定Gateway的命名空间(如果不在同一namespace)
3. 确保请求携带SNI信息
日志里requestedServerName为空,说明你的测试请求没发送SNI。用curl测试时要确保用HTTPS协议,并且域名解析正确:
# 如果域名还没绑定Ingress网关IP,用--resolve指定映射 curl -v https://nginx.foo.bar.us --resolve nginx.foo.bar.us:443:<你的IngressGateway外部IP>
或者先在本地hosts文件里添加域名到网关IP的映射,再执行curl -v https://nginx.foo.bar.us。没有SNI信息,Istio根本没法匹配到对应的路由,自然返回404。
4. 验证Istio路由是否生成
用istioctl查看Ingress网关的路由配置,确认有没有匹配目标域名的TLS路由:
istioctl proxy-config routes istio-ingressgateway-5b794cc7c9-82z4h.istio-system
如果看不到对应nginx.foo.bar.us的路由,说明Gateway或VirtualService配置有误,需要重新检查字段是否正确(比如拼写错误、命名空间不匹配)。
5. 检查后端服务的TLS可用性
因为是SNI透传,请求会直接转发到后端服务的TLS端口,所以后端服务必须已经配置好有效的TLS证书,并且正常监听443端口。可以直接在集群内部测试后端服务的TLS连通性:
# 在集群内的Pod里执行 curl -v https://nginx.default.svc.cluster.local
如果这里也失败,那需要先修复后端服务的TLS配置。
总结
你的核心问题是Ingress网关找不到匹配的路由(NR),根源大概率是请求没携带SNI,或者Gateway/VirtualService的透传配置不符合要求。先从请求方式和基础配置入手排查,应该能解决问题。
内容的提问来源于stack exchange,提问作者ajit

