AlinsRan commented on issue #2782:
URL:
https://github.com/apache/apisix-ingress-controller/issues/2782#issuecomment-4665840885
### #2703 is not backward compatible
Before #2703 (i.e. 2.0.x), routes carried no `server_port` var, so requests
on any listening port matched. #2703 first shipped in 2.1.0 and, with the
default `listener_port_match_mode: auto`, injects a `server_port` var into
every route that matches multiple listener ports — with **no config change** on
the user's side. The "current behavior maintained" claim only refers to
compatibility with the unreleased PR, not with the last release 2.0.x. For
upgrading users this is a silent breaking change.
**Why it gets injected here (even without `sectionName`/`port`):** the
default mode `auto` injects when a route explicitly targets a listener **or**
when it matches multiple listener ports:
```go
case config.ListenerPortMatchModeAuto:
return explicit || len(ports) > 1
```
The HTTPRoute in this report has no `sectionName`/`port` and hostname
`git.example.com`, which matches **both** listeners — `http` (80, no hostname →
matches any) and `https` (443, `*.example.com` → matches `git.example.com`). So
`listenerPorts = {80, 443}`, `len(ports) > 1` is true, and `server_port in
["80","443"]` is injected.
**Why it then 404s:** the injected values `80`/`443` are the Gateway's
**logical** listener ports, but the nginx/APISIX `$server_port` variable
reflects the port **APISIX actually listens on**. In the standard Helm deploy
APISIX listens internally on `9080`/`9443` (the Service/LoadBalancer maps
external 80/443 → 9080/9443), so `$server_port` is `9080`/`9443` at request
time and never matches `in ["80","443"]` → 404.
(The #2703 e2e tests don't catch this because they set APISIX `node_listen`
to the same ports as the Gateway listeners — `9080`/`9081` — so listener port
== actual listening port there, a condition that does not hold in typical
deployments.)
### Temporary fix for affected users
Set the controller config to disable the injection:
```yaml
listener_port_match_mode: off
```
This restores the 2.0.x matching behavior without any other change.
### How this should be handled going forward
1. **The default should be `off`.** `server_port` injection must be opt-in:
- **Semantics:** a route attaching without `sectionName`/`port` means
"attach to all compatible listeners" and should match on all of them. The
`auto` heuristic (`len(ports) > 1`) turns the *normal* multi-listener
attachment into port filtering even though the user never expressed any
port-routing intent. The case that legitimately wants listener isolation is
explicit `sectionName`/`port` targeting, which is opt-in by nature.
- **Compatibility:** `auto` as default silently changes matching for
every multi-listener deployment on upgrade.
- This should ship as a 2.1.x patch so existing users recover without
touching their manifests.
2. **The mechanism itself needs a redesign before any inject-by-default mode
is safe.** Matching `$server_port` against the Gateway's logical listener port
is incorrect whenever port remapping is in play (Service/LoadBalancer, custom
`node_listen`, etc.) — which is the common case. Toggling *when* to inject does
not fix *what* is injected. A correct implementation has to map the Gateway
listener port to APISIX's actual listening port (or drop `server_port` for
listener disambiguation). This deserves a separate design discussion and should
not block the default change in (1).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]