Verweise der Form #123 im folgenden Text beziehen sich auf die GitHub-Nummerierung, nicht auf die Nummern in diesem Repo. Geschlossene Issues wurden nicht mitgezogen und sind weiterhin nur auf GitHub lesbar.
Teil von #225, Stufe 2. Die Runner stehen seit jk-cluster/cluster-config#201; damit ist die dortige Frage „Trägt ein Runner den
Install-Test?" beantwortbar geworden — und die Antwort lautet: noch nicht ganz.
Von den fünf Aufgaben in validate-charts.yml laufen vier ohne jede Änderung. detect-changed-charts (git/jq), build-chart (helm lint/package), quantity-render (helm template) und trivy-config brauchen kein Docker. Auch publish-helm-chart.yml nicht — helm package und ein curl-Upload.
Bleibt install-test. Der legt mit k3d einen k3s-Cluster an, und das ist der
eine Auftrag im ganzen Repository, der einen Docker-Daemon braucht.
Was drüben bereitsteht
Zwei Runner im Namensraum jlab-git, beide mit rootless dind:
Label
Socket im Auftragscontainer
Grenzen des Daemons
ubuntu-latest, ubuntu-24.04
nein (docker_host: "-")
4 CPU, 6Gi, 20Gi Abbilder
ubuntu-docker, ubuntu-24.04-docker
ja (docker_host: "")
6 CPU, 12Gi, 40Gi Abbilder
Damit ist zugleich die unter #225 offene Frage nach den Labels beantwortet.
Kleine Korrektur zur dortigen Annahme: es sind nicht 4 vCPU, der ubuntu-docker-Runner darf bis 6 CPU und 12Gi ziehen, bei Requests von 500m und
2Gi. Er landet auf jk-worker-1 oder jk-worker-2 (64 bzw. 32 GB), die
Steuerknoten tragen CriticalAddonsOnly.
Das eigentliche Problem: k3d findet seinen eigenen Cluster nicht
Der dind-Container ist ein nativer Sidecar im selben Pod wie der Runner, teilt
sich also dessen Netzwerk-Namensraum. Der Auftragscontainer dagegen ist ein
gewöhnlicher Docker-Container, den dieser Daemon anlegt, und hängt an einer
Bridge im Daemon — nicht am Pod.
k3d veröffentlicht den Port des API-Servers auf dem Docker-Host. Das ist hier
der dind-Container, also der Pod. In die Kubeconfig schreibt k3d entsprechend https://0.0.0.0:<port> — und aus dem Auftragscontainer heraus zeigt das auf ihn
selbst, wo nichts lauscht. Dazu kommt, dass der Runner pro Auftrag ein eigenes
Docker-Netz anlegt (container.network ist leer), während k3d sich sein eigenes
Netz k3d-install-test baut. Zwei Bridges, keine Verbindung.
Der Cluster entsteht also vermutlich sauber, und der erste kubectl läuft in eine
Zeitüberschreitung.
Gute Nachricht: ci/run-install-test.sh benutzt schlicht den eingestellten
kubectl-Kontext. Die Arbeit liegt vollständig im Workflow, die 179 Zeilen des
Skripts bleiben unberührt.
Ansätze — Spuren, nicht erprobt
Keiner davon ist gemessen; das gehört in den Wegwerf-Workflow aus #225, Stufe 2,
bevor validate-charts.yml angefasst wird.
k3d in das Netz des Auftragscontainers hängen. Der Auftrag hat den Socket,
kann sich also selbst befragen und das Netz an k3d durchreichen:
Dann liegen k3s und Auftrag auf derselben Bridge, und Dockers eingebautes DNS
löst die Containernamen auf. Das ist der Ansatz, der ohne Vorbereitung
auskommt.
Die Kubeconfig umschreiben, von 0.0.0.0 auf https://k3d-install-test-serverlb:6443. Zu prüfen ist dabei, ob das
Zertifikat des API-Servers diesen Namen führt — sonst braucht es zusätzlich
ein --k3s-arg '--tls-san=k3d-install-test-serverlb@server:*'.
K3D_FIX_DNS und K3D_FIX_MOUNTS. k3d bringt diese Umgebungsvariablen
ausdrücklich für Läufe innerhalb eines Containers mit. Ob sie hier nötig sind,
ist offen.
Ein festes container.network am Runner wäre der unbequemere Weg: der
Runner legt ein benanntes Netz nie selbst an, und der dind-Daemon ist
flüchtig — das Netz müsste bei jedem Pod-Start erzeugt werden. Nur als
Rückfallebene.
Ein Missverständnis, dem man zuvorkommen sollte
In der Runner-Konfiguration steht container.privileged: false. Das betrifft nur die Container, die der Runner selbst anlegt, also den Auftragscontainer.
Die k3s-Knoten legt der Auftrag über den Socket direkt beim Daemon an, und dabei
greift diese Einstellung nicht — k3d bekommt sein --privileged. Wer bei einem
Fehlschlag an dieser Stelle schraubt, ändert nichts an der Ursache und gibt
stattdessen jedem Auftragscontainer mehr Rechte.
Reihenfolge, die man nicht umgehen kann
runs-on: ubuntu-docker bricht die GitHub-Seite, dort gibt es das Label nicht.
JLab-Git liest .gitea/workflowsund.github/workflows, beide Systeme lesen
also vorerst dieselbe Datei. Der Wechsel des runs-on gehört damit hinter Stufe 6
aus #225 — Actions auf GitHub abschalten —, oder vorübergehend in eine eigene
Datei unter .gitea/workflows.
Für den Probelauf spielt das keine Rolle: ein Wegwerf-Workflow entsteht ohnehin
neu und kann ubuntu-docker von Anfang an fordern.
Fertig, wenn
install-test auf ubuntu-docker einen k3d-Cluster anlegt und kubectl ihn
erreicht,
ein Chart-Install darin innerhalb der 30 Minuten durchläuft,
und das über mehrere Läufe stabil ist. Ein sporadisch roter Install-Test ist
die schlechteste Variante — #225 sagt das zu Recht: man glaubt ihm dann nicht
mehr.
> Migriert aus [`jk-cluster/helm-charts#227`](https://github.com/jk-cluster/helm-charts/issues/227) — urspruenglich angelegt von **jk-cluster-bot** am 2026-09-02.
>
> Verweise der Form `#123` im folgenden Text beziehen sich auf die **GitHub-Nummerierung**, nicht auf die Nummern in diesem Repo. Geschlossene Issues wurden nicht mitgezogen und sind weiterhin nur auf GitHub lesbar.
---
Teil von #225, Stufe 2. Die Runner stehen seit
jk-cluster/cluster-config#201; damit ist die dortige Frage „Trägt ein Runner den
Install-Test?" beantwortbar geworden — und die Antwort lautet: noch nicht ganz.
Von den fünf Aufgaben in `validate-charts.yml` laufen vier ohne jede Änderung.
`detect-changed-charts` (git/jq), `build-chart` (helm lint/package),
`quantity-render` (helm template) und `trivy-config` brauchen kein Docker. Auch
`publish-helm-chart.yml` nicht — `helm package` und ein `curl`-Upload.
Bleibt `install-test`. Der legt mit k3d einen k3s-Cluster an, und das ist der
eine Auftrag im ganzen Repository, der einen Docker-Daemon braucht.
## Was drüben bereitsteht
Zwei Runner im Namensraum `jlab-git`, beide mit rootless dind:
| Label | Socket im Auftragscontainer | Grenzen des Daemons |
|---|---|---|
| `ubuntu-latest`, `ubuntu-24.04` | **nein** (`docker_host: "-"`) | 4 CPU, 6Gi, 20Gi Abbilder |
| `ubuntu-docker`, `ubuntu-24.04-docker` | **ja** (`docker_host: ""`) | 6 CPU, 12Gi, 40Gi Abbilder |
Damit ist zugleich die unter #225 offene Frage nach den Labels beantwortet.
Kleine Korrektur zur dortigen Annahme: es sind nicht 4 vCPU, der
`ubuntu-docker`-Runner darf bis 6 CPU und 12Gi ziehen, bei Requests von 500m und
2Gi. Er landet auf `jk-worker-1` oder `jk-worker-2` (64 bzw. 32 GB), die
Steuerknoten tragen `CriticalAddonsOnly`.
## Das eigentliche Problem: k3d findet seinen eigenen Cluster nicht
Der dind-Container ist ein nativer Sidecar im selben Pod wie der Runner, teilt
sich also dessen Netzwerk-Namensraum. Der **Auftragscontainer** dagegen ist ein
gewöhnlicher Docker-Container, den dieser Daemon anlegt, und hängt an einer
Bridge im Daemon — nicht am Pod.
k3d veröffentlicht den Port des API-Servers auf dem *Docker-Host*. Das ist hier
der dind-Container, also der Pod. In die Kubeconfig schreibt k3d entsprechend
`https://0.0.0.0:<port>` — und aus dem Auftragscontainer heraus zeigt das auf ihn
selbst, wo nichts lauscht. Dazu kommt, dass der Runner pro Auftrag ein eigenes
Docker-Netz anlegt (`container.network` ist leer), während k3d sich sein eigenes
Netz `k3d-install-test` baut. Zwei Bridges, keine Verbindung.
Der Cluster entsteht also vermutlich sauber, und der erste `kubectl` läuft in eine
Zeitüberschreitung.
Gute Nachricht: `ci/run-install-test.sh` benutzt schlicht den eingestellten
kubectl-Kontext. Die Arbeit liegt vollständig im Workflow, die 179 Zeilen des
Skripts bleiben unberührt.
## Ansätze — Spuren, nicht erprobt
Keiner davon ist gemessen; das gehört in den Wegwerf-Workflow aus #225, Stufe 2,
bevor `validate-charts.yml` angefasst wird.
1. **k3d in das Netz des Auftragscontainers hängen.** Der Auftrag hat den Socket,
kann sich also selbst befragen und das Netz an k3d durchreichen:
```sh
JOB_NET=$(docker inspect -f '{{range $k, $v := .NetworkSettings.Networks}}{{$k}}{{end}}' "$(hostname)")
k3d cluster create install-test --image "$K3S_IMAGE" --network "$JOB_NET" --wait
```
Dann liegen k3s und Auftrag auf derselben Bridge, und Dockers eingebautes DNS
löst die Containernamen auf. Das ist der Ansatz, der ohne Vorbereitung
auskommt.
2. **Die Kubeconfig umschreiben**, von `0.0.0.0` auf
`https://k3d-install-test-serverlb:6443`. Zu prüfen ist dabei, ob das
Zertifikat des API-Servers diesen Namen führt — sonst braucht es zusätzlich
ein `--k3s-arg '--tls-san=k3d-install-test-serverlb@server:*'`.
3. **`K3D_FIX_DNS` und `K3D_FIX_MOUNTS`.** k3d bringt diese Umgebungsvariablen
ausdrücklich für Läufe innerhalb eines Containers mit. Ob sie hier nötig sind,
ist offen.
4. **Ein festes `container.network` am Runner** wäre der unbequemere Weg: der
Runner legt ein benanntes Netz nie selbst an, und der dind-Daemon ist
flüchtig — das Netz müsste bei jedem Pod-Start erzeugt werden. Nur als
Rückfallebene.
## Ein Missverständnis, dem man zuvorkommen sollte
In der Runner-Konfiguration steht `container.privileged: false`. Das betrifft
**nur** die Container, die der Runner selbst anlegt, also den Auftragscontainer.
Die k3s-Knoten legt der Auftrag über den Socket direkt beim Daemon an, und dabei
greift diese Einstellung nicht — k3d bekommt sein `--privileged`. Wer bei einem
Fehlschlag an dieser Stelle schraubt, ändert nichts an der Ursache und gibt
stattdessen jedem Auftragscontainer mehr Rechte.
## Reihenfolge, die man nicht umgehen kann
`runs-on: ubuntu-docker` bricht die GitHub-Seite, dort gibt es das Label nicht.
JLab-Git liest `.gitea/workflows` **und** `.github/workflows`, beide Systeme lesen
also vorerst dieselbe Datei. Der Wechsel des `runs-on` gehört damit hinter Stufe 6
aus #225 — Actions auf GitHub abschalten —, oder vorübergehend in eine eigene
Datei unter `.gitea/workflows`.
Für den Probelauf spielt das keine Rolle: ein Wegwerf-Workflow entsteht ohnehin
neu und kann `ubuntu-docker` von Anfang an fordern.
## Fertig, wenn
- `install-test` auf `ubuntu-docker` einen k3d-Cluster anlegt und `kubectl` ihn
erreicht,
- ein Chart-Install darin innerhalb der 30 Minuten durchläuft,
- und das über mehrere Läufe stabil ist. Ein sporadisch roter Install-Test ist
die schlechteste Variante — #225 sagt das zu Recht: man glaubt ihm dann nicht
mehr.
Dieser Vorgang ist die migrierte Fassung des GitHub-Issues #227, das dort bereits mit Begruendung geschlossen wurde. Der Zwilling hier war versehentlich offen geblieben; das wird hiermit nachgezogen.
Zu den drei Abschlusskriterien aus dem Rumpf:
1. install-test legt auf ubuntu-docker einen k3d-Cluster an und kubectl erreicht ihn. Erfuellt. Von den vier im Rumpf skizzierten Ansaetzen trugen zwei: k3d haengt am Netz des Auftragscontainers (ueber die Selbstbefragung per Socket), und die kubeconfig wird von 0.0.0.0 auf https://k3d-<cluster>-serverlb:6443 umgeschrieben. Die dort offen gelassene Folgefrage ist beantwortet und gemessen: das Zertifikat fuehrt den serverlb-Namen bereits, ein --tls-san war nicht noetig. K3D_FIX_DNS/K3D_FIX_MOUNTS wurden nicht gebraucht, und an container.privileged wurde nichts geaendert — die Warnung im Rumpf hat sich als berechtigt erwiesen.
2. Ein Chart-Install laeuft innerhalb der 30 Minuten durch. Erfuellt, mit grossem Abstand. Create k3d cluster 19–25 s, der gesamte Install-Test 210–225 s. Im ersten echten Chart-PR (!25) erreichte freesailarr10/10 Container Ready hinter echtem Wireguard-Tunnel in 225 s — rund ein Achtel der Grenze, ohne dass INSTALL_TIMEOUT angefasst wurde.
3. Stabil ueber mehrere Laeufe. Erfuellt. Drei vollstaendige Laeufe mit beiden Charts nebenlaeufig: 216 / 212 / 210 s, 6 s Streuung. Gerade die Konstellation, die Sporadik erwarten liess — zwei k3s-Cluster gleichzeitig auf einem Daemon — hat gehalten.
Was der Rumpf nicht vorhersah
Der Weg dorthin lag nicht nur im Workflow. Zwei Ursachen lagen auf der Knotenebene und wurden in cluster-config behoben: eine MTU-Regression (rootful DinD legt Bruecken mit 1500 an, das Pod-Netz traegt 1450 — Downloads ueber ~1,4 kB starben stumm) und erschoepfte fs.inotify-Grenzen (128 Instanzen, Kernel-Standard; containerd kam nie hoch).
Dazu drei Annahmen im Workflow selbst: ein fest verdrahteter k3d-Clustername, der bei nebenlaeufigen Matrix-Zweigen kollidiert — der war auch auf GitHub falsch und fiel dort nur nie auf, weil jeder Zweig eine eigene VM bekommt —, sowie fehlendes kubectl und envsubst im Runner-Abbild.
Weiterhin ungemessen:/dev/fuse und User-Namespaces. Sie standen nie im Weg, geprueft sind sie damit nicht.
Die dauerhafte Fassung steht in der README unter „Where this repo lives"; der Verlauf in #14.
## Erledigt — der Install-Test laeuft hier
Dieser Vorgang ist die migrierte Fassung des GitHub-Issues #227, das dort bereits mit Begruendung geschlossen wurde. Der Zwilling hier war versehentlich offen geblieben; das wird hiermit nachgezogen.
Zu den drei Abschlusskriterien aus dem Rumpf:
**1. `install-test` legt auf `ubuntu-docker` einen k3d-Cluster an und `kubectl` erreicht ihn.** Erfuellt. Von den vier im Rumpf skizzierten Ansaetzen trugen zwei: k3d haengt am Netz des Auftragscontainers (ueber die Selbstbefragung per Socket), und die kubeconfig wird von `0.0.0.0` auf `https://k3d-<cluster>-serverlb:6443` umgeschrieben. Die dort offen gelassene Folgefrage ist beantwortet und **gemessen**: das Zertifikat fuehrt den serverlb-Namen bereits, ein `--tls-san` war **nicht** noetig. `K3D_FIX_DNS`/`K3D_FIX_MOUNTS` wurden nicht gebraucht, und an `container.privileged` wurde nichts geaendert — die Warnung im Rumpf hat sich als berechtigt erwiesen.
**2. Ein Chart-Install laeuft innerhalb der 30 Minuten durch.** Erfuellt, mit grossem Abstand. `Create k3d cluster` 19–25 s, der gesamte Install-Test 210–225 s. Im ersten echten Chart-PR (!25) erreichte `freesailarr` **10/10 Container Ready** hinter echtem Wireguard-Tunnel in 225 s — rund ein Achtel der Grenze, ohne dass `INSTALL_TIMEOUT` angefasst wurde.
**3. Stabil ueber mehrere Laeufe.** Erfuellt. Drei vollstaendige Laeufe mit beiden Charts nebenlaeufig: 216 / 212 / 210 s, **6 s Streuung**. Gerade die Konstellation, die Sporadik erwarten liess — zwei k3s-Cluster gleichzeitig auf einem Daemon — hat gehalten.
## Was der Rumpf nicht vorhersah
Der Weg dorthin lag nicht nur im Workflow. Zwei Ursachen lagen auf der Knotenebene und wurden in `cluster-config` behoben: eine **MTU**-Regression (rootful DinD legt Bruecken mit 1500 an, das Pod-Netz traegt 1450 — Downloads ueber ~1,4 kB starben stumm) und erschoepfte **`fs.inotify`**-Grenzen (128 Instanzen, Kernel-Standard; containerd kam nie hoch).
Dazu drei Annahmen im Workflow selbst: ein fest verdrahteter k3d-Clustername, der bei nebenlaeufigen Matrix-Zweigen kollidiert — **der war auch auf GitHub falsch und fiel dort nur nie auf, weil jeder Zweig eine eigene VM bekommt** —, sowie fehlendes `kubectl` und `envsubst` im Runner-Abbild.
**Weiterhin ungemessen:** `/dev/fuse` und User-Namespaces. Sie standen nie im Weg, geprueft sind sie damit nicht.
Die dauerhafte Fassung steht in der README unter „Where this repo lives"; der Verlauf in #14.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Teil von #225, Stufe 2. Die Runner stehen seit
jk-cluster/cluster-config#201; damit ist die dortige Frage „Trägt ein Runner den
Install-Test?" beantwortbar geworden — und die Antwort lautet: noch nicht ganz.
Von den fünf Aufgaben in
validate-charts.ymllaufen vier ohne jede Änderung.detect-changed-charts(git/jq),build-chart(helm lint/package),quantity-render(helm template) undtrivy-configbrauchen kein Docker. Auchpublish-helm-chart.ymlnicht —helm packageund eincurl-Upload.Bleibt
install-test. Der legt mit k3d einen k3s-Cluster an, und das ist dereine Auftrag im ganzen Repository, der einen Docker-Daemon braucht.
Was drüben bereitsteht
Zwei Runner im Namensraum
jlab-git, beide mit rootless dind:ubuntu-latest,ubuntu-24.04docker_host: "-")ubuntu-docker,ubuntu-24.04-dockerdocker_host: "")Damit ist zugleich die unter #225 offene Frage nach den Labels beantwortet.
Kleine Korrektur zur dortigen Annahme: es sind nicht 4 vCPU, der
ubuntu-docker-Runner darf bis 6 CPU und 12Gi ziehen, bei Requests von 500m und2Gi. Er landet auf
jk-worker-1oderjk-worker-2(64 bzw. 32 GB), dieSteuerknoten tragen
CriticalAddonsOnly.Das eigentliche Problem: k3d findet seinen eigenen Cluster nicht
Der dind-Container ist ein nativer Sidecar im selben Pod wie der Runner, teilt
sich also dessen Netzwerk-Namensraum. Der Auftragscontainer dagegen ist ein
gewöhnlicher Docker-Container, den dieser Daemon anlegt, und hängt an einer
Bridge im Daemon — nicht am Pod.
k3d veröffentlicht den Port des API-Servers auf dem Docker-Host. Das ist hier
der dind-Container, also der Pod. In die Kubeconfig schreibt k3d entsprechend
https://0.0.0.0:<port>— und aus dem Auftragscontainer heraus zeigt das auf ihnselbst, wo nichts lauscht. Dazu kommt, dass der Runner pro Auftrag ein eigenes
Docker-Netz anlegt (
container.networkist leer), während k3d sich sein eigenesNetz
k3d-install-testbaut. Zwei Bridges, keine Verbindung.Der Cluster entsteht also vermutlich sauber, und der erste
kubectlläuft in eineZeitüberschreitung.
Gute Nachricht:
ci/run-install-test.shbenutzt schlicht den eingestelltenkubectl-Kontext. Die Arbeit liegt vollständig im Workflow, die 179 Zeilen des
Skripts bleiben unberührt.
Ansätze — Spuren, nicht erprobt
Keiner davon ist gemessen; das gehört in den Wegwerf-Workflow aus #225, Stufe 2,
bevor
validate-charts.ymlangefasst wird.k3d in das Netz des Auftragscontainers hängen. Der Auftrag hat den Socket,
kann sich also selbst befragen und das Netz an k3d durchreichen:
Dann liegen k3s und Auftrag auf derselben Bridge, und Dockers eingebautes DNS
löst die Containernamen auf. Das ist der Ansatz, der ohne Vorbereitung
auskommt.
Die Kubeconfig umschreiben, von
0.0.0.0aufhttps://k3d-install-test-serverlb:6443. Zu prüfen ist dabei, ob dasZertifikat des API-Servers diesen Namen führt — sonst braucht es zusätzlich
ein
--k3s-arg '--tls-san=k3d-install-test-serverlb@server:*'.K3D_FIX_DNSundK3D_FIX_MOUNTS. k3d bringt diese Umgebungsvariablenausdrücklich für Läufe innerhalb eines Containers mit. Ob sie hier nötig sind,
ist offen.
Ein festes
container.networkam Runner wäre der unbequemere Weg: derRunner legt ein benanntes Netz nie selbst an, und der dind-Daemon ist
flüchtig — das Netz müsste bei jedem Pod-Start erzeugt werden. Nur als
Rückfallebene.
Ein Missverständnis, dem man zuvorkommen sollte
In der Runner-Konfiguration steht
container.privileged: false. Das betrifftnur die Container, die der Runner selbst anlegt, also den Auftragscontainer.
Die k3s-Knoten legt der Auftrag über den Socket direkt beim Daemon an, und dabei
greift diese Einstellung nicht — k3d bekommt sein
--privileged. Wer bei einemFehlschlag an dieser Stelle schraubt, ändert nichts an der Ursache und gibt
stattdessen jedem Auftragscontainer mehr Rechte.
Reihenfolge, die man nicht umgehen kann
runs-on: ubuntu-dockerbricht die GitHub-Seite, dort gibt es das Label nicht.JLab-Git liest
.gitea/workflowsund.github/workflows, beide Systeme lesenalso vorerst dieselbe Datei. Der Wechsel des
runs-ongehört damit hinter Stufe 6aus #225 — Actions auf GitHub abschalten —, oder vorübergehend in eine eigene
Datei unter
.gitea/workflows.Für den Probelauf spielt das keine Rolle: ein Wegwerf-Workflow entsteht ohnehin
neu und kann
ubuntu-dockervon Anfang an fordern.Fertig, wenn
install-testaufubuntu-dockereinen k3d-Cluster anlegt undkubectlihnerreicht,
die schlechteste Variante — #225 sagt das zu Recht: man glaubt ihm dann nicht
mehr.
Erledigt — der Install-Test laeuft hier
Dieser Vorgang ist die migrierte Fassung des GitHub-Issues #227, das dort bereits mit Begruendung geschlossen wurde. Der Zwilling hier war versehentlich offen geblieben; das wird hiermit nachgezogen.
Zu den drei Abschlusskriterien aus dem Rumpf:
1.
install-testlegt aufubuntu-dockereinen k3d-Cluster an undkubectlerreicht ihn. Erfuellt. Von den vier im Rumpf skizzierten Ansaetzen trugen zwei: k3d haengt am Netz des Auftragscontainers (ueber die Selbstbefragung per Socket), und die kubeconfig wird von0.0.0.0aufhttps://k3d-<cluster>-serverlb:6443umgeschrieben. Die dort offen gelassene Folgefrage ist beantwortet und gemessen: das Zertifikat fuehrt den serverlb-Namen bereits, ein--tls-sanwar nicht noetig.K3D_FIX_DNS/K3D_FIX_MOUNTSwurden nicht gebraucht, und ancontainer.privilegedwurde nichts geaendert — die Warnung im Rumpf hat sich als berechtigt erwiesen.2. Ein Chart-Install laeuft innerhalb der 30 Minuten durch. Erfuellt, mit grossem Abstand.
Create k3d cluster19–25 s, der gesamte Install-Test 210–225 s. Im ersten echten Chart-PR (!25) erreichtefreesailarr10/10 Container Ready hinter echtem Wireguard-Tunnel in 225 s — rund ein Achtel der Grenze, ohne dassINSTALL_TIMEOUTangefasst wurde.3. Stabil ueber mehrere Laeufe. Erfuellt. Drei vollstaendige Laeufe mit beiden Charts nebenlaeufig: 216 / 212 / 210 s, 6 s Streuung. Gerade die Konstellation, die Sporadik erwarten liess — zwei k3s-Cluster gleichzeitig auf einem Daemon — hat gehalten.
Was der Rumpf nicht vorhersah
Der Weg dorthin lag nicht nur im Workflow. Zwei Ursachen lagen auf der Knotenebene und wurden in
cluster-configbehoben: eine MTU-Regression (rootful DinD legt Bruecken mit 1500 an, das Pod-Netz traegt 1450 — Downloads ueber ~1,4 kB starben stumm) und erschoepftefs.inotify-Grenzen (128 Instanzen, Kernel-Standard; containerd kam nie hoch).Dazu drei Annahmen im Workflow selbst: ein fest verdrahteter k3d-Clustername, der bei nebenlaeufigen Matrix-Zweigen kollidiert — der war auch auf GitHub falsch und fiel dort nur nie auf, weil jeder Zweig eine eigene VM bekommt —, sowie fehlendes
kubectlundenvsubstim Runner-Abbild.Weiterhin ungemessen:
/dev/fuseund User-Namespaces. Sie standen nie im Weg, geprueft sind sie damit nicht.Die dauerhafte Fassung steht in der README unter „Where this repo lives"; der Verlauf in #14.