Skip to content

Conversation

@rikatz
Copy link
Member

@rikatz rikatz commented Aug 7, 2025

What type of PR is this?
/kind gep

What this PR does / why we need it:
This PR is a review of ListenerSet GEP, fixing some manifests and adding some comments to be further discussed

Which issue(s) this PR fixes:

Fixes #

Does this PR introduce a user-facing change?:

NONE

@k8s-ci-robot k8s-ci-robot added release-note-none Denotes a PR that doesn't merit a release note. kind/gep PRs related to Gateway Enhancement Proposal(GEP) cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Aug 7, 2025
@k8s-ci-robot k8s-ci-robot added do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Aug 7, 2025
Copy link
Member

@LiorLieberman LiorLieberman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@k8s-ci-robot k8s-ci-robot requested a review from dprotaso August 7, 2025 17:37
@rikatz
Copy link
Member Author

rikatz commented Aug 7, 2025

One extra question I have on ListenerSet that is not clear for me, is the deduplication of listeners from different namespaces.

Let me add an example:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: parent-gateway
  namespace: infra
spec:
  allowedListeners:
    namespaces:
      from: All
---
apiVersion: gateway.networking.x-k8s.io/v1alpha1
kind: ListenerSet
metadata:
  name: listener01
  namespace: user01
spec:
  parentRef:
    name: parent-gateway
    namespace: infra
    kind: Gateway
    group: gateway.networking.k8s.io
  listeners:
  - name: something
    hostname: something.foo.com
    protocol: HTTPS
    port: 443
    tls:
      mode: Terminate
      certificateRefs:
      - kind: Secret
        group: ""
        name: cert
---
apiVersion: gateway.networking.x-k8s.io/v1alpha1
kind: ListenerSet
metadata:
  name: listener01
  namespace: user02
spec:
  parentRef:
    name: parent-gateway
    namespace: infra
    kind: Gateway
    group: gateway.networking.k8s.io
  listeners:
  - name: something
    hostname: something.foo.com
    protocol: HTTPS
    port: 443
    tls:
      mode: Terminate
      certificateRefs:
      - kind: Secret
        group: ""
        name: othercert

Who owns something.foo.com here? because in this case, if we are not explicitly deduplicating, we may have a situation where 2 listeners for the same host and different cert are set.

@rikatz
Copy link
Member Author

rikatz commented Aug 7, 2025

on ListenerSet conflict management: at some point on this GEP there is a mention to it:

Listeners in a Gateway and their attached ListenerSets are concatenated as a list when programming the underlying infrastructure

Listeners should be merged using the following precedence:

    "parent" Gateway
    ListenerSet ordered by creation time (oldest first)
    ListenerSet ordered alphabetically by "{namespace}/{name}".

This is the statement for conflict management, but it is not really clear on what a conflict means. This way, during a discussion on gateway-api channel, we've reached the consensus of writing some conflict examples and how to deal with them, as part of the GEP, to make it easier on implementation and conformance.

@youngnick
Copy link
Contributor

Thanks @rikatz.

To bring the comments I had in the Slack thread here:

I think there should be two rules:

  • ListenerSets cannot be Accepted unless all Listeners are distinct (see the Gateway Spec listeners field for an exact definition).
  • If Listeners within a group of ListenerSets are not distinct (that is, if Listeners in different ListenerSet objects that attach to the same Gateway are not distinct), then the Listeners are conflicting, and the Listener from the oldest ListenerSet object wins and is Accepted. ListenerSets containing conflicting Listeners MUST set the Conflicted Condition to true and clearly indicate which Listeners are conflicted.

Examples that illustrate those rules would be awesome.

@k8s-ci-robot k8s-ci-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Aug 11, 2025
@rikatz
Copy link
Member Author

rikatz commented Aug 11, 2025

@youngnick added some examples and a whole section for conflict management, let me know wdyt :)

