From 71a9babc5e5803e4b16d714dbef45416fef298d5 Mon Sep 17 00:00:00 2001 From: dprotaso Date: Tue, 21 Mar 2023 21:06:34 -0400 Subject: [PATCH 01/40] Second Revision of GEP-1713 --- geps/gep-1713/index.md | 408 ++++++++++++++++++++++++++++++++++++ geps/gep-1713/metadata.yaml | 7 + 2 files changed, 415 insertions(+) create mode 100644 geps/gep-1713/index.md create mode 100644 geps/gep-1713/metadata.yaml diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md new file mode 100644 index 0000000000..1c04d0ba67 --- /dev/null +++ b/geps/gep-1713/index.md @@ -0,0 +1,408 @@ +# GEP-1713: Standard Mechanism to Merge Multiple Gateways + +* Issue: [#1713](/kubernetes-sigs/gateway-api/issues/1713) +* Status: Provisional + +(See status definitions [here](overview.md#status).) + +## tl;dr + +The `Gateway` Resource is a point of contention since it is the only place to attach listeners with certificates. We propose a new resource called `ListenerSet` to allow a shared list of listeners to be attached to a single `Gateway`. + +## Goals +- Define a mechanism to merge listeners into a single `Gateway` + +## Future Goals (Beyond the GEP) +- Attaching listeners to `Gateways` in different namespaces + +## Introduction + +Knative generates on demand per-service certificates using HTTP-01 challenges. +There can be O(1000) Knative `Services` in the cluster which means we have O(1000) distinct certificates. +Thus updating a single `Gateway` resource with this many certificates is a contention point and inhibits horizontal scaling of our controllers. + +More broadly, large scale gateway users often expose `O(1000)` domains, but are currently limited by the maximum of 64 `listeners`. + +The spec currently has language to indicate implementations `MAY` merge `Gateways` resources but the mechanic isn't defined. +https://github.com/kubernetes-sigs/gateway-api/blob/541e9fc2b3c2f62915cb58dc0ee5e43e4096b3e2/apis/v1beta1/gateway_types.go#L76-L78 + +## API + +This proposal has introduces a new resource `ListenerSet` that has the ability to attach to a set of listeners to a parent `Gateway`. + +#### Go + +```go +type GatewaySpec struct { + ... + AllowedListeners []*AllowedListeners `json:"allowedListeners"` + ... +} + +type AllowedListeners struct { + // +kubebuilder:default={from: Same} + Namespaces *ListenerNamespaces `json:"namespaces,omitempty"` +} + +// ListenerNamespaces indicate which namespaces ListenerSets should be selected from. +type ListenerNamespaces struct { + // From indicates where ListenerSets can attach to this Gateway. Possible + // values are: + // + // * Same: Only ListenerSets in the same namespace may be attached to this Gateway. + // * None: Only listeners defined in the Gateway's spec are allowed + // + // +optional + // +kubebuilder:default=Same + From *FromNamespaces `json:"from,omitempty"` +} + +// ListenerSet defines a set of additional listeners to attach to an existing Gateway. +type ListenerSet struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of ListenerSet. + Spec ListenerSetSpec `json:"spec"` + + // Status defines the current state of ListenerSet. + Status ListenerSetStatus `json:"status,omitempty"` +} + +// ListenerSetSpec defines the desired state of a ListenerSet. +type ListenerSetSpec struct { + // ParentRef references the Gateway that the listeners are attached to. + ParentRef ParentGatewayReference `json:"parentRefs,omitempty"` + + // Listeners associated with this ListenerSet. Listeners define + // logical endpoints that are bound on this referenced parent Gateway's addresses. + // + // At least one Listener MUST be specified. + // + // Note: this is the same Listener type in the GatewaySpec struct + Listeners []Listener +} + +// ListenerSetStatus defines the observed state of ListenerSet. +type ListenerSetStatus struct { + // Listeners provide status for each unique listener port defined in the Spec. + // + // +optional + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MaxItems=64 + // + // Note: this is the same ListenerStatus type in the GatewayStatus struct + Listeners []ListenerStatus `json:"listeners,omitempty"` + + // Conditions describe the current conditions of the ListenerSet. + // + // Implementations should prefer to express ListenerSet conditions + // using the `GatewayConditionType` and `GatewayConditionReason` + // constants so that operators and tools can converge on a common + // vocabulary to describe Gateway state. + // + // Known condition types are: + // + // * "Accepted" + // * "Programmed" + // + // +optional + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MaxItems=8 + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +// ParentGatewayReference identifies an API object including its namespace, +// defaulting to Gateway. +type ParentGatewayReference struct { + // Group is the group of the referent. + // + // +optional + // +kubebuilder:default="gateway.networking.k8s.io" + Group *Group `json:"group"` + + // Kind is kind of the referent. For example "Gateway". + // + // +optional + // +kubebuilder:default=Gateway + Kind *Kind `json:"kind"` + + // Name is the name of the referent. + Name ObjectName `json:"name"` + + // Namespace is the namespace of the referenced object. When unspecified, the local + // namespace is inferred. + // + // Support: Core + // + // +optional + Namespace *Namespace `json:"namespace,omitempty"` +} +``` + +#### YAML + +The following example shows a `Gateway` with an HTTP listener and two child HTTPS `ListenerSets` with unique hostnames and certificates. + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: parent-gateway +spec: + gatewayClassName: example + listeners: + - name: foo + hostname: foo.com + protocol: HTTP + port: 80 +--- +apiVersion: gateway.networking.k8s.io/v1alpha1 +kind: ListenerSet +metadata: + name: first-workload-listeners + labels: + gateway.networking.k8s.io/gateway.name: parent-gateway +spec: + parentRef: + name: parent-gateway + kind: Gateway + group: gateway.networking.k8s.io + listeners: + - name: first + hostname: first.foo.com + protocol: HTTPS + port: 443 + tls: + mode: Terminate + certificateRefs: + - kind: Secret + group: "" + name: first-workload-cert # Provisioned via HTTP01 challenge +--- +apiVersion: gateway.networking.k8s.io/v1alpha1 +kind: ListenerSet +metadata: + name: second-workload-listeners +spec: + parentRef: + name: parent-gateway + kind: Gateway + group: gateway.networking.k8s.io + listeners: + - name: second + hostname: second.foo.com + protocol: HTTPS + port: 443 + tls: + mode: Terminate + certificateRefs: + - kind: Secret + group: "" + name: second-workload-cert # Provisioned via HTTP01 challenge +``` +### Semantics + +#### Gateway <> ListenerSet Handshake + +By default a `Gateway` will allow `ListenerSets` in the same namespace to be attached. Users can prevent this behaviour by configuring their `Gateway` to disallow any listener attachment: + +``` +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: parent-gateway +spec: + allowedListeners: + - from: None +``` + +#### Listeners + +#### `ListenerSet.spec.parentRef` is immutable + +A `ListenerSet` `MUST` be created with a `parentRef` Updating the `parentRef` of a ListenerSet `MUST` be rejected by the API. + +#### `ListenerSet` Default Labels + +In order for clients of the API to easily discover `Gateways` and their `ListenerSets` we propose a set of labels to be defaulted when creating `ListenerSets`. This only applies if the `parentRef.kind` is a `Gateway` + +- `gateway.networking.k8s.io/gateway.name` is equal to `spec.parentRef.name` +- `gateway.networking.k8s.io/gateway.namespace` is equal to `spec.parentRef.namespace` + +This allows clients to perform API [lookups](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#list-and-watch-filtering) using label selectors. + +TBD: Can conditional defaulting be done with CEL? + +#### GatewaySpec.Listeners MinItems + +TBD: Do we want to make this change? + +Currently when creating a Gateway you must specify at least a single listener. With `ListenerSets` this opens the possibility of wanting to create a Gateway with no listeners. + +#### Route Attaching + +Routes MUST be able to specify a `ListenerSet` as a `parentRef` and make use of the `sectionName` field in `ParentReference` to help target a specific listener. If no listener is targeted (`sectionName`/`port` are unset) then the Route references all the listeners on the `ListenerSet`. It `MUST NOT` attach to additional listeners on the parent `Gateway`. + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: httproute-example +spec: + parentRefs: + - name: second-workload-listeners + kind: ListenerSet + sectionName: second +``` + +For instance, the following `HTTPRoute` attemps to attach to a listener defined in the parent `Gateway`. This is not valid and the route's status should reflect that. + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: httproute-example +spec: + parentRefs: + - name: some-workload-listeners + kind: ListenerSet + sectionName: foo +``` + +#### Listener Validation + +Implementations MUST treat the parent `Gateway` as having the concatenated list of all listeners from itself and attached `ListenerSets` +Validation of this list of listeners MUST behave the same as if the list were part of a single `Gateway`. + +From the earlier example the above resources would be equivalent to a single `Gateway` where the listeners are collapsed into a single list. + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: parent-gateway +spec: + gatewayClassName: example + listeners: + - name: foo + hostname: foo.com + protocol: HTTP + port: 80 + - name: first + hostname: first.foo.com + protocol: HTTPS + port: 443 + tls: + mode: Terminate + certificateRefs: + - kind: Secret + group: "" + name: first-workload-cert # Provisioned via HTTP01 challenge + - name: second + hostname: second.foo.com + protocol: HTTPS + port: 443 + tls: + mode: Terminate + certificateRefs: + - kind: Secret + group: "" + name: second-workload-cert # Provisioned via HTTP01 challenge +``` + +#### Listener Precedence + +Listeners should be merged using the following precedence: +1. "parent" Gateway +2. ListenerSet ordered by creation time (oldest first) +3. ListenerSet ordered alphabetically by “{namespace}/{name}”. + +If there are listener conflicts, this should be reported as `Conflicted=True` in the ListenerStatus as usual. See 'Conditions' section below for more details on object should report the conflict. + +### Gateway Conditions + +`Gateway` currently supports the following top-level condition types: `Accepted` and `Programmed` + +For a `Gateway`, `Accepted` should be set based on the entire set of merged listeners. +For instance, if a `ListenerSet` listener is invalid, `ListenersNotValid` would be reported. +`Programmed` is not expected, generally, to depend on the children resources, but if an implementation does depend on these +they should consider child resources when reporting this status. + +Parent gateways MUST NOT have `ListenerSet` listeners in their `status.listeners` conditions list. + +It is up to the implementation whether an invalid listener affects other listeners in the Gateway. + +### ListenerSet Conditions + +`ListenerSets` MUST NOT have their parent `Gateway`'s' listeners in the `status.listeners` conditions list. An implementation MAY reject listeners with `ListenerConditionAccepted=False` and Reason `TooManyListeners` `ListenerSets`, like a `Gateway`, also have two top-level conditions: `Accepted` and `Programmed`. These conditions, when surfacing details about listeners, MUST only summarize the `status.listener` conditions that are exclusive to the `ListenerSet`. + +These conditions MUST also surface top-level `Gateway` conditions that impact the `ListenerSet`. For example, if a `Gateway` requests an invalid address and it cannot be accepted/programmed then the `ListenerSet`'s' `Accepted` condition MUST be set to `False`. + +For example, if I have a `Gateway` named `parent`, and two `ListenerSets` named `child-1`, and `child-2` then: +* If `parent` is entirely invalid (for example, an invalid `address`) and `Accepted=False`, all two `ListenerSets` will reported `Accepted=False`. +* If `child-1` has an invalid listener, `parent` and `child-1` will report `ListenersNotValid`, while `child-2` will not. +* If `child-1` references a parent that doesn't allow merging then `child-1` will report `Accepted=False` +* If `child-1` references another child (eg. `child-2`) then `child-1` will report `Accepted=False` +* If `child-1` is valid, then when `child-2` is created if it conflicts with `child-1` then `child-2` will report `Accepted=False`. `child-1` status conditions will remain unchanged. `parent` will report `ListenersNotValid` + +When reporting status of a child, an implementation SHOULD be cautious about what information from the parent or siblings are reported +to avoid accidentally leaking sensitive information that the child would not otherwise have access to. + +TBD: The following situations aren't possible to handle since there's no 'gatewayClass' on the `ListenerSet` +* If `child-1` references a parent that doesn't exist then `child-1` will report `Accepted=False` +* If `child-1` references itself then `child-1` will report `Accepted=False` +* If `child-1` and `parent` have different gatewayClassNames then `child-1` will report `Accepted=False` + +#### Policy Attachment + +Policies attached to a parent `Gateway` apply to both the parent and all `ListenerSet` listeners. + +Policies that attach to a `ListenerSet` apply to all listeners defined in that resource, but do not impact listeners in the parent `Gateway` +If the implementation cannot apply the policy to only specific listeners, it should reject the policy. + +## Alternatives + +#### Re-using Gateway Resource + +The [first iteration of this GEP](https://github.com/kubernetes-sigs/gateway-api/pull/1863) proposed re-using the `Gateway` resource and introducing an `attachTo` property in the `infrastructure` stanza. + +The main downside of this approach is that users still require `Gateway` write access to create listeners. Secondly, it introduces complexity to future `Gateway` features as GEP authors would have now have to account for merging semantics. + +#### New 'GatewayGroup' Resource + +This was proposed in the Gateway Hiearchy Brainstorming document (see references below). The idea is to introduce a central resource that will coalease Gateways together and offer forms of delegation. + +Issues with this is complexity with status propagation, cluster vs. namespace scoping etc. It also lacks a migration path for existing Gateways to help shard listeners. + +#### Use of Multiple Disjointed Gateways + +An alternative would be to encourage users to not use overly large Gateways to minimize the blast radius of any issues. Use of disjoint Gateways could accomplish this but it has the disadvantage of consuming more resources and introducing complexity when it comes to operations work (eg. setting up DNS records etc.) + +#### Increase the Listener Limit + +Increasing the limit may help in situations where you are creating many listeners such as adding certificates created using an ACME HTTP01 challenge. Unfortunately this still makes the Gateway a single point of contention. Unfortunately, there will always be an upper bound because of etcd limitations. +For workloads like Knative we can have O(1000) Services on the cluster with unique subdomains. + +#### Expand Route Functionality + +For workloads with many certificates one option would be to introduce a `tls` stanza somewhere in the Route types. These Routes would then attach to a single Gateway. Then application operators can provide their own certificates. This probably would require some ability to have a handshake agreement with the Gateway. + +Sorta related there was a Route Delegation GEP (https://github.com/kubernetes-sigs/gateway-api/issues/1058) that was abandoned + +## References + +First Revision of the GEP +- https://github.com/kubernetes-sigs/gateway-api/pull/1863 + +Mentioned in Prior GEPs: +- https://github.com/kubernetes-sigs/gateway-api/pull/1757 + +Prior Discussions: +- https://github.com/kubernetes-sigs/gateway-api/discussions/1248 +- https://github.com/kubernetes-sigs/gateway-api/discussions/1246 + +Gateway Hiearchy Brainstorming +- https://docs.google.com/document/d/1qj7Xog2t2fWRuzOeTsWkabUaVeOF7_2t_7appe8EXwA/edit diff --git a/geps/gep-1713/metadata.yaml b/geps/gep-1713/metadata.yaml new file mode 100644 index 0000000000..2adb1f4627 --- /dev/null +++ b/geps/gep-1713/metadata.yaml @@ -0,0 +1,7 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 1713 +name: Gateway Merging - ListenerSet +status: Provisional +authors: + - dprotaso From 02c6a05789b318f0e969e1807d102cde5623434f Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Mon, 29 Jul 2024 22:09:14 -0400 Subject: [PATCH 02/40] fix minor nits --- geps/gep-1713/index.md | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 1c04d0ba67..fff38a0012 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -28,13 +28,14 @@ https://github.com/kubernetes-sigs/gateway-api/blob/541e9fc2b3c2f62915cb58dc0ee5 ## API -This proposal has introduces a new resource `ListenerSet` that has the ability to attach to a set of listeners to a parent `Gateway`. +This proposal introduces a new `ListenerSet` resource that has the ability to attach to a set of listeners to a parent `Gateway`. #### Go ```go type GatewaySpec struct { ... + // Note: this is a list to allow future potential features AllowedListeners []*AllowedListeners `json:"allowedListeners"` ... } @@ -75,7 +76,7 @@ type ListenerSetSpec struct { ParentRef ParentGatewayReference `json:"parentRefs,omitempty"` // Listeners associated with this ListenerSet. Listeners define - // logical endpoints that are bound on this referenced parent Gateway's addresses. + // logical endpoints that are bound on this referenced parent Gateway's addresses. // // At least one Listener MUST be specified. // @@ -131,14 +132,6 @@ type ParentGatewayReference struct { // Name is the name of the referent. Name ObjectName `json:"name"` - - // Namespace is the namespace of the referenced object. When unspecified, the local - // namespace is inferred. - // - // Support: Core - // - // +optional - Namespace *Namespace `json:"namespace,omitempty"` } ``` @@ -186,6 +179,8 @@ apiVersion: gateway.networking.k8s.io/v1alpha1 kind: ListenerSet metadata: name: second-workload-listeners + labels: + gateway.networking.k8s.io/gateway.name: parent-gateway spec: parentRef: name: parent-gateway @@ -404,5 +399,5 @@ Prior Discussions: - https://github.com/kubernetes-sigs/gateway-api/discussions/1248 - https://github.com/kubernetes-sigs/gateway-api/discussions/1246 -Gateway Hiearchy Brainstorming +Gateway Hierarchy Brainstorming - https://docs.google.com/document/d/1qj7Xog2t2fWRuzOeTsWkabUaVeOF7_2t_7appe8EXwA/edit From 72b6b1ea5bcd55378a65a85d1f4af5b51da2cb4f Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Mon, 29 Jul 2024 22:20:46 -0400 Subject: [PATCH 03/40] Drop section highlighting failure cases we can't handle --- geps/gep-1713/index.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index fff38a0012..bb542ce68f 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -346,11 +346,6 @@ For example, if I have a `Gateway` named `parent`, and two `ListenerSets` named When reporting status of a child, an implementation SHOULD be cautious about what information from the parent or siblings are reported to avoid accidentally leaking sensitive information that the child would not otherwise have access to. -TBD: The following situations aren't possible to handle since there's no 'gatewayClass' on the `ListenerSet` -* If `child-1` references a parent that doesn't exist then `child-1` will report `Accepted=False` -* If `child-1` references itself then `child-1` will report `Accepted=False` -* If `child-1` and `parent` have different gatewayClassNames then `child-1` will report `Accepted=False` - #### Policy Attachment Policies attached to a parent `Gateway` apply to both the parent and all `ListenerSet` listeners. From bb40ff66770aef265db0adc6cb93945ece36ee6c Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Mon, 29 Jul 2024 22:26:02 -0400 Subject: [PATCH 04/40] add enum validation --- geps/gep-1713/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index bb542ce68f..32a13bcc61 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -55,6 +55,7 @@ type ListenerNamespaces struct { // // +optional // +kubebuilder:default=Same + // +kubebuilder:validation:Enum=Same;None From *FromNamespaces `json:"from,omitempty"` } From 9baad11ba5aa3e3dab0395b336187b63bc238804 Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Mon, 29 Jul 2024 23:09:30 -0400 Subject: [PATCH 05/40] Describe the 'meta' details about this feature --- geps/gep-1713/index.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 32a13bcc61..98900ab78e 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -26,6 +26,12 @@ More broadly, large scale gateway users often expose `O(1000)` domains, but are The spec currently has language to indicate implementations `MAY` merge `Gateways` resources but the mechanic isn't defined. https://github.com/kubernetes-sigs/gateway-api/blob/541e9fc2b3c2f62915cb58dc0ee5e43e4096b3e2/apis/v1beta1/gateway_types.go#L76-L78 +## Feature Details + +We define `ListenerSet` as the name of the feature outlined in this GEP. +The feature will be part of the experimental branches as an extended feature, which implementations can choose to support. At that time, all the requirements in this document that use MUST apply to their implementation of the feature. + + ## API This proposal introduces a new `ListenerSet` resource that has the ability to attach to a set of listeners to a parent `Gateway`. From 41b1b21209ad9d8d1d4915f4828063ef698c333b Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Mon, 29 Jul 2024 23:34:31 -0400 Subject: [PATCH 06/40] attaching to the Gateway's sectionName but through the ListenerSet kind is not allowed --- geps/gep-1713/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 98900ab78e..235350936a 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -260,7 +260,7 @@ spec: sectionName: second ``` -For instance, the following `HTTPRoute` attemps to attach to a listener defined in the parent `Gateway`. This is not valid and the route's status should reflect that. +For instance, the following `HTTPRoute` attemps to attach to a listener defined in the parent `Gateway` using the sectionName `foo`. This is not valid and the route's status should reflect that. ```yaml apiVersion: gateway.networking.k8s.io/v1beta1 From e221a16389babbe4fa0e28433f734526a604faf5 Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Tue, 30 Jul 2024 14:00:14 -0400 Subject: [PATCH 07/40] ListenerSet can have multiple parents --- geps/gep-1713/index.md | 43 +++++++++++------------------------------- 1 file changed, 11 insertions(+), 32 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 235350936a..edf4757991 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -34,7 +34,7 @@ The feature will be part of the experimental branches as an extended feature, wh ## API -This proposal introduces a new `ListenerSet` resource that has the ability to attach to a set of listeners to a parent `Gateway`. +This proposal introduces a new `ListenerSet` resource that has the ability to attach to a set of listeners to multiple parent `Gateways`. #### Go @@ -67,7 +67,7 @@ type ListenerNamespaces struct { // ListenerSet defines a set of additional listeners to attach to an existing Gateway. type ListenerSet struct { - metav1.TypeMeta `json:",inline"` + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` // Spec defines the desired state of ListenerSet. @@ -79,11 +79,11 @@ type ListenerSet struct { // ListenerSetSpec defines the desired state of a ListenerSet. type ListenerSetSpec struct { - // ParentRef references the Gateway that the listeners are attached to. - ParentRef ParentGatewayReference `json:"parentRefs,omitempty"` + // ParentRefs references the Gateway that the listeners are attached to. + ParentRefs []ParentGatewayReference `json:"parentRefs,omitempty"` - // Listeners associated with this ListenerSet. Listeners define - // logical endpoints that are bound on this referenced parent Gateway's addresses. + // Listeners associated with this ListenerSet. Listeners define + // logical endpoints that are bound on this referenced parent Gateway's addresses. // // At least one Listener MUST be specified. // @@ -93,7 +93,7 @@ type ListenerSetSpec struct { // ListenerSetStatus defines the observed state of ListenerSet. type ListenerSetStatus struct { - // Listeners provide status for each unique listener port defined in the Spec. + // Listeners provide status for each unique listener port defined in the Spec. // // +optional // +listType=map @@ -163,11 +163,9 @@ apiVersion: gateway.networking.k8s.io/v1alpha1 kind: ListenerSet metadata: name: first-workload-listeners - labels: - gateway.networking.k8s.io/gateway.name: parent-gateway spec: - parentRef: - name: parent-gateway + parentRefs: + - name: parent-gateway kind: Gateway group: gateway.networking.k8s.io listeners: @@ -186,11 +184,9 @@ apiVersion: gateway.networking.k8s.io/v1alpha1 kind: ListenerSet metadata: name: second-workload-listeners - labels: - gateway.networking.k8s.io/gateway.name: parent-gateway spec: - parentRef: - name: parent-gateway + parentRefs: + - name: parent-gateway kind: Gateway group: gateway.networking.k8s.io listeners: @@ -221,23 +217,6 @@ spec: - from: None ``` -#### Listeners - -#### `ListenerSet.spec.parentRef` is immutable - -A `ListenerSet` `MUST` be created with a `parentRef` Updating the `parentRef` of a ListenerSet `MUST` be rejected by the API. - -#### `ListenerSet` Default Labels - -In order for clients of the API to easily discover `Gateways` and their `ListenerSets` we propose a set of labels to be defaulted when creating `ListenerSets`. This only applies if the `parentRef.kind` is a `Gateway` - -- `gateway.networking.k8s.io/gateway.name` is equal to `spec.parentRef.name` -- `gateway.networking.k8s.io/gateway.namespace` is equal to `spec.parentRef.namespace` - -This allows clients to perform API [lookups](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#list-and-watch-filtering) using label selectors. - -TBD: Can conditional defaulting be done with CEL? - #### GatewaySpec.Listeners MinItems TBD: Do we want to make this change? From 67ec44f6d08d1600ad2bd1668d8fac8366fce27b Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Tue, 30 Jul 2024 14:24:11 -0400 Subject: [PATCH 08/40] Allow multiple parentRefs and adjust language around PolicyAttachment --- geps/gep-1713/index.md | 65 ++++++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index edf4757991..478f16f160 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -17,8 +17,8 @@ The `Gateway` Resource is a point of contention since it is the only place to at ## Introduction -Knative generates on demand per-service certificates using HTTP-01 challenges. -There can be O(1000) Knative `Services` in the cluster which means we have O(1000) distinct certificates. +Knative generates on demand per-service certificates using HTTP-01 challenges. +There can be O(1000) Knative `Services` in the cluster which means we have O(1000) distinct certificates. Thus updating a single `Gateway` resource with this many certificates is a contention point and inhibits horizontal scaling of our controllers. More broadly, large scale gateway users often expose `O(1000)` domains, but are currently limited by the maximum of 64 `listeners`. @@ -40,15 +40,15 @@ This proposal introduces a new `ListenerSet` resource that has the ability to at ```go type GatewaySpec struct { - ... - // Note: this is a list to allow future potential features - AllowedListeners []*AllowedListeners `json:"allowedListeners"` - ... + ... + // Note: this is a list to allow future potential features + AllowedListeners []*AllowedListeners `json:"allowedListeners"` + ... } type AllowedListeners struct { - // +kubebuilder:default={from: Same} - Namespaces *ListenerNamespaces `json:"namespaces,omitempty"` + // +kubebuilder:default={from: Same} + Namespaces *ListenerNamespaces `json:"namespaces,omitempty"` } // ListenerNamespaces indicate which namespaces ListenerSets should be selected from. @@ -65,11 +65,11 @@ type ListenerNamespaces struct { From *FromNamespaces `json:"from,omitempty"` } -// ListenerSet defines a set of additional listeners to attach to an existing Gateway. +// ListenerSet defines a set of additional listeners to attach to an existing Gateway. type ListenerSet struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - + // Spec defines the desired state of ListenerSet. Spec ListenerSetSpec `json:"spec"` @@ -80,19 +80,39 @@ type ListenerSet struct { // ListenerSetSpec defines the desired state of a ListenerSet. type ListenerSetSpec struct { // ParentRefs references the Gateway that the listeners are attached to. + // + // +kubebuilder:validation:MaxItems=32 ParentRefs []ParentGatewayReference `json:"parentRefs,omitempty"` - + // Listeners associated with this ListenerSet. Listeners define // logical endpoints that are bound on this referenced parent Gateway's addresses. // // At least one Listener MUST be specified. // // Note: this is the same Listener type in the GatewaySpec struct - Listeners []Listener + Listeners []Listener } -// ListenerSetStatus defines the observed state of ListenerSet. +// ListenerSetStatus defines the observed state of a ListenerSet type ListenerSetStatus struct { + // Parents is a list of parent resources (usually Gateways) that are + // associated with the route, and the status of the route with respect to + // each parent. When this route attaches to a parent, the controller that + // manages the parent must add an entry to this list when the controller + // first sees the route and should update the entry as appropriate when the + // route or gateway is modified. + // + // +kubebuilder:validation:MaxItems=32 + Parents []ListenerSetParentStatus `json:"parents"` +} + +// ListenerSetParentStatus defines the observed state of ListenerSet with +// to an associated Parent. +type ListenerSetParentStatus struct { + // ParentRef corresponds with a ParentRef in the spec that this + // RouteParentStatus struct describes the status of. + ParentRef ParentGatewayReference `json:"parentRef"` + // Listeners provide status for each unique listener port defined in the Spec. // // +optional @@ -102,7 +122,7 @@ type ListenerSetStatus struct { // // Note: this is the same ListenerStatus type in the GatewayStatus struct Listeners []ListenerStatus `json:"listeners,omitempty"` - + // Conditions describe the current conditions of the ListenerSet. // // Implementations should prefer to express ListenerSet conditions @@ -144,7 +164,7 @@ type ParentGatewayReference struct { #### YAML -The following example shows a `Gateway` with an HTTP listener and two child HTTPS `ListenerSets` with unique hostnames and certificates. +The following example shows a `Gateway` with an HTTP listener and two child HTTPS `ListenerSets` with unique hostnames and certificates. ```yaml apiVersion: gateway.networking.k8s.io/v1 @@ -255,7 +275,7 @@ spec: #### Listener Validation -Implementations MUST treat the parent `Gateway` as having the concatenated list of all listeners from itself and attached `ListenerSets` +Implementations MUST treat the parent `Gateway`s as having the concatenated list of all listeners from itself and attached `ListenerSets` Validation of this list of listeners MUST behave the same as if the list were part of a single `Gateway`. From the earlier example the above resources would be equivalent to a single `Gateway` where the listeners are collapsed into a single list. @@ -301,14 +321,14 @@ Listeners should be merged using the following precedence: 2. ListenerSet ordered by creation time (oldest first) 3. ListenerSet ordered alphabetically by “{namespace}/{name}”. -If there are listener conflicts, this should be reported as `Conflicted=True` in the ListenerStatus as usual. See 'Conditions' section below for more details on object should report the conflict. +If there are listener conflicts, this should be reported as `Conflicted=True` in the `ListenerSetParentStatus` as usual. See 'Conditions' section below for more details on object should report the conflict. ### Gateway Conditions `Gateway` currently supports the following top-level condition types: `Accepted` and `Programmed` For a `Gateway`, `Accepted` should be set based on the entire set of merged listeners. -For instance, if a `ListenerSet` listener is invalid, `ListenersNotValid` would be reported. +For instance, if a `ListenerSet` listener is invalid, `ListenersNotValid` would be reported. `Programmed` is not expected, generally, to depend on the children resources, but if an implementation does depend on these they should consider child resources when reporting this status. @@ -318,7 +338,7 @@ It is up to the implementation whether an invalid listener affects other listene ### ListenerSet Conditions -`ListenerSets` MUST NOT have their parent `Gateway`'s' listeners in the `status.listeners` conditions list. An implementation MAY reject listeners with `ListenerConditionAccepted=False` and Reason `TooManyListeners` `ListenerSets`, like a `Gateway`, also have two top-level conditions: `Accepted` and `Programmed`. These conditions, when surfacing details about listeners, MUST only summarize the `status.listener` conditions that are exclusive to the `ListenerSet`. +`ListenerSets` MUST NOT have their parent `Gateway`'s' listeners in the associated `status.parents.listeners` conditions list. An implementation MAY reject listeners with `ListenerConditionAccepted=False` and Reason `TooManyListeners` `ListenerSets`, like a `Gateway`, also have two top-level conditions: `Accepted` and `Programmed`. These conditions, when surfacing details about listeners, MUST only summarize the `status.listener` conditions that are exclusive to the `ListenerSet`. These conditions MUST also surface top-level `Gateway` conditions that impact the `ListenerSet`. For example, if a `Gateway` requests an invalid address and it cannot be accepted/programmed then the `ListenerSet`'s' `Accepted` condition MUST be set to `False`. @@ -326,7 +346,7 @@ For example, if I have a `Gateway` named `parent`, and two `ListenerSets` named * If `parent` is entirely invalid (for example, an invalid `address`) and `Accepted=False`, all two `ListenerSets` will reported `Accepted=False`. * If `child-1` has an invalid listener, `parent` and `child-1` will report `ListenersNotValid`, while `child-2` will not. * If `child-1` references a parent that doesn't allow merging then `child-1` will report `Accepted=False` -* If `child-1` references another child (eg. `child-2`) then `child-1` will report `Accepted=False` +* If `child-1` references another child (eg. `child-2`) then `child-1` will report `Accepted=False` * If `child-1` is valid, then when `child-2` is created if it conflicts with `child-1` then `child-2` will report `Accepted=False`. `child-1` status conditions will remain unchanged. `parent` will report `ListenersNotValid` When reporting status of a child, an implementation SHOULD be cautious about what information from the parent or siblings are reported @@ -334,9 +354,10 @@ to avoid accidentally leaking sensitive information that the child would not oth #### Policy Attachment -Policies attached to a parent `Gateway` apply to both the parent and all `ListenerSet` listeners. +Policy attachment is [under discussion] in https://github.com/kubernetes-sigs/gateway-api/discussions/2927 -Policies that attach to a `ListenerSet` apply to all listeners defined in that resource, but do not impact listeners in the parent `Gateway` +Similar to Routes, `ListenerSet` can inherit policy from a Gateway. +Policies that attach to a `ListenerSet` apply to all listeners defined in that resource, but do not impact listeners in the parent `Gateway`. This allows `ListenerSets` attached to the same `Gateway` to have different policies. If the implementation cannot apply the policy to only specific listeners, it should reject the policy. ## Alternatives From 228a4f85b7499edc2d47f505517871cf91bca2a5 Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Tue, 30 Jul 2024 14:54:30 -0400 Subject: [PATCH 09/40] clarify which section has listener ordering --- geps/gep-1713/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 478f16f160..031c18ded9 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -275,7 +275,7 @@ spec: #### Listener Validation -Implementations MUST treat the parent `Gateway`s as having the concatenated list of all listeners from itself and attached `ListenerSets` +Implementations MUST treat the parent `Gateway`s as having the concatenated list of all listeners from itself and attached `ListenerSets`. See 'Listener Precedence' for more details on ordering. Validation of this list of listeners MUST behave the same as if the list were part of a single `Gateway`. From the earlier example the above resources would be equivalent to a single `Gateway` where the listeners are collapsed into a single list. From 4ff2eb08cc977930fa4196fe418330325663c81d Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Tue, 30 Jul 2024 17:30:35 -0400 Subject: [PATCH 10/40] fix heading levels --- geps/gep-1713/index.md | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 031c18ded9..ea7afe6722 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -36,7 +36,7 @@ The feature will be part of the experimental branches as an extended feature, wh This proposal introduces a new `ListenerSet` resource that has the ability to attach to a set of listeners to multiple parent `Gateways`. -#### Go +### Go ```go type GatewaySpec struct { @@ -162,7 +162,7 @@ type ParentGatewayReference struct { } ``` -#### YAML +### YAML The following example shows a `Gateway` with an HTTP listener and two child HTTPS `ListenerSets` with unique hostnames and certificates. @@ -221,9 +221,9 @@ spec: group: "" name: second-workload-cert # Provisioned via HTTP01 challenge ``` -### Semantics +## Semantics -#### Gateway <> ListenerSet Handshake +### Gateway <> ListenerSet Handshake By default a `Gateway` will allow `ListenerSets` in the same namespace to be attached. Users can prevent this behaviour by configuring their `Gateway` to disallow any listener attachment: @@ -237,13 +237,14 @@ spec: - from: None ``` -#### GatewaySpec.Listeners MinItems +### GatewaySpec.Listeners MinItems TBD: Do we want to make this change? Currently when creating a Gateway you must specify at least a single listener. With `ListenerSets` this opens the possibility of wanting to create a Gateway with no listeners. -#### Route Attaching + +### Route Attaching Routes MUST be able to specify a `ListenerSet` as a `parentRef` and make use of the `sectionName` field in `ParentReference` to help target a specific listener. If no listener is targeted (`sectionName`/`port` are unset) then the Route references all the listeners on the `ListenerSet`. It `MUST NOT` attach to additional listeners on the parent `Gateway`. @@ -273,7 +274,7 @@ spec: sectionName: foo ``` -#### Listener Validation +### Listener Validation Implementations MUST treat the parent `Gateway`s as having the concatenated list of all listeners from itself and attached `ListenerSets`. See 'Listener Precedence' for more details on ordering. Validation of this list of listeners MUST behave the same as if the list were part of a single `Gateway`. @@ -314,7 +315,7 @@ spec: name: second-workload-cert # Provisioned via HTTP01 challenge ``` -#### Listener Precedence +### Listener Precedence Listeners should be merged using the following precedence: 1. "parent" Gateway @@ -352,7 +353,7 @@ For example, if I have a `Gateway` named `parent`, and two `ListenerSets` named When reporting status of a child, an implementation SHOULD be cautious about what information from the parent or siblings are reported to avoid accidentally leaking sensitive information that the child would not otherwise have access to. -#### Policy Attachment +### Policy Attachment Policy attachment is [under discussion] in https://github.com/kubernetes-sigs/gateway-api/discussions/2927 @@ -362,28 +363,28 @@ If the implementation cannot apply the policy to only specific listeners, it sho ## Alternatives -#### Re-using Gateway Resource +### Re-using Gateway Resource The [first iteration of this GEP](https://github.com/kubernetes-sigs/gateway-api/pull/1863) proposed re-using the `Gateway` resource and introducing an `attachTo` property in the `infrastructure` stanza. The main downside of this approach is that users still require `Gateway` write access to create listeners. Secondly, it introduces complexity to future `Gateway` features as GEP authors would have now have to account for merging semantics. -#### New 'GatewayGroup' Resource +### New 'GatewayGroup' Resource This was proposed in the Gateway Hiearchy Brainstorming document (see references below). The idea is to introduce a central resource that will coalease Gateways together and offer forms of delegation. Issues with this is complexity with status propagation, cluster vs. namespace scoping etc. It also lacks a migration path for existing Gateways to help shard listeners. -#### Use of Multiple Disjointed Gateways +### Use of Multiple Disjointed Gateways An alternative would be to encourage users to not use overly large Gateways to minimize the blast radius of any issues. Use of disjoint Gateways could accomplish this but it has the disadvantage of consuming more resources and introducing complexity when it comes to operations work (eg. setting up DNS records etc.) -#### Increase the Listener Limit +### Increase the Listener Limit Increasing the limit may help in situations where you are creating many listeners such as adding certificates created using an ACME HTTP01 challenge. Unfortunately this still makes the Gateway a single point of contention. Unfortunately, there will always be an upper bound because of etcd limitations. For workloads like Knative we can have O(1000) Services on the cluster with unique subdomains. -#### Expand Route Functionality +### Expand Route Functionality For workloads with many certificates one option would be to introduce a `tls` stanza somewhere in the Route types. These Routes would then attach to a single Gateway. Then application operators can provide their own certificates. This probably would require some ability to have a handshake agreement with the Gateway. From 879c01123908c4387cbd3cd91744f046973aac31 Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Tue, 30 Jul 2024 17:53:25 -0400 Subject: [PATCH 11/40] allow no listeners on the Gateway spec --- geps/gep-1713/index.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index ea7afe6722..dff7aa4e62 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -223,6 +223,13 @@ spec: ``` ## Semantics +### Gateway Changes + +When an implementation supports `ListenerSets` `Gateways` MUST allow the list of listeners to be empty. Thus the present `minItems=1` constraint on the listener list will be removed. This allows implementations to avoid security, cost etc. concerns with having dummy listeners. +When there are no listeners the `Gateway`'s `status.listeners` should be empty or unset. `status.listeners` is already an optional field. + +Implementations, when creating a `Gateway`, may provision underlying infrastructure when there are no listeners present. The status conditions `Accepted` and `Programmed` conditions should reflect state of this provisioning. + ### Gateway <> ListenerSet Handshake By default a `Gateway` will allow `ListenerSets` in the same namespace to be attached. Users can prevent this behaviour by configuring their `Gateway` to disallow any listener attachment: @@ -237,13 +244,6 @@ spec: - from: None ``` -### GatewaySpec.Listeners MinItems - -TBD: Do we want to make this change? - -Currently when creating a Gateway you must specify at least a single listener. With `ListenerSets` this opens the possibility of wanting to create a Gateway with no listeners. - - ### Route Attaching Routes MUST be able to specify a `ListenerSet` as a `parentRef` and make use of the `sectionName` field in `ParentReference` to help target a specific listener. If no listener is targeted (`sectionName`/`port` are unset) then the Route references all the listeners on the `ListenerSet`. It `MUST NOT` attach to additional listeners on the parent `Gateway`. From dd175c664516321adc5f02578732186471e34887 Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Tue, 30 Jul 2024 17:58:25 -0400 Subject: [PATCH 12/40] add back istio use case --- geps/gep-1713/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index dff7aa4e62..b14f5a1651 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -20,6 +20,7 @@ The `Gateway` Resource is a point of contention since it is the only place to at Knative generates on demand per-service certificates using HTTP-01 challenges. There can be O(1000) Knative `Services` in the cluster which means we have O(1000) distinct certificates. Thus updating a single `Gateway` resource with this many certificates is a contention point and inhibits horizontal scaling of our controllers. +[Istio Ambient](https://istio.io/v1.15/blog/2022/introducing-ambient-mesh/), similarly, creates a listener per Kubernetes service. More broadly, large scale gateway users often expose `O(1000)` domains, but are currently limited by the maximum of 64 `listeners`. From 6890bc3f84c883b0c74b1a1c642df5272a9b163e Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Tue, 30 Jul 2024 18:36:18 -0400 Subject: [PATCH 13/40] update gateway conditions paragraph --- geps/gep-1713/index.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index b14f5a1651..a5813e0638 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -226,7 +226,7 @@ spec: ### Gateway Changes -When an implementation supports `ListenerSets` `Gateways` MUST allow the list of listeners to be empty. Thus the present `minItems=1` constraint on the listener list will be removed. This allows implementations to avoid security, cost etc. concerns with having dummy listeners. +When an implementation supports `ListenerSets` `Gateways` MUST allow the list of listeners to be empty. Thus the present `minItems=1` constraint on the listener list will be removed. This allows implementations to avoid security, cost etc. concerns with having dummy listeners. When there are no listeners the `Gateway`'s `status.listeners` should be empty or unset. `status.listeners` is already an optional field. Implementations, when creating a `Gateway`, may provision underlying infrastructure when there are no listeners present. The status conditions `Accepted` and `Programmed` conditions should reflect state of this provisioning. @@ -327,14 +327,16 @@ If there are listener conflicts, this should be reported as `Conflicted=True` in ### Gateway Conditions -`Gateway` currently supports the following top-level condition types: `Accepted` and `Programmed` +`Gateway`'s `Accepted` and `Programmed` top-level conditions remain unchanged and reflect the status of the local configuration. -For a `Gateway`, `Accepted` should be set based on the entire set of merged listeners. -For instance, if a `ListenerSet` listener is invalid, `ListenersNotValid` would be reported. -`Programmed` is not expected, generally, to depend on the children resources, but if an implementation does depend on these -they should consider child resources when reporting this status. +Implementations MUST support a new condition type `AttachedListeners`. -Parent gateways MUST NOT have `ListenerSet` listeners in their `status.listeners` conditions list. +The condition's `Status` has the following values: +- `True` when `AllowedListeners` is set and at least one child Listener arrives from a `ListenerSet` +- `False` when `AllowedListeners` is set but has no valid listeners are attached +- `Unknown` when no `AllowedListeners` config is present + +Parent `Gateways` MUST NOT have `ListenerSet` listeners in their `status.listeners` conditions list. It is up to the implementation whether an invalid listener affects other listeners in the Gateway. From 460576f7c95cd41c18825432af765cb7f1e3e8fb Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Tue, 30 Jul 2024 18:40:50 -0400 Subject: [PATCH 14/40] don't say concatenate --- geps/gep-1713/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index a5813e0638..9d953a4b53 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -277,7 +277,7 @@ spec: ### Listener Validation -Implementations MUST treat the parent `Gateway`s as having the concatenated list of all listeners from itself and attached `ListenerSets`. See 'Listener Precedence' for more details on ordering. +Implementations MUST treat the parent `Gateway`s as having the merged list of all listeners from itself and attached `ListenerSets`. See 'Listener Precedence' for more details on ordering. Validation of this list of listeners MUST behave the same as if the list were part of a single `Gateway`. From the earlier example the above resources would be equivalent to a single `Gateway` where the listeners are collapsed into a single list. From a46a00164d30d81bbd04940c0f81f2ddd9d7ff75 Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Tue, 30 Jul 2024 19:33:29 -0400 Subject: [PATCH 15/40] drop clause saying invalid listeners affects other listeners --- geps/gep-1713/index.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 9d953a4b53..e7eb4ba3e7 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -338,8 +338,6 @@ The condition's `Status` has the following values: Parent `Gateways` MUST NOT have `ListenerSet` listeners in their `status.listeners` conditions list. -It is up to the implementation whether an invalid listener affects other listeners in the Gateway. - ### ListenerSet Conditions `ListenerSets` MUST NOT have their parent `Gateway`'s' listeners in the associated `status.parents.listeners` conditions list. An implementation MAY reject listeners with `ListenerConditionAccepted=False` and Reason `TooManyListeners` `ListenerSets`, like a `Gateway`, also have two top-level conditions: `Accepted` and `Programmed`. These conditions, when surfacing details about listeners, MUST only summarize the `status.listener` conditions that are exclusive to the `ListenerSet`. From 70261a180dd2036036cd01eeb394e224586feeab Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Tue, 30 Jul 2024 19:54:33 -0400 Subject: [PATCH 16/40] clarify route attachment --- geps/gep-1713/index.md | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index e7eb4ba3e7..e5a1941842 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -247,8 +247,9 @@ spec: ### Route Attaching -Routes MUST be able to specify a `ListenerSet` as a `parentRef` and make use of the `sectionName` field in `ParentReference` to help target a specific listener. If no listener is targeted (`sectionName`/`port` are unset) then the Route references all the listeners on the `ListenerSet`. It `MUST NOT` attach to additional listeners on the parent `Gateway`. +Routes MUST be able to specify a `ListenerSet` as a `parentRef`. Routes can use `sectionName`/`port` fields in `ParentReference` to help target a specific listener. If no listener is targeted (`sectionName`/`port` are unset) then the Route attaches to all the listeners on the `ListenerSet` and it `MUST NOT` attach to any listeners in the `ListenerSet`'s parent `Gateways`. +eg. ```yaml apiVersion: gateway.networking.k8s.io/v1beta1 kind: HTTPRoute @@ -261,7 +262,7 @@ spec: sectionName: second ``` -For instance, the following `HTTPRoute` attemps to attach to a listener defined in the parent `Gateway` using the sectionName `foo`. This is not valid and the route's status should reflect that. +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 should reflect that. ```yaml apiVersion: gateway.networking.k8s.io/v1beta1 @@ -275,6 +276,22 @@ spec: sectionName: foo ``` +To attach to listeners in both a `Gateway` and `ListenerSet` the route must have two `parentRefs`: +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: httproute-example +spec: + parentRefs: + - name: second-workload-listeners + kind: ListenerSet + sectionName: second + - name: parent-gateway + kind: Gateway + sectionName: foo +``` + ### Listener Validation Implementations MUST treat the parent `Gateway`s as having the merged list of all listeners from itself and attached `ListenerSets`. See 'Listener Precedence' for more details on ordering. From aa382cc2bc8f53f5dbbdc337aa1e0c359d42f5b4 Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Tue, 30 Jul 2024 20:37:39 -0400 Subject: [PATCH 17/40] split listenersetconditions into two sections: top-level and listenerstatus --- geps/gep-1713/index.md | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index e5a1941842..3e032cac07 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -357,19 +357,26 @@ Parent `Gateways` MUST NOT have `ListenerSet` listeners in their `status.listene ### ListenerSet Conditions -`ListenerSets` MUST NOT have their parent `Gateway`'s' listeners in the associated `status.parents.listeners` conditions list. An implementation MAY reject listeners with `ListenerConditionAccepted=False` and Reason `TooManyListeners` `ListenerSets`, like a `Gateway`, also have two top-level conditions: `Accepted` and `Programmed`. These conditions, when surfacing details about listeners, MUST only summarize the `status.listener` conditions that are exclusive to the `ListenerSet`. +`ListenerSets` have a top-level `Accepted` and `Programmed` conditions. -These conditions MUST also surface top-level `Gateway` conditions that impact the `ListenerSet`. For example, if a `Gateway` requests an invalid address and it cannot be accepted/programmed then the `ListenerSet`'s' `Accepted` condition MUST be set to `False`. +The `Accepted` condition MUST be set on every `ListenerSet`, and indicates that the `ListenerSet` is semantically valid and accepted by its `parentRefs`. -For example, if I have a `Gateway` named `parent`, and two `ListenerSets` named `child-1`, and `child-2` then: -* If `parent` is entirely invalid (for example, an invalid `address`) and `Accepted=False`, all two `ListenerSets` will reported `Accepted=False`. -* If `child-1` has an invalid listener, `parent` and `child-1` will report `ListenersNotValid`, while `child-2` will not. -* If `child-1` references a parent that doesn't allow merging then `child-1` will report `Accepted=False` -* If `child-1` references another child (eg. `child-2`) then `child-1` will report `Accepted=False` -* If `child-1` is valid, then when `child-2` is created if it conflicts with `child-1` then `child-2` will report `Accepted=False`. `child-1` status conditions will remain unchanged. `parent` will report `ListenersNotValid` +Valid reasons for `Accepted` being `False` are: +- `NotAllowed` - the `parentRef` doesn't allow attachment +- `ParentNotAccepted` - the `parentRef` isn't accepted (eg. invalid address) +- `UnsupportedValue` - a listener in the set is using an unsupported feature/value -When reporting status of a child, an implementation SHOULD be cautious about what information from the parent or siblings are reported -to avoid accidentally leaking sensitive information that the child would not otherwise have access to. +The `Programmed` condition MUST be set on every `ListenerSet` and have a similar meaning to the Gateway `Programmed` condition but only reflect the listeners in this `ListenerSet`. + +`Accepted` and `Programmed` conditions when surfacing details about listeners, MUST only summarize the `status.parents.listeners` conditions that are exclusive to the `ListenerSet`. + +`ListenerSets` MUST NOT have their parent `Gateway`'s' listeners in the associated `status.parents.listeners` conditions list. + +### ListenerSetStatus.Parents.ListenerConditions + +An implementation MAY reject listeners by setting the ListenerStatus `Accepted` condition to `False` with the `Reason` `TooManyListeners` + +Implementation SHOULD be cautious about what information from the parent or siblings are reported to avoid accidentally leaking sensitive information that the child would not otherwise have access to. ### Policy Attachment From 32fc59f7e89f24eaf9e1cb0380f8cba1f83ac71a Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Tue, 30 Jul 2024 20:47:07 -0400 Subject: [PATCH 18/40] clarify where the conflicted condition is set --- geps/gep-1713/index.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 3e032cac07..ce2432549a 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -340,7 +340,7 @@ Listeners should be merged using the following precedence: 2. ListenerSet ordered by creation time (oldest first) 3. ListenerSet ordered alphabetically by “{namespace}/{name}”. -If there are listener conflicts, this should be reported as `Conflicted=True` in the `ListenerSetParentStatus` as usual. See 'Conditions' section below for more details on object should report the conflict. +Conflicts are covered in the section 'ListenerConditions within a ListenerSet' ### Gateway Conditions @@ -372,9 +372,11 @@ The `Programmed` condition MUST be set on every `ListenerSet` and have a similar `ListenerSets` MUST NOT have their parent `Gateway`'s' listeners in the associated `status.parents.listeners` conditions list. -### ListenerSetStatus.Parents.ListenerConditions +### ListenerConditions within a ListenerSet -An implementation MAY reject listeners by setting the ListenerStatus `Accepted` condition to `False` with the `Reason` `TooManyListeners` +An implementation MAY reject listeners by setting the `ListenerStatus` `Accepted` condition to `False` with the `Reason` `TooManyListeners` + +If a listener has a conflict, this should be reported in the `ListenerStatus` of the conflicted `ListenerSet` by setting the `Conflicted` condition to `True`. Implementation SHOULD be cautious about what information from the parent or siblings are reported to avoid accidentally leaking sensitive information that the child would not otherwise have access to. From 46dbf4e3e36570ecbe52f87be38d701cb053bc3d Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Thu, 1 Aug 2024 15:51:10 -0400 Subject: [PATCH 19/40] relabel introduction => use cases --- geps/gep-1713/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index ce2432549a..5aca554f96 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -5,7 +5,7 @@ (See status definitions [here](overview.md#status).) -## tl;dr +## Introduction The `Gateway` Resource is a point of contention since it is the only place to attach listeners with certificates. We propose a new resource called `ListenerSet` to allow a shared list of listeners to be attached to a single `Gateway`. @@ -15,7 +15,7 @@ The `Gateway` Resource is a point of contention since it is the only place to at ## Future Goals (Beyond the GEP) - Attaching listeners to `Gateways` in different namespaces -## Introduction +## Use Cases & Motivation Knative generates on demand per-service certificates using HTTP-01 challenges. There can be O(1000) Knative `Services` in the cluster which means we have O(1000) distinct certificates. From cf29a9a086bbbe46942b0237a61ec93fc2062edd Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Thu, 1 Aug 2024 15:57:15 -0400 Subject: [PATCH 20/40] limit parents to 2 and listeners to 16 --- geps/gep-1713/index.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 5aca554f96..a2c78921e4 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -82,15 +82,18 @@ type ListenerSet struct { type ListenerSetSpec struct { // ParentRefs references the Gateway that the listeners are attached to. // - // +kubebuilder:validation:MaxItems=32 + // +kubebuilder:validation:MaxItems=2 ParentRefs []ParentGatewayReference `json:"parentRefs,omitempty"` // Listeners associated with this ListenerSet. Listeners define // logical endpoints that are bound on this referenced parent Gateway's addresses. // - // At least one Listener MUST be specified. // // Note: this is the same Listener type in the GatewaySpec struct + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=16 Listeners []Listener } @@ -103,7 +106,7 @@ type ListenerSetStatus struct { // first sees the route and should update the entry as appropriate when the // route or gateway is modified. // - // +kubebuilder:validation:MaxItems=32 + // +kubebuilder:validation:MaxItems=2 Parents []ListenerSetParentStatus `json:"parents"` } @@ -119,7 +122,7 @@ type ListenerSetParentStatus struct { // +optional // +listType=map // +listMapKey=name - // +kubebuilder:validation:MaxItems=64 + // +kubebuilder:validation:MaxItems=16 // // Note: this is the same ListenerStatus type in the GatewayStatus struct Listeners []ListenerStatus `json:"listeners,omitempty"` From 9356e1c36e2030504526a366a44249c8e674a635 Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Thu, 1 Aug 2024 16:12:43 -0400 Subject: [PATCH 21/40] use separate listener and status types --- geps/gep-1713/index.md | 236 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 231 insertions(+), 5 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index a2c78921e4..f67c572f4f 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -89,12 +89,183 @@ type ListenerSetSpec struct { // logical endpoints that are bound on this referenced parent Gateway's addresses. // // - // Note: this is the same Listener type in the GatewaySpec struct // +listType=map // +listMapKey=name // +kubebuilder:validation:MinItems=1 // +kubebuilder:validation:MaxItems=16 - Listeners []Listener + Listeners []ListenerEntry +} +// ListenerEntry embodies the concept of a logical endpoint where a Gateway accepts +// network connections. +type ListenerEntry struct { + // Name is the name of the Listener. This name MUST be unique within a + // Gateway. + // + // Support: Core + Name SectionName `json:"name"` + + // Hostname specifies the virtual hostname to match for protocol types that + // define this concept. When unspecified, all hostnames are matched. This + // field is ignored for protocols that don't require hostname based + // matching. + // + // Implementations MUST apply Hostname matching appropriately for each of + // the following protocols: + // + // * TLS: The Listener Hostname MUST match the SNI. + // * HTTP: The Listener Hostname MUST match the Host header of the request. + // * HTTPS: The Listener Hostname SHOULD match at both the TLS and HTTP + // protocol layers as described above. If an implementation does not + // ensure that both the SNI and Host header match the Listener hostname, + // it MUST clearly document that. + // + // For HTTPRoute and TLSRoute resources, there is an interaction with the + // `spec.hostnames` array. When both listener and route specify hostnames, + // there MUST be an intersection between the values for a Route to be + // accepted. For more information, refer to the Route specific Hostnames + // documentation. + // + // Hostnames that are prefixed with a wildcard label (`*.`) are interpreted + // as a suffix match. That means that a match for `*.example.com` would match + // both `test.example.com`, and `foo.test.example.com`, but not `example.com`. + // + // Support: Core + // + // +optional + Hostname *Hostname `json:"hostname,omitempty"` + + // Port is the network port. Multiple listeners may use the + // same port, subject to the Listener compatibility rules. + // + // Support: Core + Port PortNumber `json:"port"` + + // Protocol specifies the network protocol this listener expects to receive. + // + // Support: Core + Protocol ProtocolType `json:"protocol"` + + // TLS is the TLS configuration for the Listener. This field is required if + // the Protocol field is "HTTPS" or "TLS". It is invalid to set this field + // if the Protocol field is "HTTP", "TCP", or "UDP". + // + // The association of SNIs to Certificate defined in GatewayTLSConfig is + // defined based on the Hostname field for this listener. + // + // The GatewayClass MUST use the longest matching SNI out of all + // available certificates for any TLS handshake. + // + // Support: Core + // + // +optional + TLS *ListenerSetTLSConfig `json:"tls,omitempty"` + + // AllowedRoutes defines the types of routes that MAY be attached to a + // Listener and the trusted namespaces where those Route resources MAY be + // present. + // + // Although a client request may match multiple route rules, only one rule + // may ultimately receive the request. Matching precedence MUST be + // determined in order of the following criteria: + // + // * The most specific match as defined by the Route type. + // * The oldest Route based on creation timestamp. For example, a Route with + // a creation timestamp of "2020-09-08 01:02:03" is given precedence over + // a Route with a creation timestamp of "2020-09-08 01:02:04". + // * If everything else is equivalent, the Route appearing first in + // alphabetical order (namespace/name) should be given precedence. For + // example, foo/bar is given precedence over foo/baz. + // + // All valid rules within a Route attached to this Listener should be + // implemented. Invalid Route rules can be ignored (sometimes that will mean + // the full Route). If a Route rule transitions from valid to invalid, + // support for that Route rule should be dropped to ensure consistency. For + // example, even if a filter specified by a Route rule is invalid, the rest + // of the rules within that Route should still be supported. + // + // Support: Core + // +kubebuilder:default={namespaces:{from: Same}} + // +optional + AllowedRoutes *AllowedRoutes `json:"allowedRoutes,omitempty"` +} + +// ListenerSetTLSConfig describes a TLS configuration. +// +// +kubebuilder:validation:XValidation:message="certificateRefs or options must be specified when mode is Terminate",rule="self.mode == 'Terminate' ? size(self.certificateRefs) > 0 || size(self.options) > 0 : true" +type ListenerSetTLSConfig struct { + // Mode defines the TLS behavior for the TLS session initiated by the client. + // There are two possible modes: + // + // - Terminate: The TLS session between the downstream client and the + // Gateway is terminated at the Gateway. This mode requires certificates + // to be specified in some way, such as populating the certificateRefs + // field. + // - Passthrough: The TLS session is NOT terminated by the Gateway. This + // implies that the Gateway can't decipher the TLS stream except for + // the ClientHello message of the TLS protocol. The certificateRefs field + // is ignored in this mode. + // + // Support: Core + // + // +optional + // +kubebuilder:default=Terminate + Mode *TLSModeType `json:"mode,omitempty"` + + // CertificateRefs contains a series of references to Kubernetes objects that + // contains TLS certificates and private keys. These certificates are used to + // establish a TLS handshake for requests that match the hostname of the + // associated listener. + // + // A single CertificateRef to a Kubernetes Secret has "Core" support. + // Implementations MAY choose to support attaching multiple certificates to + // a Listener, but this behavior is implementation-specific. + // + // References to a resource in different namespace are invalid UNLESS there + // is a ReferenceGrant in the target namespace that allows the certificate + // to be attached. If a ReferenceGrant does not allow this reference, the + // "ResolvedRefs" condition MUST be set to False for this listener with the + // "RefNotPermitted" reason. + // + // This field is required to have at least one element when the mode is set + // to "Terminate" (default) and is optional otherwise. + // + // CertificateRefs can reference to standard Kubernetes resources, i.e. + // Secret, or implementation-specific custom resources. + // + // Support: Core - A single reference to a Kubernetes Secret of type kubernetes.io/tls + // + // Support: Implementation-specific (More than one reference or other resource types) + // + // +optional + // +kubebuilder:validation:MaxItems=64 + CertificateRefs []SecretObjectReference `json:"certificateRefs,omitempty"` + + // FrontendValidation holds configuration information for validating the frontend (client). + // Setting this field will require clients to send a client certificate + // required for validation during the TLS handshake. In browsers this may result in a dialog appearing + // that requests a user to specify the client certificate. + // The maximum depth of a certificate chain accepted in verification is Implementation specific. + // + // Support: Extended + // + // +optional + // + FrontendValidation *FrontendTLSValidation `json:"frontendValidation,omitempty"` + + // Options are a list of key/value pairs to enable extended TLS + // configuration for each implementation. For example, configuring the + // minimum TLS version or supported cipher suites. + // + // A set of common keys MAY be defined by the API in the future. To avoid + // any ambiguity, implementation-specific definitions MUST use + // domain-prefixed names, such as `example.com/my-custom-option`. + // Un-prefixed names are reserved for key names defined by Gateway API. + // + // Support: Implementation-specific + // + // +optional + // +kubebuilder:validation:MaxProperties=16 + Options map[AnnotationKey]AnnotationValue `json:"options,omitempty"` } // ListenerSetStatus defines the observed state of a ListenerSet @@ -123,9 +294,7 @@ type ListenerSetParentStatus struct { // +listType=map // +listMapKey=name // +kubebuilder:validation:MaxItems=16 - // - // Note: this is the same ListenerStatus type in the GatewayStatus struct - Listeners []ListenerStatus `json:"listeners,omitempty"` + Listeners []ListenerEntryStatus `json:"listeners,omitempty"` // Conditions describe the current conditions of the ListenerSet. // @@ -146,6 +315,51 @@ type ListenerSetParentStatus struct { Conditions []metav1.Condition `json:"conditions,omitempty"` } +// ListenerEntryStatus is the status associated with a ListenerEntry. +type ListenerEntryStatus struct { + // Name is the name of the Listener that this status corresponds to. + Name SectionName `json:"name"` + + // SupportedKinds is the list indicating the Kinds supported by this + // listener. This MUST represent the kinds an implementation supports for + // that Listener configuration. + // + // If kinds are specified in Spec that are not supported, they MUST NOT + // appear in this list and an implementation MUST set the "ResolvedRefs" + // condition to "False" with the "InvalidRouteKinds" reason. If both valid + // and invalid Route kinds are specified, the implementation MUST + // reference the valid Route kinds that have been specified. + // + // +kubebuilder:validation:MaxItems=8 + SupportedKinds []RouteGroupKind `json:"supportedKinds"` + + // AttachedRoutes represents the total number of Routes that have been + // successfully attached to this Listener. + // + // Successful attachment of a Route to a Listener is based solely on the + // combination of the AllowedRoutes field on the corresponding Listener + // and the Route's ParentRefs field. A Route is successfully attached to + // a Listener when it is selected by the Listener's AllowedRoutes field + // AND the Route has a valid ParentRef selecting the whole Gateway + // resource or a specific Listener as a parent resource (more detail on + // attachment semantics can be found in the documentation on the various + // Route kinds ParentRefs fields). Listener or Route status does not impact + // successful attachment, i.e. the AttachedRoutes field count MUST be set + // for Listeners with condition Accepted: false and MUST count successfully + // attached Routes that may themselves have Accepted: false conditions. + // + // Uses for this field include troubleshooting Route attachment and + // measuring blast radius/impact of changes to a Listener. + AttachedRoutes int32 `json:"attachedRoutes"` + + // Conditions describe the current condition of this listener. + // + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MaxItems=8 + Conditions []metav1.Condition `json:"conditions"` +} + // ParentGatewayReference identifies an API object including its namespace, // defaulting to Gateway. type ParentGatewayReference struct { @@ -225,6 +439,18 @@ spec: group: "" name: second-workload-cert # Provisioned via HTTP01 challenge ``` +### ListenerEntry + +TBD: `ListenerEntry` is currently a copy of the `Listener` struct but we have the opportunity to make changes here. + +From robscott https://github.com/kubernetes-sigs/gateway-api/pull/3213#discussion_r1699248634: + +> Since this would be a new API, it could be worth exploring some potential regrets of Listeners: +> +> 1. Should we have made it easier to leave port empty or do port ranges? +> 2. Should we support multiple hostnames? +> 3. Are there any validations that we wish we'd tightened up? + ## Semantics ### Gateway Changes From 947af4f2f0f53a77d6ab2c5b75ff03ab52613e92 Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Thu, 1 Aug 2024 16:16:55 -0400 Subject: [PATCH 22/40] ListenerSet attachment is opt-in --- geps/gep-1713/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index f67c572f4f..d1754e9054 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -48,7 +48,7 @@ type GatewaySpec struct { } type AllowedListeners struct { - // +kubebuilder:default={from: Same} + // +kubebuilder:default={from: None} Namespaces *ListenerNamespaces `json:"namespaces,omitempty"` } @@ -462,7 +462,7 @@ Implementations, when creating a `Gateway`, may provision underlying infrastruct ### Gateway <> ListenerSet Handshake -By default a `Gateway` will allow `ListenerSets` in the same namespace to be attached. Users can prevent this behaviour by configuring their `Gateway` to disallow any listener attachment: +By default a `Gateway` MUST NOT allow `ListenerSets` to be attached. Users can enable this behaviour by configuring their `Gateway` to allow `ListenerSet` attachment: ``` apiVersion: gateway.networking.k8s.io/v1 @@ -471,7 +471,7 @@ metadata: name: parent-gateway spec: allowedListeners: - - from: None + - from: Same ``` ### Route Attaching From de19b266326470f72600c31ea6f334473b58ecac Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Thu, 1 Aug 2024 16:21:44 -0400 Subject: [PATCH 23/40] fix formatting --- geps/gep-1713/index.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index d1754e9054..944fa40cc2 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -516,7 +516,7 @@ spec: - name: second-workload-listeners kind: ListenerSet sectionName: second - - name: parent-gateway + - name: parent-gateway kind: Gateway sectionName: foo ``` @@ -565,6 +565,7 @@ spec: ### Listener Precedence Listeners should be merged using the following precedence: + 1. "parent" Gateway 2. ListenerSet ordered by creation time (oldest first) 3. ListenerSet ordered alphabetically by “{namespace}/{name}”. @@ -591,6 +592,7 @@ Parent `Gateways` MUST NOT have `ListenerSet` listeners in their `status.listene The `Accepted` condition MUST be set on every `ListenerSet`, and indicates that the `ListenerSet` is semantically valid and accepted by its `parentRefs`. Valid reasons for `Accepted` being `False` are: + - `NotAllowed` - the `parentRef` doesn't allow attachment - `ParentNotAccepted` - the `parentRef` isn't accepted (eg. invalid address) - `UnsupportedValue` - a listener in the set is using an unsupported feature/value From 6b8b753ecf9900cfb4deb77100931a1cd564a627 Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Thu, 1 Aug 2024 16:25:50 -0400 Subject: [PATCH 24/40] fix more formatting --- geps/gep-1713/index.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 944fa40cc2..b1b98bd7d8 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -579,6 +579,7 @@ Conflicts are covered in the section 'ListenerConditions within a ListenerSet' Implementations MUST support a new condition type `AttachedListeners`. The condition's `Status` has the following values: + - `True` when `AllowedListeners` is set and at least one child Listener arrives from a `ListenerSet` - `False` when `AllowedListeners` is set but has no valid listeners are attached - `Unknown` when no `AllowedListeners` config is present @@ -651,14 +652,18 @@ Sorta related there was a Route Delegation GEP (https://github.com/kubernetes-si ## References First Revision of the GEP + - https://github.com/kubernetes-sigs/gateway-api/pull/1863 Mentioned in Prior GEPs: + - https://github.com/kubernetes-sigs/gateway-api/pull/1757 Prior Discussions: + - https://github.com/kubernetes-sigs/gateway-api/discussions/1248 - https://github.com/kubernetes-sigs/gateway-api/discussions/1246 -Gateway Hierarchy Brainstorming +Gateway Hierarchy Brainstorming: + - https://docs.google.com/document/d/1qj7Xog2t2fWRuzOeTsWkabUaVeOF7_2t_7appe8EXwA/edit From 32308c906f79f261ce173b49f542348f274bd5fc Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Thu, 1 Aug 2024 16:28:52 -0400 Subject: [PATCH 25/40] include potential goals from the gateway hierarchy document --- geps/gep-1713/index.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index b1b98bd7d8..2173320b3e 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -12,8 +12,20 @@ The `Gateway` Resource is a point of contention since it is the only place to at ## Goals - Define a mechanism to merge listeners into a single `Gateway` -## Future Goals (Beyond the GEP) +## Future Potential Goals (Beyond the GEP) + +From [Gateway Hiearchy Brainstorming](https://docs.google.com/document/d/1qj7Xog2t2fWRuzOeTsWkabUaVeOF7_2t_7appe8EXwA/edit#heading=h.w311n4l5qmwk): + - Attaching listeners to `Gateways` in different namespaces +- Standardize merging multiple lists of Listeners together ([\#1863](https://github.com/kubernetes-sigs/gateway-api/pull/1863)) +- Increase the number of Gateway Listeners that are supported ([\#2869](https://github.com/kubernetes-sigs/gateway-api/issues/2869)) +- Provide a mechanism for third party components to generate listeners and attach them to a Gateway ([\#1863](https://github.com/kubernetes-sigs/gateway-api/pull/1863)) +- Delegate TLS certificate management to App Owners and/or different namespaces ([\#102](https://github.com/kubernetes-sigs/gateway-api/issues/102), [\#103](https://github.com/kubernetes-sigs/gateway-api/issues/103)) +- Delegate domains to different namespaces, but allow those namespace to define TLS and routing configuration within those namespaces with Gateway-like resources ([\#102](https://github.com/kubernetes-sigs/gateway-api/issues/102), [\#103](https://github.com/kubernetes-sigs/gateway-api/issues/103)) +- Enable admins to delegate SNI-based routing for TLS passthrough to other teams and/or namespaces ([\#3177](https://github.com/kubernetes-sigs/gateway-api/discussions/3177)) (Remove TLSRoute) +- Simplify L4 routing by removing at least one of the required layers (Gateway \-\> Route \-\> Service) +- Delegate routing to namespaces based on path prefix (previously known as [Route delegation](https://github.com/kubernetes-sigs/gateway-api/issues/1058)) +- Static infrastructure attachment ([\#3103](https://github.com/kubernetes-sigs/gateway-api/discussions/3103\#discussioncomment-9678523)) ## Use Cases & Motivation From d01d705303748f48c8719662bd9d4bbd06252214 Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Thu, 1 Aug 2024 16:36:18 -0400 Subject: [PATCH 26/40] fix language that allows a route to attach to both a listener set and a gateway at the same time --- geps/gep-1713/index.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 2173320b3e..eaad9e39f5 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -488,9 +488,10 @@ spec: ### Route Attaching -Routes MUST be able to specify a `ListenerSet` as a `parentRef`. Routes can use `sectionName`/`port` fields in `ParentReference` to help target a specific listener. If no listener is targeted (`sectionName`/`port` are unset) then the Route attaches to all the listeners on the `ListenerSet` and it `MUST NOT` attach to any listeners in the `ListenerSet`'s parent `Gateways`. +Routes MUST be able to specify a `ListenerSet` as a `parentRef`. Routes can use `sectionName`/`port` fields in `ParentReference` to help target a specific listener. If no listener is targeted (`sectionName`/`port` are unset) then the Route attaches to all the listeners in the `ListenerSet`. + +Routes MUST be able to attach to a `ListenerSet` and it's parent `Gateway` by having multiple `parentRefs` eg: -eg. ```yaml apiVersion: gateway.networking.k8s.io/v1beta1 kind: HTTPRoute @@ -517,7 +518,7 @@ spec: sectionName: foo ``` -To attach to listeners in both a `Gateway` and `ListenerSet` the route must have two `parentRefs`: +To attach to listeners in both a `Gateway` and `ListenerSet` the route MUST have two `parentRefs`: ```yaml apiVersion: gateway.networking.k8s.io/v1beta1 kind: HTTPRoute From dd8a0f6a643976cabf77e9de7ae5d0ab9a991b00 Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Thu, 1 Aug 2024 16:37:52 -0400 Subject: [PATCH 27/40] if a route tries to attach to a non-existent listener on the listener set then Accepted should be false --- geps/gep-1713/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index eaad9e39f5..4c56d810f2 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -504,7 +504,7 @@ 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 should reflect that. +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/v1beta1 From cc114387d203cb0a7b94c3edea11a8292378cc84 Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Thu, 1 Aug 2024 16:40:20 -0400 Subject: [PATCH 28/40] ListenerStatus => ListenerEntryStatus --- geps/gep-1713/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 4c56d810f2..77f8291072 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -619,9 +619,9 @@ The `Programmed` condition MUST be set on every `ListenerSet` and have a similar ### ListenerConditions within a ListenerSet -An implementation MAY reject listeners by setting the `ListenerStatus` `Accepted` condition to `False` with the `Reason` `TooManyListeners` +An implementation MAY reject listeners by setting the `ListenerEntryStatus` `Accepted` condition to `False` with the `Reason` `TooManyListeners` -If a listener has a conflict, this should be reported in the `ListenerStatus` of the conflicted `ListenerSet` by setting the `Conflicted` condition to `True`. +If a listener has a conflict, this should be reported in the `ListenerEntryStatus` of the conflicted `ListenerSet` by setting the `Conflicted` condition to `True`. Implementation SHOULD be cautious about what information from the parent or siblings are reported to avoid accidentally leaking sensitive information that the child would not otherwise have access to. From 5c00375526d457c564a644ba0d53def1ea93c8ab Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Thu, 1 Aug 2024 16:43:41 -0400 Subject: [PATCH 29/40] add a blurb about listenerset+gateway listeners are joined as a list --- geps/gep-1713/index.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 77f8291072..3cbf5ded46 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -577,6 +577,8 @@ spec: ### Listener Precedence +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: 1. "parent" Gateway From 54de6220983b6ac469ad087fb8b1d744eeae1ddc Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Thu, 1 Aug 2024 16:54:36 -0400 Subject: [PATCH 30/40] Gateways that fail should also fail their attached ListenerSets --- geps/gep-1713/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 3cbf5ded46..7412f359cb 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -616,6 +616,7 @@ Valid reasons for `Accepted` being `False` are: The `Programmed` condition MUST be set on every `ListenerSet` and have a similar meaning to the Gateway `Programmed` condition but only reflect the listeners in this `ListenerSet`. `Accepted` and `Programmed` conditions when surfacing details about listeners, MUST only summarize the `status.parents.listeners` conditions that are exclusive to the `ListenerSet`. +An exception to this is when the parent `Gateway`'s `Accepted` or `Programmed` conditions transition to `False` `ListenerSets` MUST NOT have their parent `Gateway`'s' listeners in the associated `status.parents.listeners` conditions list. From 8b338bc994ce4896573f6ecbd125a30b7bbd4115 Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Thu, 1 Aug 2024 17:46:04 -0400 Subject: [PATCH 31/40] don't leak secrets --- geps/gep-1713/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 7412f359cb..2e08ec28e8 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -626,7 +626,7 @@ An implementation MAY reject listeners by setting the `ListenerEntryStatus` `Acc If a listener has a conflict, this should be reported in the `ListenerEntryStatus` of the conflicted `ListenerSet` by setting the `Conflicted` condition to `True`. -Implementation SHOULD be cautious about what information from the parent or siblings are reported to avoid accidentally leaking sensitive information that the child would not otherwise have access to. +Implementations SHOULD be cautious about what information from the parent or siblings are reported to avoid accidentally leaking sensitive information that the child would not otherwise have access to. This can include contents of secrets etc. ### Policy Attachment From c656a6555c669d231ce47ae8310238fdeffc76ae Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Thu, 19 Dec 2024 22:21:33 -0500 Subject: [PATCH 32/40] update title --- geps/gep-1713/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 2e08ec28e8..788724441d 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -1,4 +1,4 @@ -# GEP-1713: Standard Mechanism to Merge Multiple Gateways +# GEP-1713: ListenerSets - Standard Mechanism to Merge Multiple Gateways * Issue: [#1713](/kubernetes-sigs/gateway-api/issues/1713) * Status: Provisional From 67fbed4aa0edb96b4b531b3000eafa1068f65ef8 Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Thu, 19 Dec 2024 22:21:52 -0500 Subject: [PATCH 33/40] mention dummy listener for the first release --- geps/gep-1713/index.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 788724441d..20c72c691b 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -467,7 +467,9 @@ From robscott https://github.com/kubernetes-sigs/gateway-api/pull/3213#discussio ### Gateway Changes -When an implementation supports `ListenerSets` `Gateways` MUST allow the list of listeners to be empty. Thus the present `minItems=1` constraint on the listener list will be removed. This allows implementations to avoid security, cost etc. concerns with having dummy listeners. +An initial experimental release of `ListenerSets` _will have no modifications_ to listener list on the `Gateway` resource. Using `ListenerSets` will require a dummy listener to be configured. + +In a future (potential) release when an implementation supports `ListenerSets`, `Gateways` MUST allow the list of listeners to be empty. Thus the present `minItems=1` constraint on the listener list will be removed. This allows implementations to avoid security, cost etc. concerns with having dummy listeners. When there are no listeners the `Gateway`'s `status.listeners` should be empty or unset. `status.listeners` is already an optional field. Implementations, when creating a `Gateway`, may provision underlying infrastructure when there are no listeners present. The status conditions `Accepted` and `Programmed` conditions should reflect state of this provisioning. From 02a50a2193c26d905e4b9e40ecbd0f3c740e37fc Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Thu, 19 Dec 2024 22:31:58 -0500 Subject: [PATCH 34/40] tweak the name of the AttachedListenerSets condition --- geps/gep-1713/index.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 20c72c691b..4cfdfa805d 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -593,13 +593,13 @@ Conflicts are covered in the section 'ListenerConditions within a ListenerSet' `Gateway`'s `Accepted` and `Programmed` top-level conditions remain unchanged and reflect the status of the local configuration. -Implementations MUST support a new condition type `AttachedListeners`. +Implementations MUST support a new `Gateway` condition type `AttachedListenerSets`. The condition's `Status` has the following values: -- `True` when `AllowedListeners` is set and at least one child Listener arrives from a `ListenerSet` -- `False` when `AllowedListeners` is set but has no valid listeners are attached -- `Unknown` when no `AllowedListeners` config is present +- `True` when `Spec.AllowedListeners` is set and at least one child Listener arrives from a `ListenerSet` +- `False` when `Spec.AllowedListeners` is set but has no valid listeners are attached +- `Unknown` when no `Spec.AllowedListeners` config is present Parent `Gateways` MUST NOT have `ListenerSet` listeners in their `status.listeners` conditions list. From 4ca38a61cf8142834d6e981db72514e732476d5c Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Thu, 19 Dec 2024 23:08:15 -0500 Subject: [PATCH 35/40] rob's suggestions --- geps/gep-1713/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 4cfdfa805d..1c49ede862 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -36,13 +36,13 @@ Thus updating a single `Gateway` resource with this many certificates is a conte More broadly, large scale gateway users often expose `O(1000)` domains, but are currently limited by the maximum of 64 `listeners`. -The spec currently has language to indicate implementations `MAY` merge `Gateways` resources but the mechanic isn't defined. +The spec currently has language to indicate implementations `MAY` merge `Gateways` resources but does not define any specific requirements for how that should work. https://github.com/kubernetes-sigs/gateway-api/blob/541e9fc2b3c2f62915cb58dc0ee5e43e4096b3e2/apis/v1beta1/gateway_types.go#L76-L78 ## Feature Details We define `ListenerSet` as the name of the feature outlined in this GEP. -The feature will be part of the experimental branches as an extended feature, which implementations can choose to support. At that time, all the requirements in this document that use MUST apply to their implementation of the feature. +The feature will be part of the experimental channel, which implementations can choose to support. All the `MUST` requirements in this document apply to implementations that choose to support this feature. ## API From 3fdd031a379825dcbb75250e65cc6fb35870006f Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Thu, 19 Dec 2024 23:08:34 -0500 Subject: [PATCH 36/40] bump listener count --- geps/gep-1713/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 1c49ede862..98ce013e06 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -104,7 +104,7 @@ type ListenerSetSpec struct { // +listType=map // +listMapKey=name // +kubebuilder:validation:MinItems=1 - // +kubebuilder:validation:MaxItems=16 + // +kubebuilder:validation:MaxItems=64 Listeners []ListenerEntry } // ListenerEntry embodies the concept of a logical endpoint where a Gateway accepts @@ -305,7 +305,7 @@ type ListenerSetParentStatus struct { // +optional // +listType=map // +listMapKey=name - // +kubebuilder:validation:MaxItems=16 + // +kubebuilder:validation:MaxItems=64 Listeners []ListenerEntryStatus `json:"listeners,omitempty"` // Conditions describe the current conditions of the ListenerSet. From 1c33b846b1919c775f2f38b33512b22e28fc4a97 Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Thu, 19 Dec 2024 23:11:58 -0500 Subject: [PATCH 37/40] just re-use GatewayTLSConfig --- geps/gep-1713/index.md | 81 +----------------------------------------- 1 file changed, 1 insertion(+), 80 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 98ce013e06..8a5ea8a249 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -170,7 +170,7 @@ type ListenerEntry struct { // Support: Core // // +optional - TLS *ListenerSetTLSConfig `json:"tls,omitempty"` + TLS *GatewayTLSConfig `json:"tls,omitempty"` // AllowedRoutes defines the types of routes that MAY be attached to a // Listener and the trusted namespaces where those Route resources MAY be @@ -201,85 +201,6 @@ type ListenerEntry struct { AllowedRoutes *AllowedRoutes `json:"allowedRoutes,omitempty"` } -// ListenerSetTLSConfig describes a TLS configuration. -// -// +kubebuilder:validation:XValidation:message="certificateRefs or options must be specified when mode is Terminate",rule="self.mode == 'Terminate' ? size(self.certificateRefs) > 0 || size(self.options) > 0 : true" -type ListenerSetTLSConfig struct { - // Mode defines the TLS behavior for the TLS session initiated by the client. - // There are two possible modes: - // - // - Terminate: The TLS session between the downstream client and the - // Gateway is terminated at the Gateway. This mode requires certificates - // to be specified in some way, such as populating the certificateRefs - // field. - // - Passthrough: The TLS session is NOT terminated by the Gateway. This - // implies that the Gateway can't decipher the TLS stream except for - // the ClientHello message of the TLS protocol. The certificateRefs field - // is ignored in this mode. - // - // Support: Core - // - // +optional - // +kubebuilder:default=Terminate - Mode *TLSModeType `json:"mode,omitempty"` - - // CertificateRefs contains a series of references to Kubernetes objects that - // contains TLS certificates and private keys. These certificates are used to - // establish a TLS handshake for requests that match the hostname of the - // associated listener. - // - // A single CertificateRef to a Kubernetes Secret has "Core" support. - // Implementations MAY choose to support attaching multiple certificates to - // a Listener, but this behavior is implementation-specific. - // - // References to a resource in different namespace are invalid UNLESS there - // is a ReferenceGrant in the target namespace that allows the certificate - // to be attached. If a ReferenceGrant does not allow this reference, the - // "ResolvedRefs" condition MUST be set to False for this listener with the - // "RefNotPermitted" reason. - // - // This field is required to have at least one element when the mode is set - // to "Terminate" (default) and is optional otherwise. - // - // CertificateRefs can reference to standard Kubernetes resources, i.e. - // Secret, or implementation-specific custom resources. - // - // Support: Core - A single reference to a Kubernetes Secret of type kubernetes.io/tls - // - // Support: Implementation-specific (More than one reference or other resource types) - // - // +optional - // +kubebuilder:validation:MaxItems=64 - CertificateRefs []SecretObjectReference `json:"certificateRefs,omitempty"` - - // FrontendValidation holds configuration information for validating the frontend (client). - // Setting this field will require clients to send a client certificate - // required for validation during the TLS handshake. In browsers this may result in a dialog appearing - // that requests a user to specify the client certificate. - // The maximum depth of a certificate chain accepted in verification is Implementation specific. - // - // Support: Extended - // - // +optional - // - FrontendValidation *FrontendTLSValidation `json:"frontendValidation,omitempty"` - - // Options are a list of key/value pairs to enable extended TLS - // configuration for each implementation. For example, configuring the - // minimum TLS version or supported cipher suites. - // - // A set of common keys MAY be defined by the API in the future. To avoid - // any ambiguity, implementation-specific definitions MUST use - // domain-prefixed names, such as `example.com/my-custom-option`. - // Un-prefixed names are reserved for key names defined by Gateway API. - // - // Support: Implementation-specific - // - // +optional - // +kubebuilder:validation:MaxProperties=16 - Options map[AnnotationKey]AnnotationValue `json:"options,omitempty"` -} - // ListenerSetStatus defines the observed state of a ListenerSet type ListenerSetStatus struct { // Parents is a list of parent resources (usually Gateways) that are From 59cc00bd97dcef642713aeec365066bf6a60d1ad Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Thu, 19 Dec 2024 23:13:53 -0500 Subject: [PATCH 38/40] use v1 api version for httproute --- geps/gep-1713/index.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 8a5ea8a249..62af9cddbd 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -399,7 +399,7 @@ Implementations, when creating a `Gateway`, may provision underlying infrastruct By default a `Gateway` MUST NOT allow `ListenerSets` to be attached. Users can enable this behaviour by configuring their `Gateway` to allow `ListenerSet` attachment: -``` +```yaml apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: @@ -416,7 +416,7 @@ Routes MUST be able to specify a `ListenerSet` as a `parentRef`. Routes can use Routes MUST be able to attach to a `ListenerSet` and it's parent `Gateway` by having multiple `parentRefs` eg: ```yaml -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: httproute-example @@ -430,7 +430,7 @@ spec: 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/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: httproute-example @@ -443,7 +443,7 @@ spec: To attach to listeners in both a `Gateway` and `ListenerSet` the route MUST have two `parentRefs`: ```yaml -apiVersion: gateway.networking.k8s.io/v1beta1 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: httproute-example From cb906b9dee7a7823bf0122142e3b01d12bd09ae0 Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Thu, 19 Dec 2024 23:15:59 -0500 Subject: [PATCH 39/40] replace route with ListenerSet in godoc --- geps/gep-1713/index.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index 62af9cddbd..e4eb5a8e3c 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -204,11 +204,11 @@ type ListenerEntry struct { // ListenerSetStatus defines the observed state of a ListenerSet type ListenerSetStatus struct { // Parents is a list of parent resources (usually Gateways) that are - // associated with the route, and the status of the route with respect to - // each parent. When this route attaches to a parent, the controller that + // associated with the ListenerSet, and the status of the ListenerSet with respect to + // each parent. When this ListenerSet attaches to a parent, the controller that // manages the parent must add an entry to this list when the controller - // first sees the route and should update the entry as appropriate when the - // route or gateway is modified. + // first sees the ListenerSet and should update the entry as appropriate when the + // ListenerSet or gateway is modified. // // +kubebuilder:validation:MaxItems=2 Parents []ListenerSetParentStatus `json:"parents"` From c01596109c956727aa98e00961729d3066603b80 Mon Sep 17 00:00:00 2001 From: Dave Protasowski Date: Fri, 20 Dec 2024 12:56:14 -0500 Subject: [PATCH 40/40] include listener precedence in godoc --- geps/gep-1713/index.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/geps/gep-1713/index.md b/geps/gep-1713/index.md index e4eb5a8e3c..4951b82915 100644 --- a/geps/gep-1713/index.md +++ b/geps/gep-1713/index.md @@ -100,6 +100,14 @@ type ListenerSetSpec struct { // Listeners associated with this ListenerSet. Listeners define // logical endpoints that are bound on this referenced parent Gateway's addresses. // + // 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: + // + // 1. "parent" Gateway + // 2. ListenerSet ordered by creation time (oldest first) + // 3. ListenerSet ordered alphabetically by “{namespace}/{name}”. // // +listType=map // +listMapKey=name