Skip to content

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.

https://github.com/envoyproxy/gateway

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 CRDs
TLSRoute.v1alpha2 served from experimental CRDs
TCPRoute 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.