Kubernetes Ingress controllers don’t inherently speak HTTP/3; they’re designed for HTTP/1.1 and HTTP/2.
Let’s see this in action. We’ll use the nginx-ingress controller, a common choice, and configure it to serve an application over HTTP/3.
First, ensure you have a Kubernetes cluster running and kubectl configured. We’ll deploy a simple echoserver application.
apiVersion: apps/v1
kind: Deployment
metadata:
name: echoserver
spec:
replicas: 1
selector:
matchLabels:
app: echoserver
template:
metadata:
labels:
app: echoserver
spec:
containers:
- name: echoserver
image: registry.k8s.io/echoserver:v1.10
ports:
- containerPort: 8080
apiVersion: v1
kind: Service
metadata:
name: echoserver-svc
spec:
selector:
app: echoserver
ports:
- protocol: TCP
port: 80
targetPort: 8080
Now, the core of it: the Ingress resource. For HTTP/3, we need a controller that explicitly supports it. nginx-ingress (the one from kubernetes/ingress-nginx) does. This requires a specific configuration.
First, we need to enable QUIC (the transport protocol for HTTP/3) on the Ingress controller itself. This is typically done via a ConfigMap.
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-configuration
namespace: ingress-nginx # or wherever your controller is installed
data:
use-quic: "true"
quic-listen-port: "8443" # This is the UDP port QUIC will listen on
ssl-protocols: "TLSv1.2 TLSv1.3" # Ensure TLS 1.3 is enabled for QUIC
Apply this ConfigMap:
kubectl apply -f nginx-config.yaml
Next, we define the Ingress resource. For HTTP/3, you must use TLS. The Ingress controller will handle the TLS termination and then proxy to your backend service.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: echoserver-ingress
annotations:
# This annotation tells nginx-ingress to use the QUIC listener
nginx.ingress.kubernetes.io/quic-listen-ports: "8443"
spec:
ingressClassName: nginx # Make sure this matches your ingress controller's class
tls:
- hosts:
- echoserver.example.com # Replace with your actual domain
secretName: echoserver-tls # A Kubernetes Secret containing your TLS cert and key
rules:
- host: echoserver.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: echoserver-svc
port:
number: 80
You’ll need to create the echoserver-tls Secret containing your TLS certificate and private key.
kubectl create secret tls echoserver-tls \
--cert=/path/to/your/tls.crt \
--key=/path/to/your/tls.key \
--namespace default # or the namespace of your Ingress
The nginx-ingress controller, when use-quic: "true" is set in its ConfigMap, will start listening on UDP port 8443 (or whatever quic-listen-port is set to) in addition to its standard TCP ports. When a client attempts to connect via HTTP/3 (which is UDP-based), the controller will negotiate the connection. The nginx.ingress.kubernetes.io/quic-listen-ports annotation ensures that the Ingress resource is configured to accept QUIC connections on that specified port.
The controller then terminates the TLS and forwards the request (over HTTP/1.1 or HTTP/2, as QUIC doesn’t carry the HTTP version itself, but rather the HTTP/3 framing) to your echoserver-svc.
To test this, you’ll need a client that supports HTTP/3. Most modern browsers (Chrome, Firefox) do. You can also use curl with the --http3 flag.
# Ensure you have DNS set up for echoserver.example.com to point to your Ingress controller's IP
curl --http3 -v https://echoserver.example.com/
You should see output indicating a successful connection, and potentially messages about the HTTP/3 protocol being used.
The most surprising thing about HTTP/3 is that it’s not an upgrade to HTTP/2 in the same way HTTP/2 was to HTTP/1.1; it’s a complete reimagining of the transport layer, moving from TCP to UDP. This is why it’s often called "HTTP over QUIC."
The mental model here is that your Ingress controller is now a dual-protocol endpoint. It handles both traditional TCP-based HTTP/1.1 and HTTP/2, and UDP-based HTTP/3. The configuration maps the HTTP/3 connection attempts to the appropriate TLS termination and backend routing. The ingressClassName ensures the correct controller picks up the Ingress resource. The tls section is mandatory because QUIC, by design, requires encryption.
What most people don’t realize is that nginx-ingress (and many other HTTP/3 capable ingress controllers) doesn’t actually speak HTTP/3 end-to-end to the backend. It terminates the QUIC/HTTP/3 connection at the ingress controller and then proxies the request to the backend service using HTTP/1.1 or HTTP/2 over TCP. The benefit of HTTP/3 is realized in the connection establishment and transport efficiency between the client and the ingress controller, especially over lossy networks.
The next hurdle you’ll likely face is understanding how to properly configure DNS and firewall rules to allow UDP traffic on the QUIC port to reach your Ingress controller pods.