Skip to content

Supported Resources

This document details the feature support matrix for each Gateway API resource type in the Cloudflare Tunnel Gateway Controller.

Resource Overview

Resource API Version Status
GatewayClass gateway.networking.k8s.io/v1 Supported
Gateway gateway.networking.k8s.io/v1 Supported
HTTPRoute gateway.networking.k8s.io/v1 Supported
GRPCRoute gateway.networking.k8s.io/v1 Supported
ReferenceGrant gateway.networking.k8s.io/v1beta1 Supported
ListenerSet gateway.networking.k8s.io/v1 Supported — see ListenerSet
TCPRoute gateway.networking.k8s.io/v1alpha2 Not supported
TLSRoute gateway.networking.k8s.io/v1alpha2 Not supported
UDPRoute gateway.networking.k8s.io/v1alpha2 Not supported

GatewayClass

Field Supported Notes
spec.controllerName Yes Must match --controller-name flag
spec.parametersRef Yes Via GatewayClassConfig CRD
spec.description Yes Informational only

Gateway

The Gateway resource is fully processed. Listeners are used for route binding, status reporting, and validation. TLS termination is handled by Cloudflare edge, but TLS certificate references are validated (including ReferenceGrant checks).

Field Supported Notes
spec.gatewayClassName Yes Required; the referenced GatewayClass must have a matching spec.controllerName
spec.listeners Yes Fully processed for route binding and status
spec.listeners[].name Yes Used for route binding, status reporting, attached route counting
spec.listeners[].port Yes Used for route binding when route specifies a port
spec.listeners[].protocol Yes Used for route kind filtering (HTTP/HTTPS allow HTTPRoute/GRPCRoute)
spec.listeners[].hostname Yes Routes must have intersecting hostnames
spec.listeners[].tls Yes CertificateRefs validated with ReferenceGrant support
spec.listeners[].allowedRoutes Yes Namespace (Same/All/Selector) and kind filtering
spec.tls.backend.clientCertificateRef Yes kubernetes.io/tls Secret only; same-namespace or via ReferenceGrant; presented during backend TLS handshake only when the target Service has a BackendTLSPolicy (no client cert is sent over plaintext)
spec.addresses No Ignored; tunnel CNAME set automatically in status
spec.infrastructure No Not implemented

TLS Termination

Cloudflare Tunnel terminates TLS at Cloudflare's edge network. TLS certificate references on listeners are validated (existence, ReferenceGrant for cross-namespace refs), but the actual TLS termination is handled by Cloudflare, not by the controller. The listener port and protocol fields are used for Gateway API route binding semantics, not for configuring network listeners.

HTTPRoute

All HTTPRoute matching and filter behavior is performed by the in-process L7 proxy that the chart deploys alongside the controller.

Field Supported Notes
spec.parentRefs Yes References to Gateway
spec.parentRefs[].name Yes Gateway name
spec.parentRefs[].namespace Yes Gateway namespace
spec.parentRefs[].sectionName Yes Listener name (optional)
spec.parentRefs[].port Yes Listener port (optional)
spec.hostnames Yes Wildcard * supported
spec.rules Yes Routing rules
spec.rules[].name Yes Metadata only; preserved on the spec but not consulted during matching
spec.rules[].matches Yes Full matching
spec.rules[].matches[].path Yes PathPrefix, Exact, RegularExpression
spec.rules[].matches[].headers Yes Exact and RegularExpression matchers
spec.rules[].matches[].queryParams Yes Exact and RegularExpression matchers
spec.rules[].matches[].method Yes All HTTP methods
spec.rules[].filters Yes See Filters
spec.rules[].backendRefs Yes Service, ServiceImport, or ExternalBackend — see Supported Backend Kinds
spec.rules[].backendRefs[].name Yes Name of the Service / ServiceImport / ExternalBackend
spec.rules[].backendRefs[].namespace Yes Cross-namespace refs require ReferenceGrant (keyed on the backend group/kind)
spec.rules[].backendRefs[].port Yes Service / ServiceImport port; ignored for ExternalBackend (its spec.port wins)
spec.rules[].backendRefs[].weight Yes True weighted traffic splitting across backends
spec.rules[].backendRefs[].filters Yes Per-backend filters applied after rule-level filters
spec.rules[].timeouts Yes Per-rule request and backend timeouts

Backend Protocol (appProtocol)

When an HTTPRoute references a Service whose target port sets appProtocol, the L7 proxy selects the upstream transport accordingly:

Service.spec.ports[].appProtocol Supported Notes
kubernetes.io/h2c Yes Proxy speaks HTTP/2 cleartext (prior knowledge) to the backend
(unset) Yes Proxy speaks HTTP/1.1 to the backend (default)
kubernetes.io/ws Yes WebSocket over cleartext: the proxy detects upgrade headers and routes through a dedicated upgrade path that dials the backend, forwards the handshake, writes the 101 status, then bidirectionally pipes bytes after hijack
kubernetes.io/wss Yes WebSocket over TLS: requires a matching BackendTLSPolicy (same precondition as appProtocol: https); see Backend Protocol notes
any other value No Logged with a warning; proxy falls back to default HTTP/1.1

A GRPCRoute backend is HTTP/2 by definition, so it is dialed h2c by default and only the TLS-vs-cleartext decision applies: a TLS appProtocol (https / HTTPS / kubernetes.io/wss) with no BackendTLSPolicy fails the backend closed (HTTP 502, ResolvedRefs=False, Reason=UnsupportedProtocol), identical to the HTTPRoute path. See gRPC backends and appProtocol.

Filters

The following HTTPRoute filters are supported:

Filter Type Supported Notes
RequestHeaderModifier Yes Add, set, or remove request headers
ResponseHeaderModifier Yes Add, set, or remove response headers
RequestRedirect Yes Redirect with scheme, hostname, port, path, status code
URLRewrite Yes Rewrite hostname and/or path
RequestMirror Yes Mirror traffic to one or more secondary backends. Per Gateway API only one of percent or fraction may be set on a filter; percent takes precedence if both appear.
ExtensionRef No Not implemented

Supported Service Types

Service Type Supported Notes
ClusterIP Yes Routes via cluster-local DNS
NodePort Yes Routes via cluster-local DNS
LoadBalancer Yes Routes via cluster-local DNS
ExternalName Yes Routes directly to external hostname

Supported Backend Kinds

A backendRef may target one of the following kinds (applies to both HTTPRoute and GRPCRoute):

Group Kind Supported Notes
(core) Service Yes Default when group/kind are unset; all Service types above
multicluster.x-k8s.io ServiceImport Yes Multi-Cluster Services API; resolved via clusterset.local DNS, port validated against spec.ports
cf.k8s.lex.la ExternalBackend Yes Out-of-cluster HTTP(S) URL; see ExternalBackend
(any other) (any other) No ResolvedRefs=False, InvalidKind

Cross-namespace ServiceImport/ExternalBackend references require a ReferenceGrant whose to entry names the matching group/kind, the same way a cross-namespace Service ref does.

GRPCRoute

GRPCRoute is served by the in-process L7 proxy. gRPC requests are HTTP/2 POSTs to /{service}/{method}, so the converter maps each method match onto the proxy's path matcher. The upstream hop is cleartext h2c by default; attaching a BackendTLSPolicy upgrades the hop to TLS with HTTP/2 negotiated via ALPN, and the Gateway's clientCertificateRef is presented on the handshake for mTLS.

Field Supported Notes
spec.parentRefs Yes Gateway or ListenerSet, same as HTTPRoute
spec.hostnames Yes Wildcard * supported
spec.rules[].matches[].method Yes Exact (service+method, service-only, method-only) and RegularExpression
spec.rules[].matches[].headers Yes Exact and RegularExpression matchers (shared with HTTP)
spec.rules[].backendRefs Yes Service backends; cleartext h2c by default, TLS + ALPN HTTP/2 when a BackendTLSPolicy targets the Service
spec.rules[].filters Partial Core RequestHeaderModifier and extended ResponseHeaderModifier are served through the shared header-modifier pipeline (rule- and backend-scoped). RequestMirror and ExtensionRef are not served yet and fail closed (matching requests receive HTTP 500).
BackendTLSPolicy / Gateway clientCertificateRef Yes When a BackendTLSPolicy targets the backend Service, the proxy dials TLS with HTTP/2 negotiated via ALPN. The Gateway's clientCertificateRef is presented for mTLS only when a policy is also attached (Gateway API spec — a client cert over plaintext is meaningless). See GRPCRoute docs.

gRPC method matching maps to paths as follows:

Method match Proxy path rule
Exact service + method exact /{service}/{method}
Exact service only prefix /{service}/ (all methods)
Exact method only regex /[^/]+/{method} (any service)
RegularExpression regex /{service}/{method} (as written)

Conformance runs through an edge-routing gRPC client

