Gateway API TLSRoute with Envoy Gateway¶
TL;DR
I was able to briefly get a TLSRoute working with the Envoy Gateway, but I ran into some issues when TLSRoute was promoted out of experimental CRDs. I was using a TLSRoute to route traffic to an MQTT broker, but recently had to regress to a TCPRoute after upgrading Gateway API and Envoy Gateway.
TLSRoute from standard Gateway API CRDs should work again with an Envoy
Gateway release later than v1.7.1.
Updates
2026-04-26: v1.7.2 does not contain the fix. I'm assuming it will be
in the next minor release, possibly v1.8.0.
TLSRoute vs TCPRoute¶
TLSRoute and TCPRoute both handle L4 traffic, but they differ in how much they understand about TLS:
TLSRoute: TLS-aware routing (typically based on SNI) while keeping end-to-end TLS between client and backend.TCPRoute: raw TCP forwarding with no TLS-specific matching.
In practice, TCPRoute often means dedicating a listener/port per application because there is no hostname match, while TLSRoute enables hostname fanout on the same port.
TCPRoute still offers the simplest, most stable path if you do not need SNI-based routing logic.
What was I using TLSRoute for?¶
I have HomeAssistant running in my Talos k8s cluster, and I'm also hosting an MQTT broker for some automations related to HA. I want services to reach MQTT securely over TLS with a certificate provided by cert-manager for an internal domain name, reachable only via Tailscale or the LAN.
Envoy Gateway is used as the Gateway API implementation. MQTT serves the TLS
certificate, so when TLSRoute was working the Gateway used a TLS listener with
tls.mode: Passthrough. With TCPRoute, there is no tls.mode; the Gateway uses
a TCP listener and forwards raw TCP bytes, so TLS still passes through
end-to-end to MQTT.
TLSRoute support was available only via the experimental CRDs up until
somewhere around early 2026 (v1.5.0), after which it was moved to standard.
TCPRoute is still currently only available via experimental CRDs. Envoy
Gateway v1.7.1 has a bug when used with Gateway API v.1.5.1 standard.
I later realized that switching back to experimental for Gateway API (v1.5.1)
made TLSRoute work again with Envoy Gateway v1.7.1.
Chart Versions¶
| Chart | Version | Notes |
|---|---|---|
Kubernetes gateway-api |
v1.4.1 | TLSRoute and TCPRoute available from experimental CRDs |
| v1.5.1 | TLSRoute.v1 served from standard CRDsTLSRoute.v1alpha2 served from experimental CRDsTCPRoute served from experimental CRDs |
|
Envoy gateway-helm |
v1.6.1 | Looks for TLSRoute.v1alpha2 |
| v1.7.1 | Still looks for TLSRoute.v1alpha2 |
Investigation¶
Envoy Gateway controller log:
INFO provider kubernetes/controller.go:2195 TLSRoute CRD not found, skipping TLSRoute watch {"runner": "provider"}
Envoy Gateway v1.7.1 tries to watch *v1alpha2.TLSRoute at startup, discovers
v1alpha2 isn't served, and skips it entirely. TCPRoute is actually installed as
part of the Envoy Gateway CRDs from the experimental branch of Gateway API and
is served with v1alpha2.
Thus, I finally understood why TCPRoute worked post upgrade to standard, even though it is not currently included in the standard CRDs. I had leftover experimental TCPRoute that were not pruned by ArgoCD after upgrading Gateway API. By using experimental again with v1.5.1, I am able to get TLSRoute working again with Envoy Gateway v1.7.1.
GitHub issue¶
https://github.com/envoyproxy/gateway/issues/8326
Issue fix¶
https://github.com/envoyproxy/gateway/pull/8327
Conclusion¶
Stick to experimental CRDs for Gateway API for now. TLSRoute should work with
standard Gateway API CRDs in one of the next releases of Envoy Gateway after
v1.7.1.
Missing Details
This page could use more details on the complete setup.