@rikatz rikatz force-pushed the listener-set-fixes branch from 48fdd71 to cb485fa Compare August 15, 2025 18:34
@rikatz rikatz force-pushed the listener-set-fixes branch from ba348af to a7dd8ef Compare August 29, 2025 18:23
@rikatz
Copy link
Member Author

rikatz commented Aug 29, 2025

One last comment on this route disambiguation, just so I can be sure on the statement.

@youngnick @davidjumani if this is not right, and if you have some time I would appreciate if you can provide an example of a yaml/manifest with what you mean :)

Thanks!

@youngnick
Copy link
Contributor

Yes, this LGTM now. Thanks @rikatz!

@rikatz
Copy link
Member Author

rikatz commented Sep 1, 2025

/hold cancel

@k8s-ci-robot k8s-ci-robot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Sep 1, 2025
@youngnick
Copy link
Contributor

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Sep 2, 2025
Copy link
Member

@robscott robscott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @rikatz! Lots of great improvements here!

Some small nits + questions, feel free to remove hold when you've answered and/or addressed them.

/hold

Comment on lines 676 to 678
but MUST be validated also within a Gateway scope and all of the attached Listeners/ListenerSets. The SectionName field is an exception for this validation, and while
it should not conflict within the same ListenerSet, it can be duplicated between
different ListenerSets.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: The line length here feels inconsistent

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so, mostly of these line breaks is because I have a horizontal ruler on 80 characters after someone told me I should work better on my line breaking abilities to make it better readable :)

That said, I missed this one so I will add a new proper break here but as we don't have any convention (I guess) I wouldn't mind that much on this

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, not too picky here. I personally try to wrap at 80 chars. I've also seen some folks successfully use the sentence per line approach, and I'm increasingly thinking that may be a good compromise here. In the Mesh GEP, @kflynn went a step further to use semantic line breaks. We're likely overdue to have some kind of standard for markdown in this project.

I tend to lean towards the following:

  • 80 char wrapping for godoc comments
  • Sentence per line wrapping for all markdown files

With that said, this should probably be turned into an issue/discussion for next steps.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(FTR I think the the Mesh GEP experiment was worth doing, but I think that the sentence-per-line approach is likely to be more practical.)


To attach to listeners in both a `Gateway` and `ListenerSet` the route MUST have two `parentRefs`:
For instance, the following `HTTPRoute` attempts to attach to a listener defined in the parent `Gateway` using the sectionName `foo`, which exists on a `ListenerSet` but not on a `Gateway`.
This is not valid and the route's status `Accepted` condition should be set to `False`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What should a Gateway implementation do with this? In the case where a Route is no longer accepted, is it supposed to drop it altogether? IE if you add a new parentRef that makes the Route invalid, do you drop the entire Route, or does the Gateway impl add something into status specifically for this ListenerSet?

Actually, did we cover how status is supposed to work here? Should we populate separate Route parent statuses for each ListenerSet and Gateway, or just the Gateway? cc @youngnick

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ListenerEntryStatus has an AttachedRoutes count. That should suffice for the listenerset side (at least for now)
I don't think the route should be dropped - if ListenerSets are an extension of the Gateway, then it should work as such - similar to what happens if a gateway parentref is invalid
The implementation could add something to the route status if needed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if you add a new invalid parentRef that breaks your HTTPRoute, it should be moved to Accepted=False as originally stated, and be unconfigured on the Gateway.

You are intentionally breaking your route, right? Let's remove the ListenerSet from the equation: what happens if you have a Route that is using a Gateway as a parentRef and then you change it to another Gateway but a sectionName doesn't exist on it?

Copy link
Member Author

@rikatz rikatz Sep 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, sorry, I just typed and saw your answer @davidjumani

So, the current behavior today is that the route is not dropped, and it gets something like invalid Parent ref on the status?

EDIT: anyway, as there are 2 different understandings here, I think it is a good callout of what should be done in this case. Will wait Nick to chime in, and we can disambiguate this case

Copy link
Contributor

