ListenerSet¶
ListenerSets allow teams to define ports, hostnames, and TLS certificates in separate resources rather than cramming everything into one giant Gateway object which has a limit of 64 listeners. This enables a delegated management model suitable for high-scale, multi-tenant environments.
As such, you might use ListenerSets for the following advantages:
-
Multitenancy: You can let different teams create their own ListenerSets while sharing the same Gateway and backing load-balancing infrastructure.
-
Large scale deployments: By using ListenerSets, Gateways can have more than 64 listeners attached. Teams can also share the same ListenerSet configuration to avoid duplication.
-
Certificates for more listeners per gateway: Because you can now have more than 64 listeners per Gateway, a single Gateway can forward secured traffic to more backends that might have their own certificates. This approach aligns with projects that require service-level certificates, such as Istio Ambient Mesh or Knative.
The following diagram illustrates how ListenerSets help decentralize route configuration in a multi-tenant environment:
-
Team 1 and Team 2 each manage their own Service and HTTPRoute resources within their respective namespaces.
-
Each HTTPRoute refers to a namespace-local ListenerSet. This way, each team controls how their routes are exposed, such as the protocol, port, and TLS certificate settings.
-
The ListenerSets from both teams share a common Gateway in a separate namespace. A separate Gateway team can setup and manage centralized infrastructure or enforce policies as appropriate.
flowchart TD
subgraph team1 namespace
SVC1[Services]
HR1[HTTPRoutes]
LS1[ListenerSet]
end
subgraph team2 namespace
SVC2[Services]
HR2[HTTPRoutes]
LS2[ListenerSet]
end
subgraph shared namespace
GW[Gateway]
end
HR1 -- "parentRef" --> LS1
LS1 -- "parentRef" --> GW
HR1 -- "backendRef" --> SVC1
HR2 -- "parentRef" --> LS2
LS2 -- "parentRef" --> GW
HR2 -- "backendRef" --> SVC2
Using ListenerSets¶
Gateway Configuration¶
By default, a Gateway does not allow ListenerSets to be attached. Users can enable this behaviour
by configuring their Gateway to allow ListenerSets by adding the allowedListeners field to the Gateway spec.
This defines which namespaces are permitted to contribute listeners.
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: parent-gateway
spec:
allowedListeners:
namespaces:
from: Same
ListenerSet Configuration¶
The ListenerSet references the parent Gateway via parentRef:
apiVersion: gateway.networking.k8s.io/v1
kind: ListenerSet
metadata:
name: workload-listeners
spec:
parentRef:
name: parent-gateway
kind: Gateway
group: gateway.networking.k8s.io
Route Attachment¶
To attach an HTTPRoute (or any other route type) to a ListenerSet,
it must reference the ListenerSet as the Parent Resource via parentRefs.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httproute-example
spec:
parentRefs:
- name: workload-listeners
kind: ListenerSet
group: gateway.networking.k8s.io
sectionName: second
Listener Conflicts¶
Since multiple ListenerSets can attach to one Gateway, there are rules about how to manage conflicts. A Listener can be distinct across any group of Listeners (within a single ListenerSet object, or in the group of Listeners attached to a Gateway) based on the combination of Port, Protocol, and (depending on the Protocol) Hostname.
When Listeners are not distinct, there are Listener precedence rules that are used to choose a is used to resolve the conflict, and choose which Listener takes effect. It's often easiest to think of this as a competition, with the "winner" being the Listener that takes effect. The rules go like this, continuing on ties.
- Listeners on the parent Gateway take priority over all others.
- The ListenerSet with the earliest creation time takes priority.
- The first ListenerSet alphabetically takes priority.
The winning ListenerSet is marked as Accepted: true, and the losing ListenerSet(s) are marked with Accepted: false, and Conflidted: true.
As with all the other conflict resolution rules in Gateway API, this is intended to provide traffic stability - so adding a new, conflicting ListenerSet will never take over an existing config.
Examples¶
The following example shows a Gateway with an HTTP listener and two child HTTPS ListenerSets
with unique hostnames and certificates. Only ListenerSets in namespaces that have the belongs: shared-gateway
label will be accepted :
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: parent-gateway
spec:
gatewayClassName: example
allowedListeners:
namespaces:
from: Selector
selector:
matchLabels:
belongs-to: shared-gateway
listeners:
- name: foo
hostname: foo.com
protocol: HTTP
port: 80
---
apiVersion: v1
kind: Namespace
metadata:
name: team-1-ns
labels:
belongs: shared-gateway
---
apiVersion: gateway.networking.k8s.io/v1
kind: ListenerSet
metadata:
name: first-workload-listeners
namespace: team-1-ns
spec:
parentRef:
namespace: default
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
---
apiVersion: v1
kind: Namespace
metadata:
name: team-2-ns
labels:
belongs: shared-gateway
---
apiVersion: gateway.networking.k8s.io/v1
kind: ListenerSet
metadata:
name: second-workload-listeners
namespace: team-2-ns
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