Files
HiveGrid-Wireframes/03 Quellen und Referenzen/hivegrid-cloud/docs/ops/ci-runner-node1.md
T
2026-07-08 16:15:37 +02:00

4.0 KiB

CI-Runner auf node1 + CI-Pipeline-Overhaul (2026-06-28)

Operativer Record der CI-Umstellung. Runner-Host-Themen gehören mittelfristig auch nach infra/LESSONS.md (Infra-Repo, Akeshan-Domain) — hier dokumentiert, weil die .gitea/workflows/-Änderungen in diesem Repo liegen.

Warum: Homeserver OOMte unter paralleler CI

Der geteilte Homeserver (32 GB RAM, neben anderen Diensten ~17 GB belegt) ist bei paralleler CI wiederholt abgestürzt: parallele Jobs spikten den RAM auf 30+/32 GB, CPU auf 100%, der Linux-OOM-Killer riss den größten Job → Crash-Recover-Schleife (Runner grabbte sofort den nächsten Job). Parallelisierung auf der geteilten Box war der falsche Hebel.

Lösung: node1 als dedizierter CI-Runner

node1 (176.9.111.179, eigener Hetzner-Dedi mit self-hosted Sentry, 20 Kerne / 62 GB) ist Mesh-Peer und erreicht Gitea über 10.42.0.2. Gitea-Server bleibt, wo er ist — nur die Runner-Last zieht um.

  • Compose: /opt/stacks/gitea-ci-runner/docker-compose.yml (network_mode: host, --add-host git.tool-ctrl.de:10.42.0.2, CONFIG_FILE=/data/config.yaml).
  • Config: /srv/data/gitea-ci-runner/config.yaml (capacity, labels, cache.dir).
  • Homeserver-Runner steht auf restart=no (aus, kein Auto-Restart, keine OOM-Schleife).

act_runner-Footguns (alle real getroffen)

Symptom Ursache Fix
runner.capacity wird ignoriert run.sh überschreibt den compose-command, läuft ohne --config env CONFIG_FILE=/data/config.yaml setzen
"no matching runner online with label toolctrl-ci" leere runner.labels → KEIN Fallback auf .runner Labels EXPLIZIT in config.yaml
Daemon "token is empty" trotz erfolgreicher Registrierung act_runner register schrieb .runner ins Container-CWD → bei --rm weg docker run -w /data ... beim Register
Register "instance address is empty" run.sh ignoriert CLI-Args, nutzt leeres GITEA_INSTANCE_URL --entrypoint act_runner umgeht run.sh
pnpm-Store-Cache greift nie (Cache-Dir 12K) cache.dir default ephemer im Container, Restarts wischen ihn cache.dir: /data/actcache (gemountet)

Capacity-Findings (empirisch gemessen)

Setup Wallclock RAM-Peak frei Notiz
cap 4, docker-smoke auf Tail ~10m 35 GB
cap 6 ~8m 23-25 GB
cap 6 + docker-smoke parallel ~7m35s 23 GB
cap 8 + docker-smoke parallel ~6m53s 25 GB Sweet-Spot

cap 8 ist schneller als cap 6 trotz mehr Contention: Install/Netzwerk/Docker sind I/O-bound, die 20 Kerne tragen 8 Jobs; die Queueing-Reduktion schlägt die Mehr-Contention. cap >8 bringt nichts (Kerne saturiert). Reise gesamt: ~32m → ~6m53s.

Pipeline-Änderungen (.gitea/workflows/)

  • docker-smoke needs entfernt → läuft parallel zur Quality-Phase (baut Images aus Source, keine Cross-Job-Artefakt-Abhängigkeit), raus aus dem kritischen Tail.
  • Sentry-Release-Jobs aus ci.yml entfernt (ci.yml läuft nur auf pull_request; ein PR-Build wird nirgends deployed → die Release/Sourcemaps mappen auf keine Deployment). Release passiert in deploy.yml (push→main / promote).

Install-Diagnose (warum KEIN Deps-Image)

Gemessen: Install = ~43s Download + ~15s Link (warmer Store). Die ~2-min-Annahme war zu hoch. Ein Deps-Image würde nur die 15s Link sparen → verworfen. Der Hebel war der kalte Store (Cache persistierte nicht) → mit cache.dir gefixt.

Offene Punkte

  • Sourcemaps im Deploy: web nutzt @sentry/vite-plugin (lädt Sourcemaps beim Build hoch, wenn SENTRY_AUTH_TOKEN gesetzt). To-do: Token als BuildKit---secret an den web-build-Dockerfile-Stage durchreichen (NICHT build-arg → kein Leak) + SENTRY_PROJECT=web explizit (Default ist alter Slug hivegrid-web). Nur auf echtem Deploy testbar → bis Sentry-Go-Live aufgeschoben.
  • Persistenter Store-Cache: cache.dir gesetzt + befüllt (2,9 GB), aber Hit-Gewinn bei cap 8 noch ungemessen (Per-Job-Restore-I/O könnte Download-Gewinn auffressen → ggf. auf geteilten gemounteten Store umstellen statt actions/cache).