added peti hetzner

This commit is contained in:
2026-06-08 12:29:05 +02:00
parent 4e86091f7d
commit 2be14ac72e
+74 -39
View File
@@ -154,63 +154,87 @@ data:
set -u
SHARED=/shared
HDR=/scripts/metrics-header.prom
HETZNER="${HETZNER_HOST:?set HETZNER_HOST}"
# Space-separated endpoint labels. For each LABEL there must be an env var
# <LABEL>_HOST (uppercased) and optionally <LABEL>_HMAC.
ENDPOINTS="${ENDPOINTS:-hetzner}"
# Subset of ENDPOINTS that also get iperf3 throughput tests (the data-heavy part).
TPUT_ENDPOINTS="${TPUT_ENDPOINTS:-$ENDPOINTS}"
IRTT_PORT="${IRTT_PORT:-2112}"
IPERF_PORT="${IPERF_PORT:-5201}"
IRTT_INTERVAL="${IRTT_INTERVAL:-20ms}"
IRTT_DURATION="${IRTT_DURATION:-60}" # seconds (numeric, for timeout math)
TPUT_EVERY="${TPUT_EVERY:-900}" # seconds between throughput tests
TPUT_TIME="${TPUT_TIME:-10}" # iperf3 seconds per direction
IRTT_TARGET="${IRTT_TARGET:-hetzner}"
TPUT_TARGET="${TPUT_TARGET:-hetzner}"
HMAC_OPT=""
[ -n "${IRTT_HMAC:-}" ] && HMAC_OPT="--hmac=${IRTT_HMAC}"
IPERF_PARALLEL="${IPERF_PARALLEL:-4}" # parallel streams: one can't fill the pipe over the RTT
upper() { echo "$1" | tr '[:lower:]' '[:upper:]'; }
host_for() { U="$(upper "$1")"; eval "printf '%s' \"\${${U}_HOST:-}\""; }
hmac_for() { U="$(upper "$1")"; eval "printf '%s' \"\${${U}_HMAC:-}\""; }
mkdir -p "$SHARED"
: > "$SHARED/.irtt.prom"; : > "$SHARED/.irttload.prom"; : > "$SHARED/.tput.prom"
FRAGMENTS=""
for ep in $ENDPOINTS; do
: > "$SHARED/.irtt.$ep.prom"
: > "$SHARED/.irttload.$ep.prom"
: > "$SHARED/.tput.$ep.prom"
FRAGMENTS="$FRAGMENTS $SHARED/.irtt.$ep.prom $SHARED/.irttload.$ep.prom $SHARED/.tput.$ep.prom"
done
cp "$HDR" "$SHARED/metrics" # serve header immediately so first scrapes don't 404
# Concatenate fragments into the served file via temp + atomic rename.
# Concatenate header + all fragments into the served file via temp + atomic rename.
assemble() {
cat "$HDR" "$SHARED/.irtt.prom" "$SHARED/.irttload.prom" "$SHARED/.tput.prom" \
> "$SHARED/.metrics.tmp" 2>/dev/null
cat "$HDR" $FRAGMENTS > "$SHARED/.metrics.tmp" 2>/dev/null
mv "$SHARED/.metrics.tmp" "$SHARED/metrics"
}
# Each fragment is written to <file>.tmp then renamed, so assemble() never
# cats a partially written file (the cause of the impossible loss spikes).
run_irtt() { # $1 condition $2 outfile $3 duration(seconds)
timeout "$(( $3 + 25 ))" irtt client -i "$IRTT_INTERVAL" -d "${3}s" -q $HMAC_OPT \
-o - "${HETZNER}:${IRTT_PORT}" 2>/dev/null \
| python3 /scripts/irtt_to_prom.py "$1" "$IRTT_TARGET" > "$2.tmp"
mv "$2.tmp" "$2"
# $1 condition $2 label $3 host $4 hmac $5 outfile $6 duration(seconds)
# Writes <outfile>.tmp then renames, so assemble() never cats a partial file.
run_irtt() {
hmopt=""
[ -n "$4" ] && hmopt="--hmac=$4"
timeout "$(( $6 + 25 ))" irtt client -i "$IRTT_INTERVAL" -d "${6}s" -q $hmopt \
-o - "$3:${IRTT_PORT}" 2>/dev/null \
| python3 /scripts/irtt_to_prom.py "$1" "$2" > "$5.tmp"
mv "$5.tmp" "$5"
}
# $1 label $2 host
run_tput() {
P="${IPERF_PARALLEL:-4}" # parallel streams: a single stream can't fill the pipe over the RTT
TO="$(( TPUT_TIME + 20 ))"
TMP="$SHARED/.tput.prom.partial"
TMP="$SHARED/.tput.$1.partial"
: > "$TMP"
timeout "$TO" iperf3 -c "$HETZNER" -p "$IPERF_PORT" -t "$TPUT_TIME" -P "$P" --connect-timeout 5000 -R -J 2>/dev/null \
| python3 /scripts/tput_to_prom.py download "$TPUT_TARGET" > "$TMP"
timeout "$TO" iperf3 -c "$HETZNER" -p "$IPERF_PORT" -t "$TPUT_TIME" -P "$P" --connect-timeout 5000 -J 2>/dev/null \
| python3 /scripts/tput_to_prom.py upload "$TPUT_TARGET" >> "$TMP"
mv "$TMP" "$SHARED/.tput.prom"
timeout "$TO" iperf3 -c "$2" -p "$IPERF_PORT" -t "$TPUT_TIME" -P "$IPERF_PARALLEL" --connect-timeout 5000 -R -J 2>/dev/null \
| python3 /scripts/tput_to_prom.py download "$1" > "$TMP"
timeout "$TO" iperf3 -c "$2" -p "$IPERF_PORT" -t "$TPUT_TIME" -P "$IPERF_PARALLEL" --connect-timeout 5000 -J 2>/dev/null \
| python3 /scripts/tput_to_prom.py upload "$1" >> "$TMP"
mv "$TMP" "$SHARED/.tput.$1.prom"
}
last_tput=0
while true; do
run_irtt idle "$SHARED/.irtt.prom" "$IRTT_DURATION" # blocks ~IRTT_DURATION = loop cadence
# idle irtt to every endpoint in parallel (both paths sampled at the same instant)
for ep in $ENDPOINTS; do
h="$(host_for "$ep")"; [ -z "$h" ] && continue
run_irtt idle "$ep" "$h" "$(hmac_for "$ep")" "$SHARED/.irtt.$ep.prom" "$IRTT_DURATION" &
done
wait
assemble
now=$(date +%s)
if [ $(( now - last_tput )) -ge "$TPUT_EVERY" ]; then
LOAD_DUR=$(( 2 * TPUT_TIME + 4 ))
run_irtt under_load "$SHARED/.irttload.prom" "$LOAD_DUR" & # concurrent = bufferbloat
for ep in $TPUT_ENDPOINTS; do
h="$(host_for "$ep")"; [ -z "$h" ] && continue
# concurrent under-load irtt to the same endpoint = bufferbloat
run_irtt under_load "$ep" "$h" "$(hmac_for "$ep")" "$SHARED/.irttload.$ep.prom" "$LOAD_DUR" &
LOADPID=$!
run_tput
run_tput "$ep" "$h"
wait "$LOADPID" 2>/dev/null
last_tput="$now"
assemble
done
last_tput="$now"
fi
done
---
@@ -266,11 +290,28 @@ spec:
image: gitea.dooplex.hu/admin/wan-probe:0.1.0
command: ["/bin/sh", "/scripts/probe-loop.sh"]
env:
- name: ENDPOINTS
value: "hetzner abonet" # space-separated endpoint labels
# - name: TPUT_ENDPOINTS
# value: "hetzner" # uncomment to keep iperf3 OFF the abonet VM (saves its egress)
- name: HETZNER_HOST
# MUST be the Hetzner origin: a DNS-only (grey-cloud) record or raw IP.
# NOT the Cloudflare-proxied jarrs.eu — CF only forwards HTTP/HTTPS, so
# UDP 2112 (irtt) / TCP 5201 (iperf3) never reach the origin behind it.
value: "metrics.jarrs.eu" # DNS-only A record -> Hetzner IPv4
# MUST be the origin (DNS-only record or raw IP), NOT a Cloudflare-proxied
# name -- CF only forwards HTTP/HTTPS, so UDP 2112 / TCP 5201 never arrive.
value: "metrics.jarrs.eu"
- name: ABONET_HOST
value: "hetzner.abonet.hu" # colleague's VM (verify it's a direct A record, not CF-proxied)
- name: HETZNER_HMAC
valueFrom:
secretKeyRef:
name: wan-monitor-irtt
key: hetzner
optional: true
- name: ABONET_HMAC
valueFrom:
secretKeyRef:
name: wan-monitor-irtt
key: abonet
optional: true
- name: IRTT_PORT
value: "2112"
- name: IPERF_PORT
@@ -278,19 +319,13 @@ spec:
- name: IRTT_INTERVAL
value: "20ms"
- name: IRTT_DURATION
value: "60" # seconds (numeric)
value: "60"
- name: TPUT_EVERY
value: "900" # 15 min
value: "900"
- name: TPUT_TIME
value: "10"
- name: IPERF_PARALLEL
value: "4"
- name: IRTT_HMAC # shared key; apply via secret (see below)
valueFrom:
secretKeyRef:
name: wan-monitor-irtt
key: hmac
optional: true
resources:
requests: { cpu: 20m, memory: 48Mi }
limits: { memory: 96Mi }