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

Kubernetes多Ingress指向同一服务时 Go服务如何获取请求源子域名

核心问题根因

整个异常链路来自两个叠加的配置/代码错误:

  • Ingress规则配置不符合API规范,导致host匹配逻辑完全失效。当所有域名规则都无法被控制器识别时,请求会落到Ingress的默认转发路径上,此时控制器会将Host头强制替换为上游Pod的IP+端口,最终表现为后端代码拿到的hostname是Pod IP
  • Go代码读取Host值的字段用错,没有正确获取客户端传递的原始Host头,进一步放大了识别失败的问题

分步调整方案

1. 修正Ingress配置的无效规则

K8s Ingress的spec.rules.host字段不允许携带协议前缀(http:///https://),必须填写纯主机名,否则规则完全不会生效。原配置中三个host值都添加了http://前缀,属于无效配置。
修正后的Ingress示例:

kind: Ingress
metadata:
  annotations:
    ingress.kubernetes.io/browser-xss-filter: 'true'
    ingress.kubernetes.io/force-hsts: 'true'
    ingress.kubernetes.io/hsts-include-subdomains: 'true'
    ingress.kubernetes.io/hsts-max-age: '315360000'
  name: test
  namespace: test
spec:
  rules:
    - host: x.test.com
      http:
        paths:
          - backend:
              serviceName: test-service
              servicePort: 8080
            path: /
    - host: y.test.com
      http:
        paths:
          - backend:
              serviceName: test-service
              servicePort: 8080
            path: /
    - host: z.test.com
      http:
        paths:
          - backend:
              serviceName: test-service
              servicePort: 8080
            path: /

注:以上配置修正后,主流Ingress控制器(如Nginx Ingress)默认会将客户端原始的Host头透传到后端服务,不会额外修改为Pod IP。


2. 修正Go代码的Host读取逻辑

原代码读取r.URL.Host是完全错误的:服务端接收的HTTP请求中,r.URL仅存储请求路径相关的信息,Host字段始终为空。客户端传递的原始Host头,Go标准库直接存在r.Host字段中。
同时需要补充处理Host携带端口的场景,基于当前固定的三个子域名场景,直接匹配已知Host值的可靠性远高于盲目拆分域名字符串。
修正后的代码示例:

import (
    "net/http"
    "strings"
)

// 预定义需要识别的域名与对应子域名映射
var knownSubdomains = map[string]string{
    "x.test.com": "x",
    "y.test.com": "y",
    "z.test.com": "z",
}

func GetSubdomain(r *http.Request) (subdomain string, ok bool) {
    // 读取客户端真实传递的Host头
    rawHost := strings.TrimSpace(r.Host)
    // 去掉Host中携带的端口部分
    hostWithoutPort := strings.Split(rawHost, ":")[0]
    
    // 优先匹配预定义的已知域名
    sub, exists := knownSubdomains[hostWithoutPort]
    if exists {
        return sub, true
    }
    // 保留通用*.test.com规则作为兜底
    hostParts := strings.Split(hostWithoutPort, ".")
    if len(hostParts) == 3 && hostParts[1] == "test" && hostParts[2] == "com" {
        return hostParts[0], true
    }
    return "", false
}

验证方法

调整完成后,可以通过带Host头的curl命令直接测试:

curl -H "Host: x.test.com" http://<Ingress访问地址>/

如果后端服务读取到的r.Host为x.test.com而非Pod IP,说明配置生效,即可正常识别对应子域名。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.23 09:15:08