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

Istio VirtualService用子域名时网关失效,如何限定仅路由app.foo.com?

问题背景

在GKE环境中配置了GCP负载均衡Ingress、Istio Gateway和VirtualService,当将VirtualService的hosts字段从*替换为app.foo.com时,Istio网关无法正常路由请求到sample-app,需要调整配置让VirtualService仅对app.foo.com的请求生效。


现有配置

1. GCP负载均衡Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: "gcp-loadbalancer-ingress"
  namespace: "istio-ingress"
spec:
  rules:
    - host: "*.foo.com"
      http:
        paths:
          - path: "/"
            pathType: "Prefix"
            backend:
              service:
                name: "istio-ingressgateway"
                port:
                  number: 80

2. Istio Gateway

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: "gateway"
  namespace: "istio-ingress"
spec:
  selector:
    istio: "ingressgateway"
  servers:
  - port:
      number: 80
      name: "http"
      protocol: "HTTP"
    hosts:
    - "*"
    - "*.foo.com"

3. Istio VirtualService(当前生效版本)

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: "sample-app"
  namespace: "istio-ingress"
spec:
  hosts:
  - "*"
  # - "app.foo.com" 替换后失效
  gateways:
  - "gateway"
  http:
  - match:
      - uri:
          prefix: "/"
    route:
      - destination:
          host: "sample-app"

4. Istio IngressGateway Service(更新配置)

kind: Service
apiVersion: v1
metadata:
  name: "istio-ingressgateway"
  namespace: "istio-ingress"
  labels:
    app: "istio-ingressgateway"
    app.kubernetes.io/managed-by: "Helm"
    app.kubernetes.io/name: "istio-ingressgateway"
    app.kubernetes.io/version: "1.20.0"
    helm.sh/chart: "gateway-1.20.0"
    istio: "ingressgateway"
  annotations:
    cloud.google.com/neg: '{"ingress":true}'
    meta.helm.sh/release-name: "istio-ingressgateway"
    meta.helm.sh/release-namespace: "istio-ingress"
spec:
  ports:
  - name: "status-port"
    protocol: "TCP"
    port: 15021
    targetPort: 15021
    nodePort: 30276
  - name: "http-web"
    protocol: "TCP"
    port: 80
    targetPort: 80
    nodePort: 31849
  - name: "https-ssl"
    protocol: "TCP"
    port: 443
    targetPort: 443
    nodePort: 30824
  selector:
    app: "istio-ingressgateway"
    istio: "ingressgateway"
  clusterIP: {IP}
  clusterIPs:
  - {IP}
  type: "NodePort"
  sessionAffinity: "None"
  externalTrafficPolicy: "Cluster"
  ipFamilies:
  - "IPv4"
  ipFamilyPolicy: "SingleStack"
  internalTrafficPolicy: "Cluster"
status:
  loadBalancer: {}

问题根源

核心问题在于请求Host头的传递和Istio的匹配逻辑:

  • GCP Ingress转发请求时,如果没有正确保留原始Host头app.foo.com,Istio的VirtualService就无法匹配目标主机;
  • 当VirtualService的hosts设为app.foo.com时,只有Host头严格匹配该值的请求才会被路由,一旦Host头丢失或被篡改,路由直接失效。

修复步骤

1. 确认GCP Ingress保留Host头

GCP原生Ingress默认会保留原始Host头,无需额外配置。如果使用的是NGINX Ingress,需添加注解强制保留:

metadata:
  annotations:
    nginx.ingress.kubernetes.io/preserve-host: "true"

2. 修正VirtualService配置

将hosts设为app.foo.com,同时可添加Host头匹配规则强化精准性:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: "sample-app"
  namespace: "istio-ingress"
spec:
  hosts:
  - "app.foo.com"
  gateways:
  - "gateway"
  http:
  - match:
      - uri:
          prefix: "/"
        headers:
          host:
            exact: "app.foo.com"
    route:
      - destination:
          host: "sample-app"
          port:
            number: 80 # 明确服务端口,避免路由歧义

3. 简化Gateway配置(可选)

Gateway的hosts只需保留*.foo.com即可,无需范围过大的*:

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: "gateway"
  namespace: "istio-ingress"
spec:
  selector:
    istio: "ingressgateway"
  servers:
  - port:
      number: 80
      name: "http"
      protocol: "HTTP"
    hosts:
    - "*.foo.com"

4. 验证配置有效性

  • 应用修改后的配置:
kubectl apply -f <你的配置文件路径>
  • 检查Istio配置是否存在错误:
istioctl analyze
  • 发送测试请求验证路由:
curl -H "Host: app.foo.com" http://<你的GCP Ingress公网IP>

如果能返回sample-app的响应,说明配置生效。


内容的提问来源于stack exchange,提问作者CommonSenseCode

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 03:25:56