High throughput tunnels¶
Use this pattern when a customer has several long-lived TCP services and you want a single inlets uplink client process to carry them.
The same approach also works well for RDP, VNC, SSH, Postgres, Redis, and other long-lived TCP connections. We will use RTSP for this tutorial.
With demux enabled, inlets-pro opens a separate websocket for each incoming TCP connection.
This tutorial runs three MediaMTX instances on a private host and exposes their RTSP streams through one Uplink tunnel.
+--------------------------------------+ +--------------------------------------+
| Private host | | Uplink cluster |
| | | |
| MediaMTX #1 rtsp://127.0.0.1:8551 | | Service: mediamtx.streams.svc |
| MediaMTX #2 rtsp://127.0.0.1:8552 | | Ports: 8551, 8552, 8553 |
| MediaMTX #3 rtsp://127.0.0.1:8553 | | |
| | | Cluster clients or port-forward |
| \ | / | | |
| \ | / | | rtsp://mediamtx.streams:8551/stream |
| inlets-pro client --demux |===>| rtsp://mediamtx.streams:8552/stream |
| | | rtsp://mediamtx.streams:8553/stream |
+--------------------------------------+ +--------------------------------------+
For testing, we will use a sample demo.mp4 video file instead of a real
camera feed.
Prerequisites¶
- Inlets Uplink installed in your cluster
inlets-pro0.11.11 or newer on the private hostmediamtxandffmpegon the private host- The tunnel plugin for the
inlets-proCLI
Install the tunnel plugin:
inlets-pro plugin get tunnel
You can install the host tools with arkade, or via your package manager:
arkade get inlets-pro
arkade get mediamtx
Set the values used below:
export NS="streams"
export TUNNEL="mediamtx"
export DOMAIN="uplink.example.com"
Create the tunnel¶
Create one Tunnel resource with three TCP ports.
Demux is enabled on the tunnel server with uplink_demux=1.
apiVersion: uplink.inlets.dev/v1alpha1
kind: Tunnel
metadata:
name: mediamtx
namespace: streams
spec:
licenseRef:
name: inlets-uplink-license
namespace: streams
env:
uplink_demux: "1"
tcpPorts:
- 8551
- 8552
- 8553
Apply it:
kubectl apply -f mediamtx-tunnel.yaml
kubectl get -n $NS tunnel/$TUNNEL
Wait for the tunnel server to start:
kubectl rollout status -n $NS deploy/$TUNNEL
Run MediaMTX¶
On the private host, create a config directory:
mkdir -p ~/mediamtx-rtsp
Create three MediaMTX config files. Each instance listens on a different RTSP port and has every other protocol disabled.
for i in 1 2 3; do
port=$((8550+i))
cat > ~/mediamtx-rtsp/rtsp-$i.yml <<EOF
logLevel: info
rtsp: yes
rtspTransports: [tcp]
rtspAddress: :$port
rtmp: no
hls: no
webrtc: no
srt: no
paths:
stream:
runOnInit: ffmpeg -hide_banner -loglevel warning -re -stream_loop -1 -i ./demo.mp4 -c:v libx264 -preset ultrafast -tune zerolatency -g 30 -keyint_min 30 -c:a aac -rtsp_transport tcp -f rtsp rtsp://127.0.0.1:$port/stream
runOnInitRestart: yes
EOF
done
Replace ./demo.mp4 with your own video file.
Start the three servers:
cd ~/mediamtx-rtsp
mediamtx rtsp-1.yml &
mediamtx rtsp-2.yml &
mediamtx rtsp-3.yml &
Check that each stream is available locally:
for port in 8551 8552 8553; do
ffprobe -v error \
-rtsp_transport tcp \
-select_streams v:0 \
-show_entries stream=codec_name \
-of default=nw=1:nk=1 \
rtsp://127.0.0.1:$port/stream
done
You should see h264 three times.
Connect one client¶
Get the tunnel token:
inlets-pro tunnel token $TUNNEL \
--namespace $NS > token.txt
Run one inlets-pro client with three TCP upstreams:
inlets-pro uplink client \
--url wss://$DOMAIN/$NS/$TUNNEL \
--token-file ./token.txt \
--upstream 8551=127.0.0.1:8551 \
--upstream 8552=127.0.0.1:8552 \
--upstream 8553=127.0.0.1:8553 \
--demux
The left side of each --upstream is the tunnel port in Kubernetes. The right
side is the private host address.
Test from the cluster¶
Create a temporary probe pod:
kubectl run -n $NS rtsp-probe \
--image=alpine:latest \
--restart=Never \
--command -- sleep 3600
kubectl exec -n $NS rtsp-probe -- \
apk add --no-cache ffmpeg
Probe all three streams through the same tunnel:
for port in 8551 8552 8553; do
kubectl exec -n $NS rtsp-probe -- \
ffprobe -v error \
-rtsp_transport tcp \
-select_streams v:0 \
-show_entries stream=codec_name \
-of default=nw=1:nk=1 \
rtsp://$TUNNEL.$NS.svc.cluster.local:$port/stream
done
You should see h264 for each port.
View with port-forward¶
The Service is cluster-local. To view the streams from your laptop, forward the three service ports:
kubectl port-forward -n $NS svc/$TUNNEL \
8551:8551 \
8552:8552 \
8553:8553
Then open any of the streams with VLC, ffplay, or ffprobe:
ffplay -rtsp_transport tcp rtsp://127.0.0.1:8551/stream
ffplay -rtsp_transport tcp rtsp://127.0.0.1:8552/stream
ffplay -rtsp_transport tcp rtsp://127.0.0.1:8553/stream
If a local port is already in use, change only the left-hand side:
kubectl port-forward -n $NS svc/$TUNNEL 18551:8551
ffplay -rtsp_transport tcp rtsp://127.0.0.1:18551/stream
Notes¶
- Use
rtspTransports: [tcp]when running several MediaMTX instances on one host. Otherwise each instance also tries to bind the default RTP and RTCP UDP ports. - Demux is useful for RTSP because every viewer gets its own websocket through the tunnel.
- The tunnel remains cluster-local unless you expose it with a Service, Ingress, or LoadBalancer.