Skip to content

Commit 34b8b0b

Browse files
committed
High throughput tunnel example
Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
1 parent 5a7ac57 commit 34b8b0b

2 files changed

Lines changed: 250 additions & 0 deletions

File tree

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
# High throughput tunnels
2+
3+
Use this pattern when a customer has several long-lived TCP services and you
4+
want a single inlets uplink client process to carry them.
5+
6+
The same approach also works well for RDP, VNC, SSH, Postgres, Redis, and other
7+
long-lived TCP connections. We will use RTSP for this tutorial.
8+
9+
With [demux](/uplink/troubleshooting/#demux-mode) enabled, inlets-pro opens a
10+
separate websocket for each incoming TCP connection.
11+
12+
This tutorial runs three [MediaMTX](https://github.com/bluenviron/mediamtx)
13+
instances on a private host and exposes their
14+
[RTSP](https://en.wikipedia.org/wiki/Real-Time_Streaming_Protocol) streams
15+
through one Uplink tunnel.
16+
17+
```text
18+
+--------------------------------------+ +--------------------------------------+
19+
| Private host | | Uplink cluster |
20+
| | | |
21+
| MediaMTX #1 rtsp://127.0.0.1:8551 | | Service: mediamtx.streams.svc |
22+
| MediaMTX #2 rtsp://127.0.0.1:8552 | | Ports: 8551, 8552, 8553 |
23+
| MediaMTX #3 rtsp://127.0.0.1:8553 | | |
24+
| | | Cluster clients or port-forward |
25+
| \ | / | | |
26+
| \ | / | | rtsp://mediamtx.streams:8551/stream |
27+
| inlets-pro client --demux |===>| rtsp://mediamtx.streams:8552/stream |
28+
| | | rtsp://mediamtx.streams:8553/stream |
29+
+--------------------------------------+ +--------------------------------------+
30+
```
31+
32+
For testing, we will use a sample `demo.mp4` video file instead of a real
33+
camera feed.
34+
35+
## Prerequisites
36+
37+
- Inlets Uplink installed in your cluster
38+
- `inlets-pro` 0.11.11 or newer on the private host
39+
- `mediamtx` and `ffmpeg` on the private host
40+
- The tunnel plugin for the `inlets-pro` CLI
41+
42+
Install the tunnel plugin:
43+
44+
```bash
45+
inlets-pro plugin get tunnel
46+
```
47+
48+
You can install the host tools with
49+
[arkade](https://github.com/alexellis/arkade), or via your package manager:
50+
51+
```bash
52+
arkade get inlets-pro
53+
arkade get mediamtx
54+
```
55+
56+
Set the values used below:
57+
58+
```bash
59+
export NS="streams"
60+
export TUNNEL="mediamtx"
61+
export DOMAIN="uplink.example.com"
62+
```
63+
64+
## Create the tunnel
65+
66+
Create one Tunnel resource with three TCP ports.
67+
68+
Demux is enabled on the tunnel server with `uplink_demux=1`.
69+
70+
```yaml
71+
apiVersion: uplink.inlets.dev/v1alpha1
72+
kind: Tunnel
73+
metadata:
74+
name: mediamtx
75+
namespace: streams
76+
spec:
77+
licenseRef:
78+
name: inlets-uplink-license
79+
namespace: streams
80+
env:
81+
uplink_demux: "1"
82+
tcpPorts:
83+
- 8551
84+
- 8552
85+
- 8553
86+
```
87+
88+
Apply it:
89+
90+
```bash
91+
kubectl apply -f mediamtx-tunnel.yaml
92+
kubectl get -n $NS tunnel/$TUNNEL
93+
```
94+
95+
Wait for the tunnel server to start:
96+
97+
```bash
98+
kubectl rollout status -n $NS deploy/$TUNNEL
99+
```
100+
101+
## Run MediaMTX
102+
103+
On the private host, create a config directory:
104+
105+
```bash
106+
mkdir -p ~/mediamtx-rtsp
107+
```
108+
109+
Create three MediaMTX config files. Each instance listens on a different RTSP
110+
port and has every other protocol disabled.
111+
112+
```bash
113+
for i in 1 2 3; do
114+
port=$((8550+i))
115+
116+
cat > ~/mediamtx-rtsp/rtsp-$i.yml <<EOF
117+
logLevel: info
118+
rtsp: yes
119+
rtspTransports: [tcp]
120+
rtspAddress: :$port
121+
rtmp: no
122+
hls: no
123+
webrtc: no
124+
srt: no
125+
paths:
126+
stream:
127+
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
128+
runOnInitRestart: yes
129+
EOF
130+
done
131+
```
132+
133+
Replace `./demo.mp4` with your own video file.
134+
135+
Start the three servers:
136+
137+
```bash
138+
cd ~/mediamtx-rtsp
139+
140+
mediamtx rtsp-1.yml &
141+
mediamtx rtsp-2.yml &
142+
mediamtx rtsp-3.yml &
143+
```
144+
145+
Check that each stream is available locally:
146+
147+
```bash
148+
for port in 8551 8552 8553; do
149+
ffprobe -v error \
150+
-rtsp_transport tcp \
151+
-select_streams v:0 \
152+
-show_entries stream=codec_name \
153+
-of default=nw=1:nk=1 \
154+
rtsp://127.0.0.1:$port/stream
155+
done
156+
```
157+
158+
You should see `h264` three times.
159+
160+
## Connect one client
161+
162+
Get the tunnel token:
163+
164+
```bash
165+
inlets-pro tunnel token $TUNNEL \
166+
--namespace $NS > token.txt
167+
```
168+
169+
Run one inlets-pro client with three TCP upstreams:
170+
171+
```bash
172+
inlets-pro uplink client \
173+
--url wss://$DOMAIN/$NS/$TUNNEL \
174+
--token-file ./token.txt \
175+
--upstream 8551=127.0.0.1:8551 \
176+
--upstream 8552=127.0.0.1:8552 \
177+
--upstream 8553=127.0.0.1:8553 \
178+
--demux
179+
```
180+
181+
The left side of each `--upstream` is the tunnel port in Kubernetes. The right
182+
side is the private host address.
183+
184+
## Test from the cluster
185+
186+
Create a temporary probe pod:
187+
188+
```bash
189+
kubectl run -n $NS rtsp-probe \
190+
--image=alpine:latest \
191+
--restart=Never \
192+
--command -- sleep 3600
193+
194+
kubectl exec -n $NS rtsp-probe -- \
195+
apk add --no-cache ffmpeg
196+
```
197+
198+
Probe all three streams through the same tunnel:
199+
200+
```bash
201+
for port in 8551 8552 8553; do
202+
kubectl exec -n $NS rtsp-probe -- \
203+
ffprobe -v error \
204+
-rtsp_transport tcp \
205+
-select_streams v:0 \
206+
-show_entries stream=codec_name \
207+
-of default=nw=1:nk=1 \
208+
rtsp://$TUNNEL.$NS.svc.cluster.local:$port/stream
209+
done
210+
```
211+
212+
You should see `h264` for each port.
213+
214+
## View with port-forward
215+
216+
The Service is cluster-local. To view the streams from your laptop, forward the
217+
three service ports:
218+
219+
```bash
220+
kubectl port-forward -n $NS svc/$TUNNEL \
221+
8551:8551 \
222+
8552:8552 \
223+
8553:8553
224+
```
225+
226+
Then open any of the streams with VLC, ffplay, or ffprobe:
227+
228+
```bash
229+
ffplay -rtsp_transport tcp rtsp://127.0.0.1:8551/stream
230+
ffplay -rtsp_transport tcp rtsp://127.0.0.1:8552/stream
231+
ffplay -rtsp_transport tcp rtsp://127.0.0.1:8553/stream
232+
```
233+
234+
If a local port is already in use, change only the left-hand side:
235+
236+
```bash
237+
kubectl port-forward -n $NS svc/$TUNNEL 18551:8551
238+
ffplay -rtsp_transport tcp rtsp://127.0.0.1:18551/stream
239+
```
240+
241+
## Notes
242+
243+
- Use `rtspTransports: [tcp]` when running several MediaMTX instances on one
244+
host. Otherwise each instance also tries to bind the default RTP and RTCP UDP
245+
ports.
246+
- Demux is useful for RTSP because every viewer gets its own websocket through
247+
the tunnel.
248+
- The tunnel remains cluster-local unless you expose it with a Service,
249+
Ingress, or LoadBalancer.

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ nav:
133133
- Billing Management API: uplink/billing-management-api.md
134134
- Troubleshooting: uplink/troubleshooting.md
135135
- Tutorials:
136+
- High throughput tunnels: uplink/tutorials/high-throughput-tunnels.md
136137
- Remote cluster management with ArgoCD: uplink/tutorials/argo-cd.md
137138

138139
- Inlets Cloud:

0 commit comments

Comments
 (0)