146 lines
6.8 KiB
Markdown
146 lines
6.8 KiB
Markdown
# Wartung, drain und Container-Lebenszyklus
|
||
|
||
Was Besucher sehen, wenn an einem Backend gearbeitet wird, und welcher Befehl wofür gedacht ist.
|
||
|
||
## Das Grundprinzip
|
||
|
||
Der Agent meldet dem Server immer den **vollständigen** Stand seines Hosts. Wie ein Dienst dabei erscheint, hängt davon ab, ob sein Container noch existiert:
|
||
|
||
| Zustand des Containers | Was der Agent meldet | Besucher sehen |
|
||
|---|---|---|
|
||
| läuft | Dienst normal | die Seite |
|
||
| **gestoppt** (`docker stop`, `docker compose stop`, Absturz, `restarting`, `paused`) | Dienst vorhanden, aber *down* | **Wartungsseite** (503, „Gleich wieder da“) |
|
||
| **entfernt** (`docker rm`, `docker compose down`) | Dienst gibt es nicht mehr | **404**, die Route ist weg |
|
||
| Host/Agent weg (Reboot, Netzausfall) | nichts – Verbindung getrennt | **Wartungsseite**, solange die Lease gilt (Community 14 Tage, kommerziell 7) |
|
||
|
||
**Das ist Absicht:** Ein verteilter Dienst bestimmt sein Routing selbst. `docker compose down` heißt „diesen Dienst gibt es hier nicht mehr“, also verschwindet seine Route, so wie bei Traefiks Docker-Provider. `stop` heißt „kommt wieder“, also bleibt die Route und zeigt die Wartungsseite.
|
||
|
||
Merkregel: **Für Wartung `stop`, nie `down`.**
|
||
|
||
Auch eine angemeldete Wartung (siehe unten) rettet einen *entfernten* Container nicht. Sie gilt für die Routen, die der Server vom Knoten kennt, und ein entfernter Container meldet keine mehr.
|
||
|
||
## Die Werkzeuge
|
||
|
||
| | **maintenance** – „bin gleich wieder da“ | **drain** – „gebe meine Arbeit ab“ |
|
||
|---|---|---|
|
||
| Routen bei Traefik | bleiben, zeigen die Wartungsseite (503) | werden entfernt (404, sofern kein anderer Knoten die Domain bedient) |
|
||
| Dauer | befristet (Default 4 h, `--for`), endet von selbst | bis `resume` |
|
||
| Anlass | Patchen, Reboot, Migration | Abbau, Umzug |
|
||
| Wer darf | Admin am Server **oder** der Knoten selbst | nur Admin |
|
||
| Geltungsbereich | ganzer Knoten **oder** einzelner Dienst | ganzer Knoten |
|
||
|
||
Eine Knoten-Wartung gilt für **alle** Dienste, die der Agent dieses Hosts meldet, also für alle Container mit `traefik.enable=true` und alle Dienste aus `/etc/sultan.d`.
|
||
|
||
### Knoten-Wartung am Server (Admin)
|
||
|
||
```bash
|
||
cd /docker/sultan-server
|
||
docker compose exec sultan-server sultan token node maintenance --id dockweb11 \
|
||
--for 2h --reason "Kernel-Update" --public-reason "Geplante Wartung, gleich wieder da"
|
||
docker compose exec sultan-server sultan token node resume --id dockweb11
|
||
```
|
||
|
||
- `--for`: Dauer, z. B. `30m`, `2h`, `1d`; `0` = unbefristet. Das Ende steht auf der Wartungsseite und im `Retry-After`.
|
||
- `--reason`: intern (Log, `node list`).
|
||
- `--public-reason`: ersetzt den Standardtext der Wartungsseite (max. 300 Zeichen; noch nicht getrennt nach Sprache).
|
||
- `node resume` beendet Wartung **und** drain.
|
||
|
||
**Verzögerung:** Der Server wertet einmal pro Minute neu aus (`--refresh`). Wartung und `resume` greifen also nach **bis zu einer Minute**. Vor Beginn der Arbeiten prüfen, ob die Wartung aktiv ist:
|
||
|
||
```bash
|
||
docker compose exec sultan-server sultan token node list # Spalte Wartung: "bis …"
|
||
curl -sI https://www.example.de # HTTP 503
|
||
```
|
||
|
||
### Knoten-Wartung vom Backend aus (Kunde/Betreiber des Hosts)
|
||
|
||
Ohne Zugriff auf den Server, direkt auf dem Docker-Host:
|
||
|
||
```bash
|
||
cd /docker/sultan-agent
|
||
docker compose exec sultan-agent sultan agent maintenance on --for 2h --public-reason "Update läuft"
|
||
docker compose exec sultan-agent sultan agent maintenance off
|
||
```
|
||
|
||
Die Anfrage ist mit dem Schlüssel des Knotens signiert. Ein Knoten kann so nur sich selbst in Wartung setzen.
|
||
|
||
### Wartung für einen einzelnen Dienst
|
||
|
||
Per Label am Container. Die anderen Dienste des Hosts laufen normal weiter:
|
||
|
||
```yaml
|
||
labels:
|
||
- "sultan.maintenance=true"
|
||
- "sultan.maintenance.public_reason=Wir ziehen um – heute Abend wieder da"
|
||
```
|
||
|
||
```bash
|
||
docker compose up -d # Labels ändern = Container neu erzeugen; die Wartungsseite greift sofort
|
||
```
|
||
|
||
Zurück: Labels entfernen (oder `=false`), dann erneut `docker compose up -d`.
|
||
|
||
Für `/etc/sultan.d`-Dienste: `maintenance: true` bzw. `maintenance_public_reason` in der YAML-Datei.
|
||
|
||
### drain (Admin)
|
||
|
||
```bash
|
||
docker compose exec sultan-server sultan token node drain --id dockweb11
|
||
docker compose exec sultan-server sultan token node resume --id dockweb11
|
||
```
|
||
|
||
Die Routen verschwinden **sofort** (404). Sinnvoll vor dem Abbau eines Hosts oder wenn ein anderer Knoten die Domains übernimmt. Für eine Seite mit nur einem Backend ist **maintenance** die richtige Wahl.
|
||
|
||
## Abläufe
|
||
|
||
### Container aktualisieren (neues Image)
|
||
|
||
```bash
|
||
docker compose pull
|
||
docker compose up -d
|
||
```
|
||
|
||
`up -d` erzeugt den Container neu: alt entfernen, neu starten. Dazwischen kann für ein bis zwei Sekunden 404 kommen. Wer das nicht will, setzt vorher eine Wartung für den Knoten oder den Dienst und beendet sie danach.
|
||
|
||
### Host patchen und neu starten
|
||
|
||
```bash
|
||
# 1. Server: Wartung setzen und abwarten, bis sie aktiv ist (≤ 1 min)
|
||
docker compose exec sultan-server sultan token node maintenance --id dockweb11 --for 1h \
|
||
--public-reason "Geplante Wartung, gleich wieder da"
|
||
curl -sI https://www.example.de # 503?
|
||
|
||
# 2. Backend-Host
|
||
cd /docker/app && docker compose pull # Images vorab holen
|
||
docker compose stop # NICHT down
|
||
apt upgrade && reboot
|
||
|
||
# 3. nach dem Reboot
|
||
cd /docker/app && docker compose up -d # gestoppte Dienste starten nach dem Reboot nicht von selbst
|
||
docker compose -f /docker/sultan-agent/compose.yaml logs --tail 5 # "Mit Server verbunden"
|
||
curl -sI http://127.0.0.1:9080 # Dienst lokal ok?
|
||
|
||
# 4. Server: Wartung beenden (greift nach ≤ 1 min)
|
||
docker compose exec sultan-server sultan token node resume --id dockweb11
|
||
```
|
||
|
||
Den Agent nie mit `docker compose stop` anhalten: `restart: unless-stopped` startet ihn sonst nach dem Reboot nicht wieder. Ein Reboot ohne vorheriges `stop` ist für den Agent in Ordnung.
|
||
|
||
### Ungeplanter Ausfall
|
||
|
||
Nichts zu tun. Stürzt ein Container ab, zeigt Sultan die Wartungsseite, bis er wieder läuft. Ist der ganze Host weg, gilt das, bis die Lease abläuft. Ist ein Knoten länger als 15 Minuten getrennt (`--offline-alert-after`), alarmiert der Server über Slack/ntfy, sofern konfiguriert, und meldet sich wieder, sobald der Knoten zurück ist.
|
||
|
||
### Host abbauen
|
||
|
||
```bash
|
||
docker compose exec sultan-server sultan token node drain --id dockweb11 # Routen sofort weg
|
||
# Agent und Dienste auf dem Host stoppen, suldata/ löschen
|
||
docker compose exec sultan-server sultan token node delete --id dockweb11
|
||
```
|
||
|
||
## Grenzen (Stand heute)
|
||
|
||
- `public_reason` ist ein Text für beide Sprachen der Wartungsseite (zweisprachig geplant).
|
||
- Wartung/`resume` per CLI greifen erst beim nächsten Refresh (≤ 1 min).
|
||
- Echte Lastverteilung einer Domain über mehrere Knoten gibt es noch nicht. drain verschiebt also keine Last, sondern nimmt die Seite vom Netz.
|