306 lines
12 KiB
Markdown
306 lines
12 KiB
Markdown
# Runbook: Wenn die Host-Übernahme stehenbleibt
|
|
|
|
Der Bootstrap läuft in neun Abschnitten. Bleibt einer davon aus, zeigt die
|
|
Konsole **welcher** — nicht „irgendetwas ging schief". Dieses Runbook sagt je
|
|
Abschnitt: woran man es merkt, wo man nachsieht, und was der übliche Grund ist.
|
|
|
|
---
|
|
|
|
## Die eine Regel, die über allen steht
|
|
|
|
**Eine halb installierte Maschine wird neu aufgesetzt, nicht nachgebessert.**
|
|
|
|
Nicht aus Bequemlichkeit. Der Bootstrap ist so gebaut, dass ein zweiter Lauf auf
|
|
einer frisch aufgesetzten Maschine immer gleich ausgeht — ein Lauf auf einer
|
|
Maschine, an der jemand von Hand etwas gerade gerückt hat, ist das nicht mehr.
|
|
Wer nachbessert, tauscht ein wiederholbares Ergebnis gegen ein einmaliges, und
|
|
merkt den Unterschied erst beim nächsten Host.
|
|
|
|
Der Weg zurück ist immer derselbe:
|
|
|
|
1. Im Adminbereich einen **neuen** Host anlegen. Der Einmal-Code ist verbraucht;
|
|
die Seite zeigt ihn nicht wieder her, und das ist Absicht.
|
|
2. Beim Anbieter das **Rettungssystem** starten.
|
|
3. Die neue Zeile einfügen.
|
|
|
|
Der alte Host-Eintrag wird im Adminbereich entfernt. Solange er steht, hält er
|
|
seine Tunneladresse belegt.
|
|
|
|
**Ausnahme:** Bleibt der Lauf in `rescue_checked` stehen, ist noch **nichts**
|
|
geschrieben worden. Dort ist Nachbessern richtig — es ist der einzige Abschnitt,
|
|
der die Platte nicht angefasst hat.
|
|
|
|
---
|
|
|
|
## Wo alles steht
|
|
|
|
| Was | Wo |
|
|
|---|---|
|
|
| Fortschritt, Zeile je Abschnitt | `/var/lib/clupilot/progress.jsonl` |
|
|
| Was schon gesendet wurde (Zeilenzahl) | `/var/lib/clupilot/progress.sent` |
|
|
| Laufprotokoll des Skripts | `/var/lib/clupilot/bootstrap.log` |
|
|
| Aufrufargumente (nur root) | `/var/lib/clupilot/arguments` |
|
|
| Arbeitsverzeichnis: ISO, Protokolle | `/var/tmp/clupilot-work/` |
|
|
| Installer-Protokoll | `/var/tmp/clupilot-work/qemu.log` |
|
|
| Antwortdatei des Installers | `/var/tmp/clupilot-work/answer.toml` |
|
|
| Traefik | `/var/log/traefik.log`, `/etc/traefik/traefik.yml` |
|
|
|
|
Die Fortschrittsdatei **ist** der Zustand. Ein Abschnitt, der dort `done`
|
|
gemeldet hat, läuft bei einem Wiederanlauf nicht erneut.
|
|
|
|
---
|
|
|
|
## Vor dem Neustart oder danach?
|
|
|
|
Das ist die erste Frage, und sie ist leicht zu beantworten:
|
|
|
|
```sh
|
|
findmnt -no FSTYPE /
|
|
```
|
|
|
|
`tmpfs`, `overlay` oder `ramfs` heißt: noch im Rettungssystem, der Neustart
|
|
steht bevor. `zfs` heißt: die Maschine läuft schon auf dem installierten System,
|
|
und der `first-boot`-Hook hat den Lauf wieder aufgenommen.
|
|
|
|
---
|
|
|
|
## Abschnitt für Abschnitt
|
|
|
|
### `rescue_checked` — die Eingangsprüfung
|
|
|
|
**Woran man es merkt:** Das Skript endet sofort mit einer Liste von Befunden.
|
|
In der Konsole steht nichts, weil es vor dem Tunnel keinen Weg dorthin gibt.
|
|
|
|
**Übliche Gründe:**
|
|
|
|
- *„Das Wurzelverzeichnis liegt auf /dev/… also auf einer echten Partition."*
|
|
Die Maschine läuft nicht im Rettungssystem. Beim Anbieter das Rettungssystem
|
|
einschalten und **neu starten** — das Einschalten allein genügt nicht.
|
|
- *„Die CPU meldet weder vmx noch svm."* Ein Cloud-Produkt ohne verschachtelte
|
|
Virtualisierung (Hetzner CPX/CX, teils netcup). Nicht abstellbar; es braucht
|
|
eine dedizierte Maschine.
|
|
- *„/dev/kvm gibt es nicht."* Virtualisierung im BIOS aus, oder das
|
|
Rettungssystem hat das Modul nicht geladen: `modprobe kvm_intel` bzw.
|
|
`modprobe kvm_amd`, dann die Zeile noch einmal.
|
|
- *„Es sind Partitionen echter Platten eingehängt."* Jemand hat nachgesehen.
|
|
`umount` und noch einmal.
|
|
- *„Die Uhr geht … Sekunden falsch."* Die Meldung enthält den fertigen Befehl
|
|
zum Stellen. Ohne ihn scheitert später jede TLS-Prüfung mit einer Meldung über
|
|
Zertifikate statt über die Uhrzeit.
|
|
|
|
**Hier ist Nachbessern richtig.** Es wurde noch nichts geschrieben.
|
|
|
|
---
|
|
|
|
### `debian_installed` — das Grundsystem
|
|
|
|
Heißt „Grundsystem geschrieben". Es entsteht **kein** Debian, das nachher jemand
|
|
umbaut: die offizielle Proxmox-ISO wird mit einer Antwortdatei versehen und
|
|
unter QEMU gegen die echten Platten gestartet.
|
|
|
|
**Woran man es merkt:** Der Lauf steht lange ohne Meldung; im Rettungssystem
|
|
läuft ein `qemu-system-x86_64`.
|
|
|
|
**Wo man nachsieht:** `/var/tmp/clupilot-work/qemu.log`, und die Antwortdatei
|
|
daneben. Läuft QEMU noch, kann man dem Installer zusehen — er hört auf
|
|
`127.0.0.1:5900`:
|
|
|
|
```bash
|
|
ssh -L 5900:127.0.0.1:5900 root@<öffentliche-ip>
|
|
```
|
|
|
|
Dann mit einem VNC-Betrachter auf `localhost:5900`. Sieht man dort eine
|
|
**Eingabemaske**, ist die Antwortdatei nicht angenommen worden — der Installer
|
|
ist in den interaktiven Modus gefallen und wartet, bis die Stunde abläuft.
|
|
|
|
**Übliche Gründe:**
|
|
|
|
- `answer.toml` abgelehnt. Steht in `/var/tmp/clupilot-work/assistant.log`. Das
|
|
Skript prüft sie mit `validate-answer`, bevor es die ISO backt, also ist das
|
|
selten — und wenn, dann liegt es an einem Wert aus der Umgebung (Adresse,
|
|
Gateway, MAC), den das Rettungssystem anders meldet als erwartet.
|
|
- Prüfsumme der ISO stimmt nicht. Abgebrochene Übertragung. Zeile noch einmal.
|
|
- Keine passende PVE-9-ISO gefunden. Die Liste unter
|
|
`https://enterprise.proxmox.com/iso/` war nicht erreichbar.
|
|
|
|
---
|
|
|
|
### `rebooted` — die einzige unumkehrbare Stelle
|
|
|
|
**Woran man es merkt:** Die Maschine antwortet nach dem Neustart nicht mehr,
|
|
oder sie antwortet, meldet aber nichts weiter.
|
|
|
|
**Übliche Gründe:**
|
|
|
|
- Die Maschine bootet noch vom Rettungssystem statt von der Platte. Beim
|
|
Anbieter das Rettungssystem **abschalten** und neu starten.
|
|
- Der `first-boot`-Hook lief nicht. Nachsehen mit
|
|
`journalctl -u proxmox-first-boot` und `ls /var/lib/clupilot/`. Fehlt das
|
|
Verzeichnis ganz, ist der Hook nicht in die ISO gekommen — dann neu aufsetzen.
|
|
|
|
**Kommt die Maschine gar nicht zurück:** Anbieterkonsole. Neu aufsetzen ist
|
|
schneller als jede Suche.
|
|
|
|
---
|
|
|
|
### `proxmox_installed` — abnehmen und Quellen richten
|
|
|
|
**Woran man es merkt:** Meldung mit `failed` und einem der folgenden Sätze.
|
|
|
|
**Übliche Gründe:**
|
|
|
|
- *„pveversion gibt es nicht"* — die ISO hat kein Proxmox installiert. Neu
|
|
aufsetzen.
|
|
- *„läuft auf …, das ist kein PVE-Kernel"* — die Maschine ist in den
|
|
Debian-Kernel gebootet. `uname -r` muss `-pve` enthalten.
|
|
- *„erwartet wäre PVE 9"* — Abbild und Unterbau passen nicht zusammen. Mit dem
|
|
richtigen Abbild neu aufsetzen; Paketquellen heilen das nicht.
|
|
- *„apt-get update schlägt fehl"* — siehe `/var/tmp/clupilot-work/apt.log`. Fast
|
|
immer eine Abonnement-Quelle, die wieder aufgetaucht ist:
|
|
`ls /etc/apt/sources.list.d/`.
|
|
|
|
---
|
|
|
|
### `network_bridged` — der gefährlichste Abschnitt
|
|
|
|
**Woran man es merkt:** Entweder eine `failed`-Meldung, oder die Maschine ist
|
|
für ein paar Minuten weg und kommt dann von selbst zurück.
|
|
|
|
**Kommt sie zurück, war das die Selbstrücknahme.** Das ist kein Fehler des
|
|
Zeitgebers, sondern sein Zweck: die Brücke hätte den Host vom Netz genommen.
|
|
Nachsehen mit `journalctl -t clupilot`.
|
|
|
|
**Übliche Gründe:**
|
|
|
|
- Falsche Anbieterform erkannt. Bei einer gerouteten Einzeladresse muss
|
|
`pointopoint` in `/etc/network/interfaces` stehen; fehlt sie, findet der
|
|
Kernel das Gateway nicht.
|
|
- *„die Datacenter-Firewall ließ sich nicht einschalten"* — ohne sie sind die
|
|
„nur 80/443"-Regeln **jeder** Kunden-VM wirkungslos. Prüfen mit
|
|
`pvesh get /cluster/firewall/options`.
|
|
|
|
**Kommt die Maschine nicht zurück:** Anbieterkonsole, dort
|
|
`tar xzf /var/lib/clupilot/interfaces.vor-der-bruecke.tar.gz -C /` und
|
|
`ifreload -a`. Danach neu aufsetzen.
|
|
|
|
---
|
|
|
|
### `wireguard_joined` — ab hier ist CluPilot erreichbar
|
|
|
|
**Woran man es merkt:** Bis hierher stand in der Konsole „wartet auf den
|
|
Tunnel". Bleibt es dabei, ist dieser Abschnitt der offene.
|
|
|
|
**Wo man nachsieht:** `wg show` auf dem Host. Steht dort ein Peer ohne
|
|
`latest handshake`, steht die Datei und der Tunnel nicht.
|
|
|
|
**Übliche Gründe:**
|
|
|
|
- Der Hub kennt den Peer nicht. Sollte nicht vorkommen — CluPilot legt ihn beim
|
|
Anlegen des Hosts an —, aber ein gelöschter Host-Eintrag nimmt ihn mit.
|
|
- Der Hub-Endpunkt ist von dieser Maschine aus nicht erreichbar. UDP auf dem
|
|
Port des Hubs prüfen.
|
|
- *„konnte wg-quick@wg0 nicht freigeben"* — der Tunnel überlebte den nächsten
|
|
Neustart nicht. Das ist ein harter Fehler, kein Schönheitsfehler.
|
|
|
|
---
|
|
|
|
### `traefik_running`
|
|
|
|
**Woran man es merkt:** `failed` mit einem der Sätze unten. Der Host ist
|
|
erreichbar, also lässt sich alles direkt nachsehen.
|
|
|
|
**Übliche Gründe:**
|
|
|
|
- *„antwortet nicht am Ping-Endpunkt"* — `/var/log/traefik.log` und
|
|
`systemctl status traefik`.
|
|
- *„80 und 443 sind nicht belegt"* — Traefik läuft, ein Entrypoint fehlt.
|
|
`ss -ltnp | grep -E ':80|:443'`. Belegt sie etwas anderes, gehört das nicht auf
|
|
diese Maschine.
|
|
- Prüfsumme des Binaries stimmt nicht. Zeile noch einmal.
|
|
|
|
Dass Traefik hier **noch keine Routentabelle** holt, ist richtig so: den Token
|
|
dafür gibt es erst mit der Registrierung.
|
|
|
|
---
|
|
|
|
### `template_built` — die goldene Vorlage
|
|
|
|
**Woran man es merkt:** `failed`, meist mit einem Hinweis auf eine der drei
|
|
Fallen.
|
|
|
|
**Wo man nachsieht:** `/var/tmp/clupilot-work/virt-customize.log` und
|
|
`qm.log`.
|
|
|
|
**Übliche Gründe:**
|
|
|
|
- *„erfüllt Falle 2 nicht"* — das Cloud-Abbild hat LVM oder die Wurzel ist nicht
|
|
die letzte Partition. Dann stimmt etwas am Abbild nicht, das dort liegt.
|
|
- *„qemu-guest-agent ist NICHT im Abbild"* — `virt-customize` hat Erfolg
|
|
gemeldet und apt hat das Paket still nicht installiert. Fast immer ein
|
|
Netzproblem im Abbild-Umbau.
|
|
- *„kein `user: www-data`"* — die Compose-Datei im Abbild ist nicht die aus
|
|
`assets/`. Ohne diese Zeile schlagen **alle** `occ`-Aufrufe fehl.
|
|
- *„meldet nicht template: 1"* — die VM existiert, ist aber keine Vorlage.
|
|
`qm template 9000` von Hand und dann **trotzdem neu aufsetzen**: wenn dieser
|
|
Schritt schiefging, ist unklar, was sonst noch.
|
|
|
|
---
|
|
|
|
### `registered` — die Übergabe
|
|
|
|
**Woran man es merkt:** Der Host bleibt in der Konsole auf `onboarding`.
|
|
|
|
**Übliche Gründe:**
|
|
|
|
- *„die Proxmox-Rolle ließ sich nicht angleichen"* — ohne `Sys.Modify` stirbt
|
|
später **jede** Kundenbereitstellung am Backup-Schritt. Prüfen mit
|
|
`pveum role list`.
|
|
- *„hat nicht geantwortet"* — CluPilot ist über den Tunnel nicht erreichbar,
|
|
obwohl der Handshake stand. Auf der CluPilot-Seite nachsehen, ob die
|
|
Tunneladresse in `TRUSTED_RANGES` steht.
|
|
- *„kam ohne host_token zurück"* — die Registrierung ist durchgelaufen, die
|
|
Antwort war unvollständig. Auf der CluPilot-Seite nachsehen.
|
|
- *„der Schlüsseltausch hat keinen Handshake ergeben"* — das Skript hat auf den
|
|
alten Schlüssel zurückgestellt, der Host ist also **noch erreichbar**. Der Hub
|
|
hat den neuen Peer möglicherweise schon aufgenommen und den alten entfernt;
|
|
dann ist der Host beim nächsten Versuch weg. Neu aufsetzen.
|
|
- *„die Routentabelle ist nicht abrufbar"* — der Token stimmt nicht oder
|
|
`/host/routes` antwortet nicht. Direkt prüfen:
|
|
```bash
|
|
curl -H "Authorization: Bearer $(cat /etc/traefik/host-token)" http://<tunnel-ip>/host/routes
|
|
```
|
|
|
|
---
|
|
|
|
## Der Host ist nicht mehr erreichbar
|
|
|
|
Erst die Frage: **war die Firewall schon dran?** Sie wird als **allerletztes**
|
|
angewendet. Steht in der Konsole `registered` noch nicht auf `done`, war sie es
|
|
nicht — dann liegt es am Netz, nicht an den Regeln.
|
|
|
|
War sie dran, gibt es von der Anbieterkonsole aus genau einen Griff:
|
|
|
|
```bash
|
|
/usr/local/sbin/clupilot-emergency-open-firewall.sh
|
|
```
|
|
|
|
Der Host nimmt danach auf jedem Port wieder an. **Es gibt bewusst keine
|
|
automatische Wiederöffnung** — kein Zeitgeber, kein „nach N Minuten ohne
|
|
Handshake wieder auf". Eine Firewall, die sich unter Störung selbst öffnet, ist
|
|
keine Firewall.
|
|
|
|
Zurück kommen die Regeln mit:
|
|
|
|
```bash
|
|
nft -f /etc/nftables.conf && systemctl enable --now nftables
|
|
```
|
|
|
|
---
|
|
|
|
## Was dieses Runbook nicht sagt
|
|
|
|
Alles, was noch nicht auf echter Hardware gelaufen ist. Die Abschnitte oben sind
|
|
aus dem Skript und aus den Fundstellen geschrieben, die ihm zugrunde liegen —
|
|
nicht aus Vorfällen. Was beim ersten Durchlauf tatsächlich stehenbleibt, gehört
|
|
hier ergänzt, mit dem Satz, der in der Konsole stand.
|