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
kubectlconfigured 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:
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: UDPApply 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=120sStep 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}"helm upgrade -n aic api7-ee-3-gateway api7/gateway \
--reuse-values \
--set "gateway.stream.enabled=true" \
--set "gateway.stream.only=false" \
--set "gateway.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:
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-configCreate a UDPRoute manifest:
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: 9000Apply both manifests:
kubectl apply -f gateway.yaml -f udp-route.yamlWhen 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.
Create a stream route manifest:
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: stream-route-udp
namespace: aic
spec:
ingressClassName: apisix
stream:
- name: stream-route-udp
protocol: UDP
match:
ingressPort: 9300
backend:
serviceName: udp-echo
servicePort: 9000Apply the manifest:
kubectl apply -f udp-route.yamlStep 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:
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: udpApply the policy:
kubectl apply -f udp-upstream-policy.yamlCreate an ApisixUpstream with the same name as the backend Service:
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
name: udp-echo
namespace: aic
spec:
ingressClassName: apisix
scheme: udpApply the upstream configuration:
kubectl apply -f udp-upstream.yamlTo 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/shInside 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.yamlTroubleshoot
| Symptom | Cause | Fix |
|---|---|---|
| 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. |