feat: pre-warm tailscale path to k3s server on game node start#573
feat: pre-warm tailscale path to k3s server on game node start#573Flegma wants to merge 1 commit into
Conversation
Code reviewNo issues found in the diff. Verified:
Pre-existing, out of scope (already noted in the PR description): the sibling 5stack-panel/game-node-server-setup.sh Lines 197 to 226 in 0be3beb |
After a reboot the Tailscale direct path to the k3s server can come up one-way (tx>0, rx0). tailscaled self-reports healthy (BackendState Running, empty Health), so the existing state-check passes while the agent cannot reach the control plane: k3s-agent hangs validating the connection, no pods schedule, and the node shows Offline in the panel. Add a best-effort ExecStartPre that, when K3S_URL is set, runs a bounded tailscale ping to the server before k3s starts, forcing the direct path to establish bidirectionally. The drop-in lands in whichever k3s unit dir the node uses (k3s-agent.service.d on agents) and is a no-op on server nodes with no upstream. Prefixed with - so a failed pre-warm can never block k3s from starting.
0be3beb to
b42391c
Compare
|
Amended to 5stack-panel/game-node-server-setup.sh Lines 211 to 226 in b42391c |
Problem
When a game/GPU node reboots, the Tailscale direct path to the k3s server can come up one-way (
tx>0, rx 0).tailscaledself-reports healthy (BackendState=Running, emptyHealth), so the existing5stack-tailscale-state-checkpasses every cycle, yet the node cannot actually reach the control plane.k3s-agentthen loops onfailed to get CA certs ... context deadline exceeded, never joins the cluster, no pods (includinggame-server-node-connector) get scheduled, and the node shows Offline in the panel (the connector's 30s Redis heartbeat never fires, so the API's 90s TTL flips it offline).Observed on a live GPU node: stuck ~27 minutes after a reboot. A manual
tailscale ping <server>re-established the path and k3s-agent recovered on its own within one retry.Fix
Add a best-effort
ExecStartPredrop-in (tailscale-prewarm.conf) that runs before k3s starts: ifK3S_URLis set, it does a boundedtailscale pingto the server, forcing Tailscale's NAT traversal to (re)establish the direct path bidirectionally, so k3s-agent never validates against a dead one-way path.k3s-agent.service.don agents), via a one-line check fork3s-agent.service.env.K3S_URL, nothing upstream to reach), so it is safe regardless of role.-and wrapped in|| trueso a failed pre-warm can never block k3s from starting.5stack-tailscale-state-checklogic or the other drop-ins.Testing
K3S_URL=https://100.90.141.113:6443giveshost=100.90.141.113, thenpong ... 21ms.ExecStartPre,systemd-analyze verifywas clean, andk3s-agentstayed active (not restarted).bash -nclean;shellcheckreports no new findings (only pre-existing ones).Scope / follow-ups
Deliberately minimal. Two related things intentionally left out:
5stack-tailscale-state-checkstill only inspects tailscaled's self-reported health, so it will not detect a one-way path during steady state (only the pre-warm at start guards it). A functional reachability probe (TCP to the k3s server) in that check would let a mid-run degradation self-heal too.k3s.service.donly; aligning those with the node's real unit dir is a separate change.