Skip to content

Expand and clarify Listeners definition #2288

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

Merged
merged 9 commits into from
Sep 25, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 49 additions & 32 deletions apis/v1beta1/gateway_types.go
Original file line number Diff line number Diff line change
@@ -85,38 +85,55 @@ type GatewaySpec struct {
//
// Port and protocol combinations not listed above are considered Extended.
//
// An implementation MAY group Listeners by Port and then collapse each
// group of Listeners into a single Listener if the implementation
// determines that the Listeners in the group are "compatible". An
// implementation MAY also group together and collapse compatible
// Listeners belonging to different Gateways.
//
// For example, an implementation might consider Listeners to be
// compatible with each other if all of the following conditions are
// met:
//
// 1. Either each Listener within the group specifies the "HTTP"
// Protocol or each Listener within the group specifies either
// the "HTTPS" or "TLS" Protocol.
//
// 2. Each Listener within the group specifies a Hostname that is unique
// within the group.
//
// 3. As a special case, one Listener within a group may omit Hostname,
// in which case this Listener matches when no other Listener
// matches.
//
// If the implementation does collapse compatible Listeners, the
// hostname provided in the incoming client request MUST be
// matched to a Listener to find the correct set of Routes.
// The incoming hostname MUST be matched using the Hostname
// field for each Listener in order of most to least specific.
// That is, exact matches must be processed before wildcard
// matches.
//
// If this field specifies multiple Listeners that have the same
// Port value but are not compatible, the implementation must raise
// a "Conflicted" condition in the Listener status.
// A Gateway's Listeners are considered "compatible" if:
//
// 1. The implementation can serve them in compliance with the Addresses
// requirement that all Listeners are available on all assigned
// addresses.
// 2. The implementation can match inbound requests to a single distinct
// Listener. When multiple Listeners share values for fields (for
// example, two Listeners with the same Port value), the implementation
// can can match requests to only one of the Listeners using other
// Listener fields.
//
// Compatible combinations in Extended support are expected to vary across
// implementations. A combination that is compatible for one implementation
// may not be compatible for another.
//
// If this field specifies multiple Listeners that are not compatible, the
// implementation MUST set the "Conflicted" condition in the Listener
// Status to "True".
//
// Implementations MAY choose to still accept a Gateway with conflicted
// Listeners if they accept a partial Listener set that contains no
// incompatible Listeners. They MUST set a "ListenersNotValid" condition
Copy link
Member

Choose a reason for hiding this comment

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

Nit: ListenersNotValid is a reason that can be used with "Accepted", generally to set the condition to "False". I'm not sure what we'd recommend in the case where Listeners were not valid and the Gateway was accepted.

Copy link
Contributor Author

@rainest rainest Aug 15, 2023

Choose a reason for hiding this comment

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

We say it can be used when Accepted is True. From the first point in my self-review, this is indeed a confusing case, but probably one that's intentionally ambiguous because we expect it to vary so much between implementations.

If we want to leave that as-is, the change here is just to say (here) that implementations must set this, whereas previously it wasn't a strict requirement, and wasn't obvious unless you looked through the reason comments. Even if it changes, I think we should mention something here.

Changing the current vague guidelines to something more formal would be a significant breaking change. Between that and the expected variance across vendors, my vote would be to defer it to post GA, when we have more practical experience regarding which approaches are in use and their pros and cons.

// the Gateway Status when the Gateway contains incompatible Listeners
// whether or not they accept the Gateway.
Comment on lines +107 to +111
Copy link
Member

Choose a reason for hiding this comment

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

I think the only reason we'd want to allow this is if a Gateway was already programmed with compatible listeners and then invalid/incompatible one(s) were added. It gets really tricky to represent this state. I may be remembering wrong here, but I think on GKE we will leave "Programmed" set to "True" with the last generation it was Programmed, but I don't think we have any clear guidance for these kinds of partially valid states in the spec.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

//
// For example, the following Listener scenarios may be compatible
// depending on implementation capabilities:
//
// 1. Multiple Listeners with the same Port that all use the "HTTP"
Copy link
Contributor

Choose a reason for hiding this comment

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

this example is a core feature

I wonder if "may be compatible" is applicable to it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Compatibility is weird because it ends up being about implementation capabilities rather than rules in the spec. If your implementation isn't compatible with something the core requires, it just can't implement the spec.

We could bring this further out of core by making it something outside the language above and mentioning specific ports, e.g. "Multiple Listeners with Port "9999" that all use the "HTTP" protocol (and similar for the other examples, just to make them consistent).

We could also separate examples that are within core or outside it, but it wouldn't be great for brevity.

// Protocol that all have unique Hostname values.
Copy link
Member

Choose a reason for hiding this comment

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

I know this is just an example, so it may not be critical here, but it might be helpful to define whether *.example.com and foo.example.com would be considered unique here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

8a9acfb adds this to the following Hostname precedence section. Do you think that works? It's not explicitly saying they are considered distinct, but it is using them as distinct values in the context where it matters.

// 2. Multiple Listeners with the same Port that use either the "HTTPS" or
// "TLS" Protocol that all have unique Hostname values.
// 3. A mixture of "TCP" and "UDP" Protocol Listeners, where no Listener
// with the same Protocol has the same Port value.
//
// An implementation that cannot serve both TCP and UDP listeners on the same
// address, or cannot mix HTTPS and generic TLS listens on the same port
// would not consider those cases compatible.
//
// Implementations using the Hostname value to select between same-Port
// Listeners MUST match inbound request hostnames from the most specific
// to least specific Hostname values to find the correct set of Routes.
// Exact matches must be processed before wildcard matches, and wildcard
// matches must be processed before fallback (empty Hostname value)
// matches. For example, `"foo.example.com"` takes precedence over
// `"*.example.com"`, and `"*.example.com"` takes precedence over `""`.
//
// Implementations MAY merge separate Gateways onto a single set of
// Addresses if all Listeners across all Gateways are compatible.
//
// Support: Core
//
118 changes: 74 additions & 44 deletions config/crd/experimental/gateway.networking.k8s.io_gateways.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

118 changes: 74 additions & 44 deletions config/crd/standard/gateway.networking.k8s.io_gateways.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.