@youngnick youngnick Sep 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case highlighted here, if a HTTPRoute references a sectionName on a parentRef that points to a ListenerSet, and there is no Listener in that ListenerSet with that name field set, then the HTTPRoute MUST fail to attach, regardless of what Listeners exist at the Gateway level.

That's what we agreed on earlier - to summarize:

  • For considering Listener-Listener conflicts, you have to look at all Listeners, regardless of their source.
  • For considering Route attachement, you only need to consider the listeners in the actual parent object (Gateway or ListenerSet). For Routes that attach to a Gateway, you don't need to care about what Listeners are in any ListenerSets, and for Routes that attach to a ListenerSet, you don't need to care about what Listeners are in the Gateway.

Maybe another way to say this that's more specification-like:

  • Routes attach to all relevant Listeners in their direct Parent object.
  • If a Route has a parentRef that is a ListenerSet, then the ListenerSet is the direct Parent.
  • If a Route has a parentRef that is a Gateway, then the Gateway is the direct Parent.
  • If the Route is using Gateway defaulting, then the default Gateway is the direct Parent.
  • If sectionName is not set, then all Listeners in the direct Parent object are relevant, and the Route must attach to all of them (subject to any allowedRoutes criteria.)
  • If sectionName is set, then only the Listener in the direct Parent object with the name field set to the same value as sectionname is relevant, and the Route must attach only to that Listener (subject to any allowedRoutes criteria).
  • If there are no relevant Listeners (because, for example, a sectionName is specified that does not exist on the direct Parent), then the Route has nowhere to attach to and MUST be have Accepted set to false for that parentRef.

Route status is per-parentRef, so if a new parentRef is added, that attachment is independent of any existing parentRefs. A Route can be Accepted by one parentRef and not another, that's fine.

If you have a Route that has a Gateway parentRef with a sectionName, that is Accepted already, and you add another parentRef that points to a ListenerSet with a sectionName, and the ListenerSet does not include a Listener with a name matching the sectionName, then the ListenerSet parentRef must be Accepted status: false. That does not affect the Gateway parentRef.

To answer @robscott's original question, yes, we should populate status per-parentRef, no matter what the parent is.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a phenomenal summary, thanks @youngnick! Would love to see this incorporated into the GEP.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@robscott @youngnick I have copied Nick's text as is to the GEP, as I agree it is great and very clarifying, thanks!

@k8s-ci-robot k8s-ci-robot added do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. approved Indicates a PR has been approved by an approver from all required OWNERS files. labels Sep 2, 2025
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: davidjumani, rikatz, robscott

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot removed the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Sep 2, 2025
@youngnick
Copy link
Contributor

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Sep 4, 2025
@robscott
Copy link
Member

robscott commented Sep 4, 2025

/hold cancel

@k8s-ci-robot k8s-ci-robot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Sep 4, 2025
@k8s-ci-robot k8s-ci-robot merged commit 368d492 into kubernetes-sigs:main Sep 4, 2025
18 of 19 checks passed
shaneutt pushed a commit that referenced this pull request Sep 5, 2025
* Improve some ListenetSet gep descriptions

* Add examples of conflicting ListenerSets

* Fix some review findings

* Fix some comments on GEP

* Make the behavior on route attachement explicit

* Fix some reviews

* Use XListenerSet on example kinds

* Final fix on listenerset gep

* Fix some more reviews

* Add clarification on ListenerSet attachment
tylerauerbeck pushed a commit to tylerauerbeck/gateway-api that referenced this pull request Nov 27, 2025
* Improve some ListenetSet gep descriptions

* Add examples of conflicting ListenerSets

* Fix some review findings

* Fix some comments on GEP

* Make the behavior on route attachement explicit

* Fix some reviews

* Use XListenerSet on example kinds

* Final fix on listenerset gep

* Fix some more reviews

* Add clarification on ListenerSet attachment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/gep PRs related to Gateway Enhancement Proposal(GEP) lgtm "Looks good to me", indicates that a PR is ready to be merged. release-note-none Denotes a PR that doesn't merit a release note. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants