diff --git a/docs/REPO_MAP.md b/docs/REPO_MAP.md index 9adbda1..71d997a 100644 --- a/docs/REPO_MAP.md +++ b/docs/REPO_MAP.md @@ -35,6 +35,7 @@ Details gilt immer die betroffene Compose-Datei oder das jeweilige Runbook. | `docs/GITOPS_DRIFT_RUNBOOK.md` | Git/Gitea/Komodo/Docker/Host-Drift | | `docs/AUDIT_2026-05-25_TODO.md` | aktuelle Restliste | | `docs/DR_WORKSTATION_SETUP.md` | Schritt-fuer-Schritt-Runbook fuer den DR-Gaming-PC (WSL2 + Borg-Client + SSH-Keys) | +| `docs/runbooks/komodo-bulk-deploy-dns.md` | Bulk-Deploy-Pulls scheitern an DNS, wenn AdGuard im selben Batch recreated wird | ## Wichtige Skripte diff --git a/docs/runbooks/komodo-bulk-deploy-dns.md b/docs/runbooks/komodo-bulk-deploy-dns.md new file mode 100644 index 0000000..1810cc2 --- /dev/null +++ b/docs/runbooks/komodo-bulk-deploy-dns.md @@ -0,0 +1,58 @@ +# Runbook: Komodo Bulk-Deploy schlaegt mit DNS `connection refused` fehl + +Stand: 2026-06-10 · Typ: Runbook / ADR-light · Status: Sofortmassnahme empfohlen, noch nicht umgesetzt + +## Symptom + +Ein Bulk-Merge (z. B. Renovate-Sammel-PR) loest gleichzeitig viele Komodo-Stack-Webhooks aus. Komodo startet parallele `DeployStack`. Nur ein Teil der Stacks deployt, der Rest bleibt auf dem alten Image. In der Deploy-Stufe **Compose Pull** stehen Fehler wie: + +``` +Get "https://registry-1.docker.io/v2/": dial tcp: lookup registry-1.docker.io +on 192.168.178.58:53: read udp ...->192.168.178.58:53: read: connection refused +``` + +Manuelles Re-Deploy der betroffenen Stacks danach funktioniert (AdGuard ist dann wieder oben). + +## Ursache + +Der Host nutzt **AdGuard Home als einzigen Resolver** (`/etc/resolv.conf` = nur `nameserver 192.168.178.58`, keine `/etc/docker/daemon.json`). AdGuard laeuft selbst als Container auf dem Host und bindet `0.0.0.0:53`. Wird der `adguard`-Stack im selben Batch neu deployt, faellt Port 53 fuer Sekunden aus. Alle parallelen `docker compose pull` der anderen Stacks koennen `registry-1.docker.io` dann nicht aufloesen -> `connection refused` -> Deploy `success=false`. + +Es ist **kein** Webhook-, Auth- oder Docker-Hub-Rate-Limit-Problem: Webhooks authentifizieren sauber, `webhook_enabled=true`, Fehlerbild ist `connection refused` auf den eigenen DNS-Port direkt nach AdGuard-Recreate. Fuer den Pull-Pfad zaehlt der Docker-Daemon/Go-Resolver (iteriert ueber die `resolv.conf`-Server und springt bei Socket-Fehlern zum naechsten), nicht der glibc-Client. + +## Sofortmassnahme (Schicht 1) + +Unraid -> Settings -> Network Settings -> `eth0`: + +- DNS server 1: `192.168.178.58` (AdGuard, bleibt) +- **DNS server 2: `192.168.178.1`** (FritzBox) -> Apply + +Damit ueberleben Registry-Pulls einen kurzen AdGuard-Ausfall via Resolver-Failover. Im Normalbetrieb wird weiter DNS1 (AdGuard) genutzt, der Filter bleibt aktiv. + +Pruefen / Bedingungen: + +- **Kein `options rotate`** in `/etc/resolv.conf` (sonst dauerhafter Filter-Bypass). Aktuell nicht gesetzt; nach Apply erneut pruefen. +- Router muss oeffentliche Namen **selbst** aufloesen und nicht intern an AdGuard zurueckleiten. +- Hinweis zur Verifikation: Ein `nslookup registry-1.docker.io 192.168.178.1` bei laufendem AdGuard ist ein gutes Signal, aber **kein letzter Beweis**. Wasserdicht: AdGuard kurz stoppen und `dig @192.168.178.1 registry-1.docker.io`, oder FritzBox-Upstream / AdGuard-Querylog pruefen. + +Rollback: DNS server 2 leeren + Apply. + +## Betriebsregel (Schicht 2) + +- **AdGuard und Unbound nicht gemeinsam mit abhaengigen Stacks im Bulk deployen.** DNS-Infrastruktur immer separat / einzeln deployen, nicht waehrend 20+ parallele Pulls laufen. +- Renovate-PRs gestaffelt mergen (eine Etappe pro Deploy) statt Sammel-Merge. Deckt dieses Problem fuer den Normalbetrieb bereits ab. + +## Spaeter optional + +- Komodo-Deploys serialisieren: statt vieler paralleler Stack-Webhooks eine **Procedure** (sequenzielle Stages) oder **Resource Sync** mit `after`-Ordering. Trifft die Ursache direkter, ist aber ein groesserer Umbau und **kein Renovate-Blocker**. +- Host-DNS vom AdGuard-Container entkoppeln (AdGuard eigene IP via macvlan, Host-Resolver auf Router/Unbound), damit `:53` am Host nicht exklusiv am Container-Lifecycle haengt. + +## Verworfen + +- `/etc/docker/daemon.json` mit `"dns": [...]`: wirkt nur fuer Container-DNS, nicht fuer Daemon-eigene Image-Pulls. +- AdGuard `network_mode: host`: beim Recreate ist der DNS-Prozess trotzdem weg; macht aus dem Single Point of Failure keinen HA-Resolver. + +## Referenzen + +- Diagnose-Zugriff: SSH `root@192.168.178.58`; Komodo-Mongo (`docker exec komodo-mongo`, DB `komodo`, Collections `Stack`/`Update`); Gitea SQLite `/data/gitea/gitea.db` (Tabelle `webhook`, `repo_id=3`). +- Verwandt: `docs/WORKFLOW.md` (DNS-Regeln fuer Container), `docs/GITOPS_DRIFT_RUNBOOK.md`. +