design: gates 3 and 4 — one file, and two flags I had not thought of
Setting --node-ip alone would have been wrong in two ways I only found by looking. servicelb publishes the node's address, so the traefik service and every single ingress currently carry the public IP and would have started carrying 10.0.0.2. And the API certificate's SAN list has no 10.0.0.2 in it, so regenerating it while the kubeconfig points at the public address is how you lock yourself out. The line now carries --node-external-ip and --tls-san alongside. Two risks I had assumed turned out not to exist: alloy scrapes pods only, never the kubelet or the node role, and cert-manager solves HTTP01 over the public name. Neither cares what the node advertises. The install step runs with SKIP_START on purpose. The whole risk of this undertaking is what the script writes into that unit, so it gets read before anything starts rather than trusted.
This commit is contained in:
@@ -88,7 +88,7 @@ Bedeutung der Meilensteine: siehe [roadmap.md](roadmap.md).
|
||||
|
||||
| Design | Gate | Title |
|
||||
|---|---|---|
|
||||
| [2026-08-22-k3s-patch-1-34-10](docs/design/2026-08-22-k3s-patch-1-34-10.md) | gate-2 | Design: k3s v1.34.6 → v1.34.10 — die mitgelieferten Komponenten nachziehen |
|
||||
| [2026-08-22-k3s-patch-1-34-10](docs/design/2026-08-22-k3s-patch-1-34-10.md) | gate-4 | Design: k3s v1.34.6 → v1.34.10 — die mitgelieferten Komponenten nachziehen |
|
||||
|
||||
## ADRs (27)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
type: design
|
||||
status: gate-2
|
||||
status: gate-4
|
||||
date: 2026-08-22
|
||||
size: L
|
||||
related:
|
||||
@@ -267,3 +267,98 @@ repariert." Begründung, Beleg und die verworfenen Optionen B und C gehören
|
||||
festgehalten — sonst schreibt sie der nächste Mensch aus guter Absicht zurück.
|
||||
|
||||
> **STOP — wartet auf Gate-2-Freigabe.**
|
||||
|
||||
## Gate 3 + 4 — Program Design und Slices
|
||||
|
||||
Zusammengelegt: Es gibt **eine** zu ändernde Datei und eine Kommandofolge; ein
|
||||
getrenntes Gate 4 hätte dieselbe Liste zweimal.
|
||||
|
||||
### Die einzige Datei
|
||||
|
||||
`/etc/systemd/system/k3s.service` — nichts sonst. Kein Manifest, kein
|
||||
Helm-Wert, keine Zeile in einem Repo.
|
||||
|
||||
⚠️ **Und das ist selbst ein Befund.** Die gesamte Konfiguration dieses Clusters
|
||||
steht in einer Unit auf einem Host und in **keinem** Repository. Genau die
|
||||
Lücke, die [#0110](../issues/0110-haertung-lebt-auf-dem-host-das-repo-weiss-nichts-davon.md)
|
||||
für den Betriebs-Stack beschreibt — hier trifft sie den Cluster selbst.
|
||||
|
||||
**Neue ExecStart-Zeile:**
|
||||
|
||||
```
|
||||
/usr/local/bin/k3s server \
|
||||
--node-ip=10.0.0.2 \
|
||||
--node-external-ip=49.13.132.245 \
|
||||
--tls-san=49.13.132.245
|
||||
```
|
||||
|
||||
Drei Flags, jedes mit einem Grund:
|
||||
|
||||
| Flag | warum |
|
||||
|---|---|
|
||||
| `--node-ip=10.0.0.2` | Der Knoten kündigt heute seine **öffentliche** Adresse als `InternalIP` an. Der vSwitch liegt auf `enp7s0`, die Route zu CFGMON geht darüber. |
|
||||
| `--node-external-ip=49.13.132.245` | ⚠️ **Sonst veröffentlicht `servicelb` die private Adresse.** Der Traefik-Dienst trägt heute `49.13.132.245`, und **jeder** Ingress veröffentlicht sie. Ohne dieses Flag stünde dort `10.0.0.2`. |
|
||||
| `--tls-san=49.13.132.245` | ⚠️ Die SANs des API-Zertifikats sind heute `49.13.132.245`, die öffentliche IPv6, `10.43.0.1`, `127.0.0.1`, `localhost`, `matrix`. **`10.0.0.2` fehlt.** Beim Adresswechsel wird das Zertifikat neu erzeugt; ohne dieses Flag kann die öffentliche Adresse herausfallen — und unsere Kubeconfig zeigt genau dorthin. |
|
||||
|
||||
**Nicht** in der Zeile: `--disable=traefik`, `--disable=servicelb`. Sie werden
|
||||
gestrichen, nicht repariert — der Ingress bleibt vorerst k3s-verwaltet.
|
||||
|
||||
### Was der Adresswechsel NICHT anfasst — geprüft, nicht angenommen
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Alloy** | scrapt ausschließlich `role = "pod"`, keinen Kubelet und keine Knoten-Rolle. Unberührt. |
|
||||
| **cert-manager** | HTTP01 über die IngressClass `traefik`; Let's Encrypt kommt über den öffentlichen Namen, der Weg ändert sich nicht. |
|
||||
| **NetworkPolicies** | verweisen auf `kube-system` per Namensraum-Label, nicht auf Adressen. |
|
||||
| **Prometheus remote-write** | geht aus dem Cluster nach `10.0.0.3` — Gegenrichtung, unberührt. |
|
||||
| **Flux** | spricht `kubernetes.default` im Cluster an. |
|
||||
|
||||
⚠️ **Was sich ändert und in die Abnahme gehört:** Der Knoten verliert seine
|
||||
öffentliche **IPv6** als `InternalIP` (`--node-ip` setzt IPv4). Die Pod-CIDRs
|
||||
sind ohnehin IPv4-only (in #0088 gemessen), aber die Serie `kube_node_info`
|
||||
ändert sich — und damit möglicherweise Panels, die daran hängen.
|
||||
|
||||
### Ablauf
|
||||
|
||||
⚠️ **Ein Stopp, nicht zwei.** Der Datenbank-Abzug verlangt einen gestoppten
|
||||
Dienst (eine offene sqlite-Datei ist kein konsistenter Abzug). Also wird
|
||||
gestoppt, gesichert, aufgerüstet und gestartet — der Ausfall beginnt mit der
|
||||
Sicherung, nicht mit dem Upgrade.
|
||||
|
||||
| Slice | Was | Prüfung danach |
|
||||
|---|---|---|
|
||||
| **0** | **Vorher-Bild festhalten:** Pod-Liste, `kubectl get nodes -o wide`, SAN-Liste, Antwort von `axion1337.chat` und `wiki.axion1337.chat`, CVE-Zahlen. | Datei liegt vor; ohne sie ist „danach ist alles wie vorher" nicht belegbar. |
|
||||
| **1** | `systemctl stop k3s`; `cp /usr/local/bin/k3s /root/k3s-v1.34.6.bak`; `cp /etc/systemd/system/k3s.service /root/k3s.service.bak`; `cp -a /var/lib/rancher/k3s/server/db /root/db-vor-1.34.10/` | Alle drei existieren, `db` ist ~60 MB. ⚠️ **Ohne diesen Beleg wird nicht weitergemacht.** |
|
||||
| **2** | Installationsskript mit `INSTALL_K3S_VERSION=v1.34.10+k3s1`, `INSTALL_K3S_EXEC="server --node-ip=10.0.0.2 --node-external-ip=49.13.132.245 --tls-san=49.13.132.245"` und **`INSTALL_K3S_SKIP_START=true`** | ⚠️ **Nicht starten.** Erst die geschriebene Unit **lesen** und gegen die obige Zeile halten — genau hier liegt das Risiko dieses Vorhabens. |
|
||||
| **3** | `systemctl start k3s` | Innerhalb ~70 s: Knoten `Ready`, Fassung `v1.34.10+k3s1`, alle Pods `Running`. |
|
||||
| **4** | Abnahme gegen das Vorher-Bild | Ingress von außen, Anmeldung, SANs, Knoten-Adressen, sechs Komponenten-Fassungen. |
|
||||
| **5** | Nacharbeit: die sechs `rancher/*`-Einträge aus `entscheidungen.json` entfernen, ADR schreiben, Ledger schließen | `cve_critical_offen` = 0, `cve_entscheidungen_ohne_befund` = 0. |
|
||||
|
||||
### Grenzen — DO NOT CHANGE
|
||||
|
||||
- **Kein `--disable`.** Nicht in dieser Zeile, nicht „schon mal vorbereitet".
|
||||
- **Keine Minor-Sprünge.** Ziel ist exakt `v1.34.10+k3s1`.
|
||||
- **Keine `HelmChartConfig`.** Traefik bleibt auf k3s-Vorgaben.
|
||||
- **Kein Anfassen der Arbeitslasten.** Wer während des Fensters „schnell noch"
|
||||
etwas ausrollt, macht die Abnahme wertlos.
|
||||
|
||||
### Wackeligste Annahmen
|
||||
|
||||
1. **Dass das Installationsskript `INSTALL_K3S_EXEC` so übernimmt, wie erwartet.**
|
||||
Deshalb Slice 2 mit `SKIP_START` und Lesen statt Vertrauen. Wenn die Unit
|
||||
anders aussieht: anhalten, nicht korrigieren und weiterlaufen.
|
||||
2. **Dass ein Patch-Rückschritt trägt.** Innerhalb derselben Minor-Reihe ist er
|
||||
unterstützt; sicher ist erst der Datenbank-Abzug daneben.
|
||||
3. **Dass 70 Sekunden reichen.** Gemessen am Neustart vom 2026-08-01 — der war
|
||||
allerdings **ohne** Fassungswechsel und ohne neue Images. Diesmal müssen
|
||||
sechs Images gezogen werden. ⚠️ Realistisch also länger; die Images können in
|
||||
Slice 0 vorgezogen werden (`crictl pull`), dann bleibt es bei der Größenordnung.
|
||||
|
||||
### Neue ADRs
|
||||
|
||||
**Einer**, nach dem Sprung zu schreiben: „Der Ingress bleibt vorerst
|
||||
k3s-verwaltet; die drei nie wirksamen Flags werden gestrichen, `--node-ip`
|
||||
wird bewusst gesetzt." Mit Beleg, warum die Flags vier Monate lang nichts taten
|
||||
— sonst schreibt der Nächste sie aus guter Absicht zurück.
|
||||
|
||||
> **STOP — wartet auf Gate-3/4-Freigabe.**
|
||||
|
||||
@@ -16,6 +16,7 @@ related:
|
||||
|---|---|---|---|---|
|
||||
| 1 | bf2d87a | sorb | DONE | Umfang, sechs Abnahmekriterien, zwei offene Entscheidungen (Ausfallzeit, Traefik-Chart-Major); ⚠️ korrigiert die eigene Aussage „grosses Vorhaben" — es ist ein Patch auf der eigenen Minor-Reihe. |
|
||||
| 2 | 1d0d5f1 | sorb | DONE_WITH_CONCERNS | Fassungen gepinnt, Traefik-Major gerendert (identisch), Ausfallzeit aus der Historie gemessen (~70 s); ⚠️ Fund: drei k3s-Flags sind seit der Installation unwirksam, und das Installationsskript schreibt die Unit neu. |
|
||||
| 3+4 | PENDING | sorb | DONE | Eine Datei, sechs Slices; ExecStart um `--node-external-ip` und `--tls-san` ergaenzt, weil `--node-ip` allein die veroeffentlichte Adresse und das API-Zertifikat mitreisst. |
|
||||
|
||||
## Slices
|
||||
|
||||
@@ -34,6 +35,8 @@ related:
|
||||
| die genauen Fassungen der Release, statt die neuesten Tags zu nehmen | `k3s-images.txt` der Release nennt jedes Image mit Tag — klipper-helm v0.13.3-build20260727, coredns 1.14.6, local-path v0.0.36 | reused: das Herausgeber-Verzeichnis; die Korrektur kostet 29 HIGH gegenueber meiner Schaetzung und wird VOR der Arbeit im Kriterium nachgezogen | |
|
||||
| das ECHTE laufende Traefik-Chart, statt upstream als Stellvertreter zu nehmen | k3s legt die Chart-Tarballs unter `/var/lib/rancher/k3s/server/static/charts/` ab; von dort geholt und mit den echten `HelmChart`-Werten gerendert | reused: der laufende Bestand als Vergleichsseite — Objekte, Dienste, Ports, Selektoren, RBAC und Argumente sind identisch | |
|
||||
| wie lange ein k3s-Neustart wirklich kostet, statt „einige Minuten" zu schaetzen | der Neustart vom 2026-08-01 steht in den Container-Startzeiten: 19:37:06 Dienst, 19:38:14 letzter Container | reused: die eigene Historie als Messung — ~70 s statt einer Vermutung, und kein Pod-Objekt wurde neu erzeugt | |
|
||||
| was der Adresswechsel sonst anfasst, statt nur an die Kubeconfig zu denken | `servicelb` veroeffentlicht die Knoten-Adresse: der Traefik-Dienst UND jeder Ingress tragen heute 49.13.132.245 — ohne `--node-external-ip` stuende dort kuenftig 10.0.0.2 | built: die ExecStart-Zeile traegt jetzt drei Flags statt einem; der Fund kam aus dem Nachsehen, nicht aus dem Nachdenken | |
|
||||
| ob Alloy oder cert-manager an der Knoten-Adresse haengen | Alloy scrapt ausschliesslich `role = "pod"`, kein Kubelet, keine Knoten-Rolle; cert-manager loest HTTP01 ueber den oeffentlichen Namen | reused: die eigene Konfiguration als Pruefmassstab — zwei vermutete Risiken sind damit gegenstandslos, statt sie vorsorglich zu behandeln | |
|
||||
| ob die Unit ueberhaupt das tut, was sie sagt | NEIN: `server` steht zweimal in ExecStart, alles danach wird als Positionsargument gelesen. `k3s.io/node-args` fuehrt die Flags, `k3s.io/internal-ip` zeigt die oeffentliche Adresse, `traefik.yaml` ist ausgerollt | built: nichts — aber der Fund bestimmt das ganze Vorhaben: das Installationsskript schreibt die Unit neu, und dann werden drei seit vier Monaten stille Flags scharf | |
|
||||
|
||||
## Notes
|
||||
|
||||
Reference in New Issue
Block a user