You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

配置Kubernetes Gateway API指定Hostname时Istio TLS路由报错

问题:Istio Gateway配置hostname后无法匹配FilterChain导致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-example Secret包含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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 12:48:10