Proxy WebSocket Connections
Configure APISIX or API7 Ingress Controller to proxy WebSocket connections with HTTPRoute or ApisixRoute resources.
Applies to:API7 Ingress Controller (drives API7 Gateway)APISIX Ingress Controller (drives Apache APISIX)
Goal
Enable the gateway to proxy WebSocket connections to a backend Service using a Gateway API HTTPRoute or an APISIX CRD route.
Before you begin
- Complete Set Up Ingress Controller and Gateway.
- Install websocat to verify the WebSocket connection.
- You have
kubectlconfigured against the cluster used in the setup guide. - Choose a free local port for the gateway port-forward. The examples use
9080.
Set the variables this guide uses:
export UPSTREAM_WS_PORT="8080"
export UPSTREAM_APP_PROTOCOL="kubernetes.io/ws"
export WEBSOCKET_PATH="/.ws"
export GATEWAY_SERVICE_NAME="apisix-gateway" # your gateway's Service name in namespace aic
export GATEWAY_HTTP_PORT="80"
export FORWARD_PORT="9080"Steps
Step 1: Deploy the example WebSocket upstream
Create a manifest for the WebSocket echo server in the aic namespace. The server exposes the /.ws endpoint.
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: aic
name: websocket-server
spec:
replicas: 1
selector:
matchLabels:
app: websocket-server
template:
metadata:
labels:
app: websocket-server
spec:
containers:
- name: echo-server
image: jmalloc/echo-server
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: websocket-server
spec:
selector:
app: websocket-server
ports:
- name: ws
port: 8080
targetPort: 8080
protocol: TCP
appProtocol: kubernetes.io/ws
type: ClusterIPApply the manifest and wait for the Pod to become ready:
kubectl apply -f ws-echo.yaml
kubectl wait --for=condition=ready pod -l app=websocket-server -n aic --timeout=120sStep 2: Create the WebSocket route
Create a route that matches the WebSocket path and forwards to the example service:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: ws-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /.ws
backendRefs:
- name: websocket-server
port: 8080HTTPRoute has no route-level WebSocket field. The Ingress Controller reads appProtocol from the referenced Service port and enables the protocol upgrade on the generated route.
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: ws-route
spec:
ingressClassName: apisix
http:
- name: ws-route
match:
paths:
- /.ws
websocket: true
backends:
- serviceName: websocket-server
servicePort: 8080The websocket: true field is sufficient for ApisixRoute even when the Service port does not declare appProtocol. In this example, either setting enables the protocol upgrade.
Apply the manifest:
kubectl apply -f ws-route.yamlValidate
Forward the gateway HTTP port to your local machine:
kubectl port-forward -n aic "svc/${GATEWAY_SERVICE_NAME}" "${FORWARD_PORT}:${GATEWAY_HTTP_PORT}" &Establish a WebSocket connection through the route and send a test message:
websocat "ws://127.0.0.1:${FORWARD_PORT}${WEBSOCKET_PATH}"Type hello and press Enter. Expected output:
Request served by 1cd244052136
hello
helloThe server echoes the message back. You can continue to send more messages; the server echoes each one. This confirms the bidirectional connection is successful and persistent.
Roll back / Clean up
Delete the manifests created in this guide:
kubectl delete -f ws-route.yaml
kubectl delete -f ws-echo.yamlStop the local port-forward process if it is still running:
kill %1 2>/dev/null || trueTroubleshoot
| Symptom | Cause | Fix |
|---|---|---|
websocat returns 200 OK instead of 101 Switching Protocols. | The backend Service does not declare the correct appProtocol, or the ApisixRoute websocket field is false. | Verify the Service port has appProtocol: kubernetes.io/ws (or wss) for HTTPRoute, or websocket: true for ApisixRoute. |
websocat cannot connect. | The route is not accepted or the port-forward is not running. | Check kubectl get httproute ws-route -n aic or kubectl get apisixroute ws-route -n aic, and confirm GATEWAY_SERVICE_NAME and FORWARD_PORT. |
| The echo server stops responding. | The backend Pod or gateway worker was replaced, or the connection was closed. | Open a new websocat connection after any endpoint change. |