Question and scenario
Design a shared Kubernetes Gateway. A platform team owns the Gateway and load-balancing infrastructure; application teams own hostnames, ports, HTTPRoutes, and certificates in their namespaces. Assume 20 teams with 50 listeners each, or about 1,000 domains, while a single Gateway has a baseline listener limit of 64.
Explain how to split listeners out of one giant Gateway into ListenerSets, authorize cross-namespace attachment, keep traffic stable during conflicts, and expose status so teams can distinguish Accepted, Programmed, or Conflicted configuration.
What the interviewer is testing
Resource boundaries and delegation
A strong answer separates shared infrastructure, tenant configuration, and route attachment, then explains why application teams should not edit the platform Gateway directly.
Conflicts and secure defaults
State the default denial of ListenerSets, allowed namespace sources, deterministic hostname precedence, and certificate-reference boundaries.
Controller consistency
Cover watches, merging, validation, status conditions, and retries. A YAML object alone does not mean the data plane is programmed.
Scale and migration
Compare one Gateway, one Gateway per tenant, and Ingress annotations. Explain when ListenerSet complexity is worth the delegation and interoperability.
Clarifying questions before answering
- Do all 1,000 domains share one load-balancer address, or does each team need an isolated entry point?
- May application teams manage their TLS Secrets, or does the platform approve certificates?
- Should cross-namespace attachment allow all namespaces, a label selector, or only the same namespace?
- Must an old configuration keep serving on conflict, or may a new configuration take over?
- How quickly must the controller reflect changes, and is cross-cluster replication required?
- Do HTTPRoute, TLSRoute, and other route kinds share the same authorization boundary?
30-second answer framework
“I would let the platform team create the Gateway and deny ListenerSets by default, then use allowedListeners to select permitted namespaces. Each application team submits a ListenerSet and routes in its namespace. The controller validates ParentRef, hostname, port, protocol, certificate references, and AllowedRoutes, then merges listeners using parent Gateway first, oldest creation time second, and namespace/name order third. A conflict is marked Accepted=False and Conflicted=True and cannot replace an active listener. The data plane is programmed only from a validated aggregate, while status conditions and metrics distinguish rejection, conflict, unprogrammed, and programmed states.”
Step-by-step deep answer
Step 1: Estimate scale and choose resources
Twenty teams times 50 listeners is about 1,000 entry points. Putting all 1,000 declarations in one Gateway creates single-object write contention, broad permissions, and repeated controller recomputation. ListenerSets split team-owned configuration into independent resources; the Gateway keeps platform address, class, and attachment policy.
Step 2: Establish the authorization handshake
allowedListeners is the security gate. None accepts no ListenerSet by default; the platform can choose Same, a label Selector, or All. A ListenerSet uses parentRef to name the Gateway. The controller includes it only when both sides authorize the relationship, the reference is valid, and namespace selection permits it.
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: shared-gateway
spec:
allowedListeners:
namespaces:
from: Selector
selector:
matchLabels:
gateway-access: shared
---
apiVersion: gateway.networking.k8s.io/v1
kind: ListenerSet
metadata:
name: team-a-listeners
namespace: team-a
spec:
parentRef:
name: shared-gateway
namespace: platform
listeners:
- name: app-a
hostname: app-a.example.com
protocol: HTTPS
port: 443Step 3: Define merge and conflict rules
Combine Gateway listeners with authorized ListenerSet listeners, then determine identity from port, protocol, and applicable hostname. Resolve conflicts deterministically: the parent Gateway wins; then the older ListenerSet wins; remaining ties use namespace/name order. Mark losing resources Conflicted instead of silently replacing active traffic.
Step 4: Isolate routes and certificates
ListenerSet allowedRoutes limits which namespaces may bind routes. A route uses parentRefs to target a ListenerSet section. Platform policy constrains TLS Secret references, separating certificate approval from application release permission. A team can edit its own ListenerSet and Secret but cannot use ParentRef to read another tenant’s resource.
Step 5: Make the controller converge
Watch Gateway, ListenerSet, Route, namespace labels, and Secrets and build a desired model grouped by Gateway. Deduplicate and debounce events, validate the aggregate, then program the load balancer. Return Accepted, Programmed, ResolvedRefs, and Conflicted conditions. Retries are idempotent; the last desired state remains until the new configuration is programmed successfully.
Step 6: Compare alternatives and failure paths
One Gateway per tenant simplifies permission boundaries but multiplies addresses, load balancers, and certificate cost. A single Gateway with annotations is cheap but lacks a shared schema, conflict semantics, and cross-implementation interoperability. When the ListenerSet control plane is unavailable, keep the last Programmed snapshot and reject unknown new listeners. If the parent Gateway disappears or ParentRef becomes invalid, mark children unaccepted and reconcile after recovery.
High-quality sample answer
“I would treat the Gateway as a platform-owned shared boundary and ListenerSets as tenant-owned declarations. The platform configures GatewayClass, addresses, and allowedListeners with denial as the default; only namespaces labeled gateway-access=shared may attach. Each team submits its own ListenerSet, HTTPRoute, and certificate reference.
On every event, the controller validates ParentRef, namespace authorization, port/protocol/hostname, AllowedRoutes, and Secret references before merging. The parent Gateway wins conflicts, followed by ListenerSet creation time and namespace/name order. Losers receive Accepted=False and Conflicted=True and cannot take over live traffic. Only a validated aggregate programs the load balancer, and Programmed means the data plane has applied it.
For 20 teams times 50 listeners, about 1,000 entries, resource splitting avoids single-object write contention and centralized permissions. During controller downtime, the data plane serves the last stable snapshot and rejects conflicting additions. If a tenant needs an isolated address, compliance boundary, or failure domain, I would use separate Gateways and accept the infrastructure cost.”
Common errors
- Let every team edit the Gateway → configurations overwrite one another and permissions are broad → platform owns Gateway, tenants own ListenerSets.
- Allow every namespace by default → any tenant can request shared ingress → default to None, then narrow with Same or Selector.
- Let the last write win → a new listener can hijack a hostname → use deterministic precedence and mark losers conflicted.
- Compare only hostname → different protocols can still collide → use port, protocol, and applicable hostname together.
- Pass Secret names straight to the data plane → cross-namespace privilege or certificate leakage → validate references and authorization first.
- Reprogram immediately for every event → transient invalid states cause churn → debounce, merge idempotently, switch after success, and retain a snapshot.
- Expose only Ready in status → tenants cannot tell rejection from conflict or programming lag → use Accepted, Programmed, ResolvedRefs, and Conflicted conditions.
- Treat ListenerSet as unlimited scaling → controllers and load balancers still have limits → shard by Gateway, set tenant quotas, and monitor convergence.
Follow-up questions and responses
Follow-up 1: Two teams submit the same hostname and port. Who wins?
The parent Gateway wins. Between ListenerSets, the older creation time wins; a remaining tie uses namespace/name order. The loser stays visible with Conflicted and cannot change the result through retry timing.
Follow-up 2: How can the platform freeze one tenant temporarily?
Remove its namespace label or narrow the allowedListeners selector. The controller marks the ListenerSet unaccepted while retaining the last snapshot. Record the freeze for audit, and revalidate on recovery instead of trusting the old object blindly.
Follow-up 3: A ListenerSet has 64 listeners. Can it grow further?
The implementation limit still applies; total capacity is not infinite. Split the tenant across ListenerSets and Gateways with quotas. If address or certificate isolation matters more than sharing, use multiple Gateways.
Follow-up 4: How do you rotate a TLS Secret without an outage?
Watch the Secret version, validate its chain, hostname, and expiry, and update Programmed only after the data plane confirms the new certificate. Keep the old certificate for a grace window; on failure continue serving the last known-good version and alert.
Follow-up 5: Can a new Route replace live traffic while the controller restarts?
No. Persist or rebuild desired state while the data plane serves the last successful snapshot. After restart, recompute references and conflicts, then switch once to an observable configuration version.
Source 1: Gateway API ListenerSet user guide
The guide defines ListenerSet’s delegated multi-tenant use, the 64-listener limit, allowedListeners, parentRef, and conflict precedence. Those facts ground the resource model, authorization handshake, conflict handling, and status design.
Source 2: GEP-1713
GEP-1713 describes resource contention, cross-namespace management, and large-domain use cases, and specifies parent Gateway, creation-time, and lexical merge rules. The capacity estimate and alternatives use those constraints.
Source 3: Kubernetes Gateway API v1.5 release notes
The release notes record ListenerSet moving to Standard and its focus on multi-tenancy, delegated listeners, and more than 64 listeners. This answer turns that public change into migration and governance decisions.
Source 4: Public system-design interview guide
The public guide emphasizes clarifying requirements, discussing scale and failure, and explaining trade-offs. The clarifications, estimate, conflict follow-ups, and alternatives train those observable interview signals.