The upstream Gateway API gRPC conformance tests dial the Gateway address (*.cfargotunnel.com) directly, and that hostname resolves to Cloudflare's ULA range, which is not externally routable. The suite allows injecting a custom gRPC client, so the conformance run supplies one that dials the Cloudflare edge instead — the same approach the HTTP suite already uses via a custom RoundTripper. GRPCExactMethodMatching, GRPCRouteHeaderMatching, GRPCRouteNamedRule, and GRPCRouteListenerHostnameMatching run this way (the run pins the http2 tunnel transport, since gRPC trailers do not survive QUIC). One test stays skipped: GRPCRouteWeight, whose distribution sampler news its own client and bypasses the injectable one (kubernetes-sigs/gateway-api#4926). gRPC routing is additionally validated end-to-end by the in-house e2e suite against a real tunnel.

ReferenceGrant

ReferenceGrant enables cross-namespace backend references in HTTPRoute and GRPCRoute resources.

Field Supported Notes
spec.from Yes Source routes (HTTPRoute, GRPCRoute)
spec.from[].group Yes Must be gateway.networking.k8s.io
spec.from[].kind Yes Must be HTTPRoute or GRPCRoute
spec.from[].namespace Yes Namespace where routes are located
spec.to Yes Target resources (Services)
spec.to[].group Yes Must be "" (core) for Services
spec.to[].kind Yes Must be Service
spec.to[].name Yes Optional; if omitted, all Services allowed

See ReferenceGrant for detailed examples.

Path Matching

All matching is performed by the in-process L7 proxy:

Type Behavior
PathPrefix Full prefix matching
Exact True exact matching
RegularExpression Full regex matching (RE2)

gRPC Method Matching

gRPC methods are mapped to HTTP/2 paths using the standard format /package.Service/Method. All matching happens inside the in-process L7 proxy (see the GRPCRoute table above for the same mapping in the route context).

Match Type Example Proxy path rule
Service only service: mypackage.MyService prefix /mypackage.MyService/
Service + Method service: mypackage.MyService, method: GetUser exact /mypackage.MyService/GetUser
Method only method: GetUser regex /[^/]+/GetUser (any service)
No match (empty) Matches all gRPC traffic

Weight and Traffic Splitting

True weighted traffic splitting across multiple backends is performed by the in-process L7 proxy.

  • Default weight: 1 (per Gateway API specification)
  • Zero weight: Backends with weight: 0 are disabled

An invalid backend ref fails its own traffic fraction

If a backend ref in a rule fails validation — cross-namespace denial (RefNotPermitted), a missing Service (BackendNotFound), or an unsupported kind/port — it stays in the weighted pool and the proxy returns HTTP 500 for its traffic fraction only; the other backends in the same rule keep serving their proportional share. The route status shows ResolvedRefs=False. Weighting is not failover: an invalid ref fails closed for its fraction rather than silently shifting that traffic to the healthy backends. Only when every backend in a rule is unavailable (or all carry weight: 0) does the rule return 500 for all of its traffic. A weight: 0 invalid ref carries no traffic, so it is dropped rather than marked. See Unavailable backends return a status, not a dial error.

Status Conditions

Gateway Conditions

Type Status Reason Description
Accepted True Accepted Gateway accepted by controller
Accepted False ListenersNotValid One or more of the Gateway's own listeners conflict (carry Conflicted=True)
Programmed True Programmed Gateway configured in Cloudflare

Gateway Listener Conditions

Type Status Reason Description
Accepted True Accepted Listener accepted
Accepted False HostnameConflict / ProtocolConflict Listener conflicts with a higher-precedence listener on the same port
Programmed True Programmed Listener programmed
Programmed False Invalid Listener has unresolved references
Programmed False HostnameConflict / ProtocolConflict Listener conflicts with a higher-precedence listener
Conflicted True HostnameConflict / ProtocolConflict Listener clashes with another listener on hostname (same port + hostname) or protocol (different protocol on the same port)
ResolvedRefs True ResolvedRefs References resolved
ResolvedRefs False InvalidCertificateRef TLS certificate reference invalid
ResolvedRefs False RefNotPermitted Cross-namespace TLS ref denied by ReferenceGrant
ResolvedRefs False InvalidRouteKinds Invalid route kind in allowedRoutes

HTTPRoute/GRPCRoute Conditions

Type Status Reason Description
Accepted True Accepted Route accepted and synced
Accepted False NoMatchingParent No matching listener found
Accepted False NoMatchingListenerHostname Route hostnames don't intersect with listener
Accepted False NotAllowedByListeners Route namespace or kind not allowed by listener
Accepted False Conflicted Route lost a cross-route-type conflict (HTTPRoute vs GRPCRoute on a shared Gateway with intersecting hostnames); the oldest Route by creationTimestamp is accepted
ResolvedRefs True ResolvedRefs Backend references resolved
ResolvedRefs False RefNotPermitted Cross-namespace reference denied
ResolvedRefs False BackendNotFound Backend Service not found