This is the "latest" release of Envoy Gateway, which contains the most recent commits from the main branch.
This release might not be stable.
Please refer to the /docs documentation for the most current information.
HTTP3
7 minute read
This task will help you get started using HTTP3 using EG. EG supports HTTP/3 between the client and the Gateway, and HTTP/3 between the Gateway and the backend. The two are configured separately and can be used on their own or together. This task uses a self-signed CA, so it should be used for testing and demonstration purposes only.
HTTP/3 to Clients
HTTP/3 to clients is enabled with the http3 field of a ClientTrafficPolicy. The Gateway then
listens for QUIC on the HTTPS listener’s port and advertises HTTP/3 to clients with an alt-svc
response header.
Prerequisites
- OpenSSL to generate TLS assets.
Installation
Follow the steps below to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP.
Expand for instructions
Install the Gateway API CRDs and Envoy Gateway using Helm:
Gateway API CRD compatibilityThis command installs Gateway API CRDs. If your Kubernetes provider already manages compatible Gateway API CRDs for the cluster, use the provider-managed Gateway API CRD install steps instead.
helm install eg oci://docker.io/envoyproxy/gateway-helm --version v0.0.0-latest -n envoy-gateway-system --create-namespaceInstall the GatewayClass, Gateway, HTTPRoute and example app:
kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/latest/quickstart.yaml -n defaultVerify Connectivity:
Get the External IP of the Gateway:
export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}')Curl the example app through Envoy proxy:
curl --verbose --header "Host: www.example.com" http://$GATEWAY_HOST/getThe above command should succeed with status code 200.
Get the name of the Envoy service created the by the example Gateway:
export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}')Get the deployment of the Envoy service created the by the example Gateway:
export ENVOY_DEPLOYMENT=$(kubectl get deploy -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}')Port forward to the Envoy service:
kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8888:80 &Curl the example app through Envoy proxy:
curl --verbose --header "Host: www.example.com" http://localhost:8888/getThe above command should succeed with status code 200.
TLS Certificates
Generate the certificates and keys used by the Gateway to terminate client TLS connections.
Create a root certificate and private key to sign certificates:
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example.com.key -out example.com.crt
Create a certificate and a private key for www.example.com:
openssl req -out www.example.com.csr -newkey rsa:2048 -nodes -keyout www.example.com.key -subj "/CN=www.example.com/O=example organization"
openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in www.example.com.csr -out www.example.com.crt
Store the cert/key in a Secret:
kubectl create secret tls example-cert --key=www.example.com.key --cert=www.example.com.crt
Update the Gateway from the Quickstart to include an HTTPS listener that listens on port 443 and references the
example-cert Secret:
kubectl patch gateway eg --type=json --patch '
- op: add
path: /spec/listeners/-
value:
name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- kind: Secret
group: ""
name: example-cert
'
Enabling HTTP/3
Apply the following ClientTrafficPolicy to enable HTTP3
cat <<EOF | kubectl apply -f -
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: ClientTrafficPolicy
metadata:
name: enable-http3
spec:
http3: {}
targetRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: eg
EOF
Save and apply the following resource to your cluster:
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: ClientTrafficPolicy
metadata:
name: enable-http3
spec:
http3: {}
targetRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: eg
By default, Envoy Gateway advertises the Gateway listener port in the HTTP/3 alt-svc response header.
If an external load balancer exposes the Gateway on a different port, set advertisedPort to the
external port without changing the listener or Service ports:
spec:
http3:
advertisedPort: 443
Verify the Gateway status:
kubectl get gateway/eg -o yaml
Testing
Get the External IP of the [Gateway][]:
export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}')
Query the example app through the [Gateway][]:
The below example uses a custom docker image with custom curl binary with built-in http3.
docker run --net=host --rm ghcr.io/macbre/curl-http3 curl -kv --http3 -HHost:www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" https://www.example.com/get
It is not possible at the moment to port-forward UDP protocol in kubernetes service check out https://github.com/kubernetes/kubernetes/issues/47862. Hence we need external loadbalancer to test this feature out.
HTTP/3 to Backends
HTTP/3 to the backend is enabled with the http3 field of a BackendTrafficPolicy.
Prerequisites
QUIC always runs over TLS, so the backend must already be configured with TLS through a
BackendTLSPolicy or a Backend resource’s spec.tls. When a BackendTrafficPolicy enables
http3 for a route whose backends are not all configured with TLS, or whose backendRefs cannot all
be resolved, HTTP/3 is left off for that route, the rest of the policy still applies, and the policy
reports a Warning condition naming the route. HTTP/3 comes back on its own once the route’s
backends are all resolved and configured with TLS.
HTTP/3 requires a verified backend. A backend with insecureSkipVerify is left off HTTP/3 with
a Warning condition on the policy. Configure the backend’s CA instead, through a
BackendTLSPolicy or the Backend’s tls.caCertificateRefs.
Enabling HTTP/3
Apply a BackendTrafficPolicy with http3 set to the routes whose backends speak HTTP/3. There
are two modes, Auto and Always:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
name: backend-http3
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: backend
http3:
mode: Auto
Auto Mode
Auto is the default. Envoy uses HTTP/3 only for backends that advertise support for it through an
alt-svc response header. It caches that advertisement, then races a QUIC connection against a TCP
one and uses whichever is established first, so it falls back to HTTP/1.1 or HTTP/2 whenever QUIC is
unavailable. This is the safe choice for backends reached over a network where UDP may be blocked.
Envoy only honors an alt-svc entry whose port is the port it dials the backend on, and that names
no host. For a Service backend that is the Pod IP and targetPort, not the Service port. A backend
that advertises h3=":443" behind a Service that maps port 443 to targetPort 8443 is dialed on
8443, so the advertisement never matches and Auto keeps using TCP. Either have the backend
advertise the port it actually listens on, as in h3=":8443", or give the Service the same port and
targetPort. The same rule applies to a Backend resource: the advertised port must be the
endpoint’s port. The QUIC listener on the backend must also be reachable on that port over UDP.
The backend’s alt-svc header is not forwarded to clients. It names a port on the backend, which a
client would read as a port on the Gateway, so Envoy Gateway strips it after recording it and adds
the Gateway’s own alt-svc when the listener has HTTP/3 enabled. Do not remove alt-svc with an
HTTPRoute ResponseHeaderModifier filter: that runs before the advertisement is recorded, so
Auto mode would never discover the backend’s HTTP/3 support.
Always Mode
Always sends every request over HTTP/3 and never falls back to TCP. Use it only where the backend
is known to speak HTTP/3 and UDP is known to work, since there is no recovery if QUIC fails. Active
health checks are the exception: Envoy sends them over TLS on TCP even in Always mode, so a backend
with an active healthCheck must also accept TCP on the same port, or every endpoint is marked
unhealthy while QUIC traffic still works. Passive health checks observe the QUIC traffic itself and
are unaffected.
Limitations
The EnvoyProxy backendTLS.alpnProtocols setting is not applied to a cluster using HTTP/3. Envoy
offers that list on the QUIC handshake too, where only h3 is valid, so the cluster offers no ALPN
list of its own: QUIC negotiates h3 and the cluster’s TCP connections fall back to h2 and
http/1.1. The policy reports a Warning condition naming the cluster.
http3 cannot be combined with useClientProtocol or proxyProtocol: the first would have Envoy
pick the upstream protocol from the downstream request, and PROXY protocol is a TCP preamble with
no QUIC equivalent. A policy that sets both is rejected at admission. HTTP/3 is also left off, with
the same Warning condition, for backends that declare an HTTP/2 or gRPC appProtocol, since
those ask for a protocol HTTP/3 cannot provide.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.