Skip to content

Improve some ListenetSet gep descriptions #3978

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

rikatz
Copy link
Contributor

@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 requested a review from candita August 7, 2025 17:29
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: rikatz
Once this PR has been reviewed and has the lgtm label, please assign thockin for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found 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 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
@@ -59,7 +59,7 @@ type GatewaySpec struct {
}

type AllowedListeners struct {
// +kubebuilder:default={from:Same}
// +kubebuilder:default={from: None}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this was made to reflect the current implementation

Copy link
Member

Choose a reason for hiding this comment

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

I may be out of context, wdym here? are we moving away from the Same as default?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

on the API definition Same is not the default, None is:

// +kubebuilder:default={from: None}

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!

@@ -59,7 +59,7 @@ type GatewaySpec struct {
}

type AllowedListeners struct {
// +kubebuilder:default={from:Same}
// +kubebuilder:default={from: None}
Copy link
Member

Choose a reason for hiding this comment

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

I may be out of context, wdym here? are we moving away from the Same as default?

Comment on lines -442 to +474

To attach to listeners in both a `Gateway` and `ListenerSet` the route MUST have two `parentRefs`:
```yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httproute-example
spec:
parentRefs:
- name: some-workload-listeners
- name: second-workload-listeners
kind: ListenerSet
sectionName: second
- name: parent-gateway
kind: Gateway
sectionName: foo
```

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`. This is not valid and the route's status `Accepted` condition should be set to `False`

```yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httproute-example
spec:
parentRefs:
- name: second-workload-listeners
kind: ListenerSet
sectionName: second
- name: parent-gateway
- name: some-workload-listeners
Copy link
Member

Choose a reason for hiding this comment

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

I guess no real change here, just order, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

right, I wrote on my self review why I did the change. The example of the attachment of Gateway AND ListenerSet is more clear on this order, then we can go to the invalid examples :)

Copy link
Contributor

Choose a reason for hiding this comment

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

To make this invalid the kind needs to be a ListenerSet in the parentRef

kind: Gateway
sectionName: foo
```
>--- Ricardo - above is a bit confusing, maybe ask Dave some clarification
Copy link
Member

Choose a reason for hiding this comment

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

/cc @dprotaso

@k8s-ci-robot k8s-ci-robot requested a review from dprotaso August 7, 2025 17:37
```yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: parent-gateway
spec:
gatewayClassName: example
allowedListeners:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

per the api spec, not having an allowedListener means "None" which would make this invalid, so I am fixing the example for at least same namespace

@@ -417,7 +424,8 @@ metadata:
name: parent-gateway
spec:
allowedListeners:
- from: Same
namespaces:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

allowedListeners is not an array, so changing here to reflect the current implemented API

@@ -438,35 +446,38 @@ spec:
sectionName: second
```

For instance, the following `HTTPRoute` attempts to attach to a listener defined in the parent `Gateway` using the sectionName `foo`. This is not valid and the route's status `Accepted` condition should be set to `False`

To attach to listeners in both a `Gateway` and `ListenerSet` the route MUST have two `parentRefs`:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have changed the order of examples here to make it clear what means using two parentRefs, before the next example which is an invalid example

Copy link
Contributor

Choose a reason for hiding this comment

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

Reading this now it is a duplicate of Routes MUST be able to attach to a ListenerSetand it's parentGatewayby having multipleparentRefs eg:

I saw we replace the above yaml

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: httproute-example
spec:
  parentRefs:
  - name: second-workload-listeners
    kind: ListenerSet
    sectionName: second

with the yaml containing two parent refs

kind: Gateway
sectionName: foo
```
>--- Ricardo - above is a bit confusing, maybe ask Dave some clarification
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@dprotaso the example above is a bit confusing for me, probably because the API changed from when it was implemented.

I was wondering what it means for an HTTPRoute to try to attach a listener defined on a Gateway, using a section name foo. If this section name exists on the Gateway it is valid, right? eg.:

  listeners:
  - name: foo
    port: 80
    protocol: HTTP

So how can the situation above be invalid? Maybe we can get the full yaml definition, with Gateway, ListenerSet and HTTPRoute for clarification here?

Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

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

@rikatz
Copy link
Contributor 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
Contributor 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
Contributor Author

rikatz commented Aug 11, 2025

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

@@ -115,6 +115,16 @@ type ListenerSetSpec struct {
// 2. ListenerSet ordered by creation time (oldest first)
// 3. ListenerSet ordered alphabetically by “{namespace}/{name}”.
//
// Regarding Conflict Management, Listeners in a ListenerSet follow the same
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we add this new clause to the API types godoc?

Also we might want to call out sectionName behaves a bit differently where sibling ListenerSets can have the same sectionName.

hostname: www.something.tld
protocol: HTTPS
port: 443
tls:
Copy link
Contributor

Choose a reason for hiding this comment

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

tab instead of space maybe?

Image

Comment on lines 343 to +345
The following example shows a `Gateway` with an HTTP listener and two child HTTPS `ListenerSets` with unique hostnames and certificates.

Only `ListenerSets` from the same namespace of the `Gateway` will be accepted:
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
The following example shows a `Gateway` with an HTTP listener and two child HTTPS `ListenerSets` with unique hostnames and certificates.
Only `ListenerSets` from the same namespace of the `Gateway` will be accepted:
The following example shows a `Gateway` with an HTTP listener and two child HTTPS `ListenerSets` with unique hostnames and certificates. Only `ListenerSets` from the same namespace of the `Gateway` will be accepted:

Conflicts are covered in the section 'ListenerConditions within a ListenerSet'
Conflicts are covered in the section [Listener and ListenerSet conflicts](#listener-and-listenerset-conflicts)

### Listener and ListenerSet conflicts
Copy link
Contributor

Choose a reason for hiding this comment

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

We should combine this section into ListenerConditions within a ListenerSet so that conflicts are covered in one section.

management.

With ListenerSet this validation should happen within the same ListenerSet resource,
but MUST be validated also within a Gateway scope and all of the attached Listeners/ListenerSets.
Copy link
Contributor

Choose a reason for hiding this comment

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

this language needs to exclude sectionName when comparing it across sibling Listeners

Copy link
Contributor

Choose a reason for hiding this comment

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

Or refer to 'Optional Section Name'

hostname: www.something.tld
protocol: HTTPS
port: 443
conditions:
Copy link
Contributor

@dprotaso dprotaso Aug 11, 2025

Choose a reason for hiding this comment

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

using a tab here instead of spaces

Copy link
Contributor

Choose a reason for hiding this comment

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

There's a bunch of these places - just view the GitHub rendering of the GEP and you'll see broken syntax formatting

```

The ListenerSet `user-listenerset` should be marked as Conflicted, as the `parent-gateway`
have a listener definition called `foo` that conflicts with the ListenetSet definition
Copy link
Contributor

@dprotaso dprotaso Aug 11, 2025

Choose a reason for hiding this comment

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

Suggested change
have a listener definition called `foo` that conflicts with the ListenetSet definition
The ListenerSet `user-listenerset` should be marked as Conflicted, as the `parent-gateway`
has a listener definition called `foo` that conflicts with the ListenerSet definition
called `myapp`, as the following:

Can we also update this (the paragraph not the condition message) to highlight that it is a conflict because the host name is the same but they use different termination TLS certificates

protocol: HTTPS
port: 443
conditions:
- message: ListenerSet has conflicts with Gateway 'infra/parent-gateway'
Copy link
Contributor

Choose a reason for hiding this comment

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

Would we want to highlight the listener name in the error message?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. kind/gep PRs related to Gateway Enhancement Proposal(GEP) 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.

5 participants