配置Kubernetes Gateway API指定Hostname时Istio TLS路由报错
通过Helm手动部署Istio网关,尝试配置Kubernetes Gateway API启用TLS时,在Gateway资源中设置hostname字段后,Istio日志出现错误:
2025-02-05T18:51:09.844430Z debug envoy conn_handler external/envoy/source/common/listener_manager/active_stream_listener_base.cc:45 closing connection from XXX.XXX.XXX.0:39292: no matching filter chain found thread=21
curl请求TLS握手失败,返回:
$ curl -kLvv -H "Host: httpbin.example.com" https://XXX.XXX.XXX.XXX:444/get?foo=bar * TCP_NODELAY set * Connected to XXX.XXX.XXX.XXX (XXX.XXX.XXX.XXX) port 444 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /etc/pki/tls/certs/ca-bundle.crt CApath: none * TLSv1.3 (OUT), TLS handshake, Client hello (1): * OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to XXX.XXX.XXX.XXX:444 * Closing connection 0 curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to XXX.XXX.XXX.XXX:444
添加--resolve httpbin.example.com:444:XXX.XXX.XXX.XXX也无法解决问题。查看Istio-ingress Pod的Envoy监听配置,可见filterChain中包含serverNames: ["httpbin.example.com"]的匹配规则,但移除Gateway的hostname字段后,filterChainMatch被移除,流量恢复正常。
使用的Istio版本为1.21.6,相关配置如下:
Gateway配置
--- apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway namespace: istio-ingress spec: gatewayClassName: istio listeners: - name: default port: 81 protocol: HTTP allowedRoutes: namespaces: from: All - name: default-tls hostname: "httpbin.example.com" port: 444 protocol: HTTPS tls: certificateRefs: - kind: Secret name: httpbin-example namespace: default allowedRoutes: namespaces: from: All addresses: - value: istio-ingress.istio-ingress.svc.cluster.local type: Hostname
ReferenceGrant配置
--- apiVersion: gateway.networking.k8s.io/v1beta1 kind: ReferenceGrant metadata: name: allow-istio-ingress-to-ref-secrets namespace: default spec: from: - group: gateway.networking.k8s.io kind: Gateway namespace: istio-ingress to: - group: "" kind: Secret
HTTPRoute配置
--- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: http namespace: default spec: parentRefs: - name: gateway namespace: istio-ingress hostnames: - httpbin.example.com rules: - matches: - path: type: PathPrefix value: /get backendRefs: - name: httpbin port: 8000
Envoy监听配置片段
{ "name": "0.0.0.0_443", "address": { "socketAddress": { "address": "0.0.0.0", "portValue": 443 } }, "filterChains": [ { "filterChainMatch": { "serverNames": [ "httpbin.example.com" ] }, "filters": [ { "name": "envoy.filters.network.http_connection_manager", "typedConfig": { "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", "statPrefix": "outbound_0.0.0.0_443", "rds": { "configSource": { "ads": {}, "initialFetchTimeout": "0s", "resourceApiVersion": "V3" }, "routeConfigName": "https.444.default.gateway-istio-autogenerated-k8s-gateway-default-tls.istio-ingress" }, "httpFilters": [ { "name": "istio.metadata_exchange", "typedConfig": { "@type": "type.googleapis.com/udpa.type.v1.TypedStruct", "typeUrl": "type.googleapis.com/io.istio.http.peer_metadata.Config", "value": { "upstream_discovery": [ { "istio_headers": {} }, { "workload_discovery": {} } ], "upstream_propagation": [ { "istio_headers": {} } ] } } }, ....
确保SNI正确传递:当Gateway listener指定
hostname时,Envoy要求TLS握手阶段客户端发送的SNI必须匹配该hostname。之前的curl命令直接访问IP并添加Host头,但SNI仍为IP,导致无法匹配filterChain。使用以下命令发起请求,确保SNI为目标域名:curl -kLvv --resolve httpbin.example.com:444:XXX.XXX.XXX.XXX https://httpbin.example.com:444/get?foo=bar验证TLS证书Secret:确认
default命名空间下的httpbin-exampleSecret包含httpbin.example.com域名的有效证书和私钥,密钥对需存储在tls.crt和tls.key字段中。可通过以下命令检查:kubectl get secret httpbin-example -n default -o yaml同时验证证书的SAN字段包含目标域名:
kubectl get secret httpbin-example -n default -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -text | grep DNS检查端口映射一致性:确认Istio-ingress Service的端口映射正确,将444端口转发到Pod的443端口:
kubectl get service istio-ingress -n istio-ingress确保输出中存在
444:443/TCP的映射规则。确认ReferenceGrant权限生效:检查Istio-ingress Pod日志,确认没有读取Secret的权限错误。虽然当前ReferenceGrant配置允许跨命名空间引用,但可重新应用配置确保生效:
kubectl apply -f reference-grant.yaml检查Istio特性开关:确认Istio的
GATEWAY_API特性开关已启用(Istio 1.21默认启用):istioctl feature list | grep GATEWAY_API若未启用,添加
--set features.gatewayAPI=true重新部署Istio网关。
内容的提问来源于stack exchange,提问作者Wanderer

