Docs
Ingress ControllerManage traffic and APIsTraffic ManagementProxy UDP Traffic by Port

Proxy UDP Traffic by Port

Configure APISIX or API7 Ingress Controller to proxy UDP traffic by gateway port to an echo Service.

Applies to:API7 Ingress Controller (drives API7 Gateway)APISIX Ingress Controller (drives Apache APISIX)

Goal

Route UDP traffic to a Kubernetes echo Service based on the incoming gateway port, using either a Gateway API UDPRoute or an APISIX CRD stream route.

Before you begin

  • Complete Set Up Ingress Controller and Gateway.
  • You have kubectl configured against the cluster used in the setup guide.
  • Choose a free UDP gateway stream port. The examples use 9300; change this if it conflicts.

Set the variables this guide uses:

export GATEWAY_SERVICE_NAME="apisix-gateway"   # your gateway's Service name in namespace aic
export GATEWAY_UDP_PORT="9300"

Steps

Step 1: Deploy the example UDP echo upstream

Create a manifest for a UDP echo server that listens on port 9000 in the aic namespace:

udp-echo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: udp-echo
  namespace: aic
spec:
  replicas: 1
  selector:
    matchLabels:
      app: udp-echo
  template:
    metadata:
      labels:
        app: udp-echo
    spec:
      containers:
        - name: udp-echo
          image: python:3-alpine
          command: ["python", "-u", "-c"]
          args:
            - |
              import socket
              sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
              sock.bind(('', 9000))
              print("UDP echo server listening on port 9000")
              while True:
                  data, addr = sock.recvfrom(1024)
                  sock.sendto(data, addr)
          ports:
            - containerPort: 9000
              protocol: UDP
---
apiVersion: v1
kind: Service
metadata:
  name: udp-echo
  namespace: aic
spec:
  selector:
    app: udp-echo
  ports:
    - name: udp
      port: 9000
      targetPort: 9000
      protocol: UDP

Apply the manifest and wait for the Pod to become ready:

kubectl apply -f udp-echo.yaml
kubectl wait --for=condition=ready pod -l app=udp-echo -n aic --timeout=120s

Step 2: Enable the gateway stream proxy

Upgrade the gateway Helm release to enable stream mode and expose UDP port 9300.

helm upgrade -n aic apisix apisix/apisix \
  --reuse-values \
  --set "service.stream.enabled=true" \
  --set "service.stream.udp[0]=${GATEWAY_UDP_PORT}"

Step 3: Configure UDP routing

Create a route that listens for UDP traffic on port 9300.

Add a UDP listener to your existing Gateway manifest:

gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  namespace: aic
  name: apisix
spec:
  gatewayClassName: apisix
  listeners:
  - name: http
    protocol: HTTP
    port: 80
  - name: udp
    protocol: UDP
    port: 9300
    allowedRoutes:
      kinds:
      - kind: UDPRoute
  infrastructure:
    parametersRef:
      group: apisix.apache.org
      kind: GatewayProxy
      name: apisix-config

Create a UDPRoute manifest:

udp-route.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: UDPRoute
metadata:
  name: stream-route-udp
  namespace: aic
spec:
  parentRefs:
  - name: apisix
    sectionName: udp
  rules:
  - backendRefs:
    - name: udp-echo
      port: 9000

Apply both manifests:

kubectl apply -f gateway.yaml -f udp-route.yaml

When listener_port_match_mode is explicit or auto, the sectionName: udp reference adds a server_port match for 9300. The Gateway listener port must equal the physical gateway stream listener port. With the mode set to off, the controller does not add this match.

Step 4: Set the upstream transport scheme

Use udp for a plain UDP backend. L4 schemes apply only to stream routes.

Attach a BackendTrafficPolicy to the backend Service:

udp-upstream-policy.yaml
apiVersion: apisix.apache.org/v1alpha1
kind: BackendTrafficPolicy
metadata:
  name: udp-echo-transport
  namespace: aic
spec:
  targetRefs:
  - group: ""
    kind: Service
    name: udp-echo
    sectionName: udp
  scheme: udp

Apply the policy:

kubectl apply -f udp-upstream-policy.yaml

To attach stream plugins to the UDPRoute, see Apply Plugins to L4 Routes.

Validate

kubectl port-forward supports only TCP, so run a temporary Pod inside the cluster to send UDP packets to the gateway:

kubectl run -it --rm test-udp-proxy --image=busybox --namespace=aic -- /bin/sh

Inside the Pod, send a UDP packet to the gateway Service on the configured port:

echo "UDP Testing" | nc -u -w1 "${GATEWAY_SERVICE_NAME}" "${GATEWAY_UDP_PORT}"

Expected: the message UDP Testing is echoed back.

Roll back / Clean up

Delete the manifests created in this guide:

kubectl delete -f udp-route.yaml
kubectl delete -f gateway.yaml
kubectl delete -f udp-echo.yaml
kubectl delete -f udp-upstream-policy.yaml
kubectl delete -f udp-upstream.yaml

Troubleshoot

SymptomCauseFix
No response from the echo server.The gateway stream proxy is not enabled for UDP, or the UDPRoute parentRefs do not resolve.Confirm the Helm release has service.stream.enabled=true and service.stream.udp[0]=9300 (or the API7 Gateway equivalents), the Gateway listener is named udp and exposes port 9300, and sectionName: udp is present in the UDPRoute.
nc: bad address inside the temporary Pod.The gateway Service name is not reachable from the test Pod's namespace, or DNS is not ready.Verify GATEWAY_SERVICE_NAME matches the gateway Service in namespace aic.
The controller ignores the UDPRoute.The Gateway listener protocol is not UDP, or the listener port does not match the UDPRoute parentRefs.Check the Gateway listener protocol, port, and allowedRoutes.kinds include UDPRoute.