Skip to content

Listener isolation or cascading behavior #2416

@youngnick

Description

@youngnick

When talking about Listener acceptance and merging behavior as part of #2288, we discovered that there was a particularly important part of the spec that we had not clarified enough, and that this has created a behavior variance between implementations.

I (@youngnick) summarized this as follows:

That concept is important because, for better or for worse, it has always been intended that the traffic-matching between Listeners and Routes is a two stage process. First you match a Listener, then you look for matching routes. In the case that there's a wildcard hostname, it was definitely not intended that a request could match both (for example, the cafe.example.com and *.example.com Listeners.) That is, having different values at all for hostname has been intended to make the Listeners distinct and unmergeable. We certainly have not done enough to explain that this is the intention, and I'm sorry for that.

That is, it was the original intention in the spec that, if there is a precise hostname match in one Listener, and a wildcard match in another, that traffic that matches the precise hostname will arrive only at Routes bound to that Listener.

Another way to put this is that if a precise hostname match is present, then a wildcard match should never also match that precise hostname.

Because we were not clear about this in the spec originally, many implementations have implemented their rules such that requests that match a precise hostname may, if there are no matching Routes for the request, match Routes attached to the wildcard hostname.

To use an example, here is a Gateway that @pleshakov supplied in #2288.

apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: gateway
spec:
  gatewayClassName: nginx
  listeners:
  - name: example
    port: 80
    protocol: HTTP
    hostname: "*.example.com"
  - name: cafe-http
    port: 80
    protocol: HTTP
    hostname: "cafe.example.com"

And here are some Routes that illustrate the config that may result in cascading behavior. I've left out hostnames on the HTTPRoutes so that only the Listener hostname is relevant.

apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: coffee
spec:
  parentRefs:
  - name: gateway
    sectionName: cafe-http
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /coffee
    backendRefs:
    - name: backend
      port: 3000
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: tea
spec:
  parentRefs:
  - name: gateway
    sectionName: example 
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /tea
    backendRefs:
    - name: backend 
      port: 3000

In this example, cafe.example.com has one HTTPRoute attached, /coffee, and *.example.com has one HTTPRoute attached, /tea.

The original intent of the spec is that the only valid request using cafe.example.com is http://cafe.example.com/coffee. Any request that does not match the set of Routes attached to the cafe-http Listener should be 404ed.

However, many implementations allow the request to cascade between Listeners, which means that request to either http://cafe.example.com/coffee or http://cafe.example.com/tea will succeed.

This issue is to discuss how to proceed here.

My personal preference is to tighten up the language here, and make the originally-implied behavior explicit and compulsory, with conformance tests to back it up. I'm aware that this will be painful for a number of implementations, but I really think that this is better in the long run. This is a very subtle difference that will be very difficult to explain to end users, and I think that it will significantly decrease portability to have this be optional in an extended feature.

Metadata

Metadata

Labels

kind/bugCategorizes issue or PR as related to a bug.triage/acceptedIndicates an issue or PR is ready to be actively worked on.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions