Nginx Ingress无主机与指定主机规则冲突致404问题问询
核心逻辑误区
你之前的误解是关键:无host的Ingress规则并不等价于host: *(匹配所有主机),它的实际作用是:仅当请求的Host头不在任何Ingress规则的host列表中时,才会匹配Nginx的默认server块(server_name _)。
问题触发的具体机制
无host规则的配置生成:
你的api1Ingress未指定host,Nginx Ingress Controller会将/api1的location规则添加到默认server块(server_name _)中。此时,任何请求的Host未被其他Ingress规则匹配时(比如直接用IP访问、或者用未在Ingress中定义的域名访问),都会进入这个默认server,匹配/api1路径并转发到对应服务。指定host规则的配置生成:
当你添加api2Ingress(指定host: my-server.com)后,Controller会生成一个独立的server块,server_name为my-server.com。同时,这个server块会自动添加一个兜底的location /规则,该规则会匹配该host下所有未被更精确路径(比如/api2)匹配的请求,并且默认转发到upstream-default-backend(这是Ingress Controller内置的默认后端,专门处理无匹配路径的请求,返回404)。Nginx的匹配优先级:
Nginx的请求匹配逻辑是先匹配server_name,再在匹配到的server块内匹配location。当你访问my-server.com/api1时,请求的Host是my-server.com,会直接进入对应的server块,而该块内没有/api1的location规则,于是匹配兜底的location /,转发到默认后端返回404——完全不会去默认server块找/api1的规则,因为server匹配已经完成。IP访问正常的原因:
用IP1.2.3.4/api1访问时,请求的Host头是该IP,而这个IP没有被任何Ingress的host字段定义,所以会匹配默认server块,里面的/api1规则生效,正常转发到服务。
解决办法
针对这个场景,有几种规范的处理方式:
- 合并规则到同一host:将
/api1路径添加到my-server.com的Ingress规则中,或者创建一个新的针对my-server.com的Ingress包含/api1路径,确保该host的server块内有对应location规则。 - 使用通配符host覆盖:如果需要
/api1对所有主机生效(包括已定义的my-server.com),可以创建一个指定host: *的Ingress(注意K8s Ingress的通配符host需符合规范:只能是前缀或后缀通配,比如*.example.com,若要匹配所有主机,也可结合多个host条目)。 - 自定义server块配置:通过
nginx.ingress.kubernetes.io/server-snippet注解,在my-server.com的server块中添加规则,让未匹配的请求转发到默认server的对应路径,但这种方式相对复杂,不推荐作为常规方案。
内容的提问来源于stack exchange,提问作者azuse

