Add haproxy proxy: /metrics returns 200 empty, everything else proxies to SGLang
SGLang now runs on port+1, haproxy binds the original vLLM port. haproxy serves a stub /metrics endpoint (200, empty body) and passes all other traffic through to SGLang via raw TCP proxy.
This commit is contained in:
76
vllm-shim.sh
76
vllm-shim.sh
@@ -5,6 +5,12 @@ set -euo pipefail
|
||||
# vLLM -> SGLang shim
|
||||
# This script replaces the vllm binary. The k8s production stack
|
||||
# calls `vllm serve <model> [flags]`, and we intercept everything.
|
||||
#
|
||||
# Architecture:
|
||||
# haproxy on the vLLM port (front door)
|
||||
# /metrics → 200 empty response
|
||||
# /* → proxy to SGLang on port+1
|
||||
# SGLang on port+1 (internal)
|
||||
# ============================================================
|
||||
|
||||
echo ""
|
||||
@@ -22,6 +28,20 @@ done
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
# Log to file
|
||||
LOG_PATH="${VLLM_SHIM_LOG:-/tmp/vllm-shim.log}"
|
||||
{
|
||||
echo "$(date -Iseconds) vLLM -> SGLang Shim (shell)"
|
||||
echo " Invoked as: vllm $*"
|
||||
echo " All arguments received:"
|
||||
i=1
|
||||
for arg in "$@"; do
|
||||
echo " [$i] $arg"
|
||||
i=$((i + 1))
|
||||
done
|
||||
echo ""
|
||||
} >> "$LOG_PATH"
|
||||
|
||||
# Defaults
|
||||
HOST="0.0.0.0"
|
||||
PORT="8000"
|
||||
@@ -38,12 +58,60 @@ while [[ $# -gt 0 ]]; do
|
||||
esac
|
||||
done
|
||||
|
||||
echo "Launching SGLang on ${HOST}:${PORT}"
|
||||
# SGLang runs one port higher; haproxy binds the original port
|
||||
SGLANG_PORT=$((PORT + 1))
|
||||
|
||||
echo "Launching SGLang on ${HOST}:${SGLANG_PORT} (internal)"
|
||||
echo "Launching haproxy on ${HOST}:${PORT} (front door, /metrics stub)"
|
||||
echo ""
|
||||
|
||||
exec python -m sglang.launch_server \
|
||||
# Write haproxy config
|
||||
HAPROXY_CFG="/tmp/haproxy-shim.cfg"
|
||||
cat > "$HAPROXY_CFG" <<EOF
|
||||
global
|
||||
log /dev/log local0
|
||||
maxconn 4096
|
||||
|
||||
defaults
|
||||
mode http
|
||||
timeout connect 5s
|
||||
timeout client 300s
|
||||
timeout server 300s
|
||||
|
||||
frontend proxy
|
||||
bind ${HOST}:${PORT}
|
||||
http-request return status 200 content-type text/plain "" if { path /metrics }
|
||||
default_backend sglang
|
||||
|
||||
backend sglang
|
||||
server s1 127.0.0.1:${SGLANG_PORT}
|
||||
EOF
|
||||
|
||||
echo "haproxy config written to ${HAPROXY_CFG}" >> "$LOG_PATH"
|
||||
|
||||
# Start SGLang in the background
|
||||
python -m sglang.launch_server \
|
||||
--model-path mistralai/Devstral-2-123B-Instruct-2512 \
|
||||
--host "$HOST" \
|
||||
--port "$PORT" \
|
||||
--port "$SGLANG_PORT" \
|
||||
--tp 8 \
|
||||
--tool-call-parser mistral
|
||||
--tool-call-parser mistral &
|
||||
|
||||
SGLANG_PID=$!
|
||||
|
||||
# Give SGLang a moment to start before haproxy starts routing
|
||||
sleep 2
|
||||
|
||||
# Start haproxy in the foreground (this is now PID 1 for the container)
|
||||
haproxy -f "$HAPROXY_CFG" &
|
||||
|
||||
HAPROXY_PID=$!
|
||||
|
||||
echo "SGLang PID: ${SGLANG_PID}, haproxy PID: ${HAPROXY_PID}" >> "$LOG_PATH"
|
||||
|
||||
# Wait for whichever dies first — if either goes, we go
|
||||
wait -n "$SGLANG_PID" "$HAPROXY_PID"
|
||||
EXIT_CODE=$?
|
||||
echo "A process exited (code ${EXIT_CODE}), shutting down" >> "$LOG_PATH"
|
||||
kill "$SGLANG_PID" "$HAPROXY_PID" 2>/dev/null || true
|
||||
exit $EXIT_CODE
|
||||
|
||||
Reference in New Issue
Block a user