Venkat-C-J opened a new issue, #2822:
URL: https://github.com/apache/apisix-ingress-controller/issues/2822
### Current Behavior
Starting in v2.1.0 (commit `0d225ad`, PR #2743), the route translator no
longer sets `route.Hosts`
when building the APISIX route object for ADC sync.
File: `internal/adc/translator/apisixroute.go`, function `buildRoute`
The PR description states the line was removed intentionally:
> "Hosts were being set redundantly at both the route level and the service
level. Since the
> service level is the canonical location, the route-level assignment was
removed to prevent
> spurious diff-detected events during ADC sync."
This assumes APISIX inherits `service.hosts` for route matching. It does not
— APISIX's
radix-tree route matcher only reads the **route's own** `hosts` field.
`service.hosts` has no
effect on request routing/matching at all.
As a result, every `ApisixRoute` CRD that specifies
`spec.http[].match.hosts` in its source YAML
gets translated into an APISIX route object with **no `hosts` field**, even
though the CRD itself
is correct. This makes every route match on **path + priority only**,
regardless of the incoming
`Host` header.
**Impact:** In any multi-tenant setup where two different `ApisixRoute`
resources (for two
different hosts) happen to define overlapping/generic path patterns (e.g.
`/`, `/user`, or a
regex like `/(.*)/callback.*`), the route with the **higher `priority`** now
wins for *all* hosts,
not just the host it was intended for. Requests for Host B get silently
routed to the backend
configured for Host A, typically producing a 404 (or worse, being served
with the wrong tenant's
plugins/backend) instead of matching Host B's own route.
### Expected Behavior
`buildRoute` should preserve the route-level hosts from the CRD:
```go
route.Hosts = rule.Match.Hosts
```
A route created from an `ApisixRoute` with `match.hosts:
[tenant-a.example.com]` should only ever
match requests carrying that `Host` header, irrespective of any other
route's priority or the
`hosts` set on the referenced `ApisixService`.
## Suggested Fix
Restore the deleted line in `internal/adc/translator/apisixroute.go`,
function `buildRoute`:
```go
// APISIX route matching uses route.Hosts, NOT service.Hosts.
// Removing this causes all routes to become host-agnostic.
route.Hosts = rule.Match.Hosts
```
If the original "spurious diff detected" issue (duplicate hosts assignment
between route and
service level) still needs solving, it should be solved by
normalizing/deduplicating the diff
comparison logic, not by dropping the route-level `hosts` field — since
`service.hosts` has no
bearing on actual request routing.
### Error Logs
**1. Source `ApisixRoute` CRD (sanitized) — hosts are correctly specified:**
```yaml
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: service-b-routes
spec:
ingressClassName: apisix
http:
- name: service-b-user-route
priority: 5
match:
hosts:
- tenant-b.example.com
paths:
- /*
exprs:
- subject:
scope: Path
name: user-path
op: RegexMatch
value: '/user$'
backends:
- serviceName: service-b-backend
servicePort: 8080
```
**2. Resulting route object dumped from the APISIX Admin API (sanitized) —
`hosts` is missing:**
```json
{
"key": "/apisix/routes/aaaa1111",
"value": {
"id": "aaaa1111",
"name": "service-b_service-b-routes_service-b-user-route",
"uris": ["/*"],
"priority": 5,
"service_id": "bbbb2222",
"vars": [["uri", "~~", "/user$"]]
}
}
```
Note: no `hosts` key at all, despite the source CRD above defining
`match.hosts: [tenant-b.example.com]`.
**3. Competing higher-priority route from a different tenant (sanitized),
also missing `hosts`:**
```json
{
"key": "/apisix/routes/cccc3333",
"value": {
"id": "cccc3333",
"name": "service-a_service-a-routes_service-a-user-route",
"uris": ["/*"],
"priority": 20,
"service_id": "dddd4444",
"vars": [["uri", "~~", "/user$|/user/$"]]
}
}
```
**4. Observed test failure (sanitized E2E result):**
```
Testcase: "user path via https"
Request: GET https://tenant-b.example.com/user
Expected: 200 (service-b-backend response)
Actual: 404 (request was routed to service-a-backend, which has no
knowledge of tenant-b.example.com)
```
Because both routes above lack a `hosts` field after translation, APISIX
picks the route with the
higher numeric `priority` (20, tenant-a's route) for **any** Host header
hitting path `/user`,
including requests for `tenant-b.example.com` that should have matched the
priority-5 route
instead.
### Steps to Reproduce
1. Install APISIX Ingress controller v2.1.0 with the Helm chart, pointing at
an APISIX data plane
with two upstream services, `service-a-backend` and `service-b-backend`.
2. Create two `ApisixRoute` resources:
- `service-a-routes`: `match.hosts: [tenant-a.example.com]`, path `/*`
with a regex `vars`
condition matching `/user$`, `priority: 20`, backend
`service-a-backend`.
- `service-b-routes`: `match.hosts: [tenant-b.example.com]`, path `/*`
with a regex `vars`
condition matching `/user$`, `priority: 5`, backend `service-b-backend`.
3. Wait for the ingress controller to sync both routes to APISIX via ADC.
4. Dump the routes from the Admin API: `curl
http://<apisix-admin>/apisix/admin/routes` — observe
neither route object contains a `hosts` field, even though both source
CRDs specify one.
5. Send a request with `Host: tenant-b.example.com` and path `/user`.
6. **Expected:** response comes from `service-b-backend` (matched by
`service-b-routes`,
priority 5, host `tenant-b.example.com`).
7. **Actual:** response comes from `service-a-backend` (`service-a-routes`,
priority 20) because
route selection is now host-agnostic and priority alone decides —
`service-a-backend` has no
knowledge of `tenant-b.example.com` and returns 404 (or an unrelated
response).
### Environment
- APISIX Ingress controller version: `2.1.0` (regression introduced in PR
#2743, commit `0d225ad`;
confirmed working correctly on `2.0.1`)
- ADC version: `v0.26.x`
- APISIX data plane version: `3.16.x` (also reproduced on `3.15.x` — data
plane version is not the
cause; confirmed via changelog review that no route-matching semantics
changed between these
versions)
- Kubernetes cluster version: `1.29.x` (generic — issue is not
Kubernetes-version-specific)
- OS: Linux (containerized); also reproduced with a local Docker Desktop /
kind cluster on macOS
--
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]