From eff9d206ac546f6ebe8442d45b771330ae76b44e Mon Sep 17 00:00:00 2001 From: migatu Date: Wed, 26 Aug 2026 21:44:02 +0200 Subject: [PATCH] =?UTF-8?q?data:=20wymagaj=20w=C4=99z=C5=82a=20z=20x86-64-?= =?UTF-8?q?v2;=20runbook=20maskowania=20CPU=20i=20lista=20czterech=20w?= =?UTF-8?q?=C4=99z=C5=82=C3=B3w?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit data-demo wpadał w pętlę restartów na k3s-agent3: RuntimeError: NumPy was built with baseline optimizations: (X86_V2) but your machine doesn't support: (X86_V2). DIAGNOZA — to NIE jest różnica sprzętu. Wszystkie cztery węzły to maszyny wirtualne. Trzy widzą procesor jako „QEMU Virtual CPU 2.5+" i mają komplet rozszerzeń x86-64-v2; agent3 widzi „Common KVM processor" (kvm64) i nie ma popcnt, ssse3, sse4_1 ani sse4_2. Fizyczny i7-3770 pod spodem obsługuje nawet x86-64-v3 — te flagi są MASKOWANE przez domyślny model CPU w Proxmoksie. agent3 ma 14 dni, pozostałe 52. Został dołożony później i pominięto przy nim krok `--cpu host`, odnotowany w pamięci projektu 2 sierpnia. Nikt tego nie zauważył, dopóki scheduler nie postawił tam akurat warstwy danych — jedynej, która ciągnie pandas, a przez nią NumPy. ZABEZPIECZENIE: data i data-demo wymagają etykiety `astrololo.czernobog.pl/cpu-x86-64-v2`. Świadomie ETYKIETA, a nie wykluczenie agent3 po nazwie: wykluczanie po nazwie znaczyłoby, że każdy KOLEJNY źle postawiony węzeł znów zbiera się przez awarię. Nowy węzeł jest domyślnie nieoznaczony, więc nie dostanie tych podów, dopóki ktoś go nie sprawdzi i nie oznaczy. Pending z czytelnym powodem bije pętlę restartów z komunikatem o „baseline optimizations". KOLEJNOŚĆ: węzły trzeba oznaczyć PRZED wdrożeniem tej zmiany. Dziś etykietę ma zero węzłów, więc samo zmergowanie posłałoby data w Pending. RUNBOOK: skrypt sprawdzający węzły, naprawa u źródła (`qm set --cpu host` plus pełne wyłączenie i włączenie maszyny — sam restart z gościa nie wystarcza), oraz zastrzeżenie, że `--cpu host` blokuje migrację na żywo między hostami o różnych procesorach. PUŁAPKA PRZY CZYTANIU FLAG, udokumentowana bo kosztowała fałszywą diagnozę: Linux raportuje SSE3 jako „pni", nie „sse3". Pierwsza wersja kontroli wskazała przez to trzy zdrowe węzły jako niesprawne. Przy okazji: lista węzłów w eksportach NFS obejmuje wszystkie cztery. Runbooki wymieniały trzy, a klaster ma cztery — ten sam mechanizm, ta sama przyczyna. Co-Authored-By: Claude Opus 5 --- astrololo/README-astrodemo.md | 2 +- astrololo/README-stan-prezentacji.md | 2 +- astrololo/README.md | 81 +++++++++++++++++++++++++++- astrololo/astrodemo-stack.yaml | 20 +++++++ astrololo/data.yaml | 20 +++++++ 5 files changed, 122 insertions(+), 3 deletions(-) diff --git a/astrololo/README-astrodemo.md b/astrololo/README-astrodemo.md index 345a688..9758b45 100644 --- a/astrololo/README-astrodemo.md +++ b/astrololo/README-astrodemo.md @@ -47,7 +47,7 @@ midclt call sharing.nfs.query '[["path","=","/mnt/Tank1/astrololo-demo"]]' \ midclt call sharing.nfs.create '{ "path": "/mnt/Tank1/astrololo-demo", "comment": "astrololo — pule kont wersji demo (PRE-29)", - "hosts": ["192.168.1.73", "192.168.1.80", "192.168.1.81"], + "hosts": ["192.168.1.73", "192.168.1.80", "192.168.1.81", "192.168.1.82"], "enabled": true, "ro": false, "mapall_user": "root", diff --git a/astrololo/README-stan-prezentacji.md b/astrololo/README-stan-prezentacji.md index 75fe87e..19a9399 100644 --- a/astrololo/README-stan-prezentacji.md +++ b/astrololo/README-stan-prezentacji.md @@ -66,7 +66,7 @@ sudo chmod 770 /mnt/Tank1/astrololo-state midclt call sharing.nfs.create '{ "path": "/mnt/Tank1/astrololo-state", "comment": "astrololo — stan prezentacji (konta PRE-27)", - "hosts": ["192.168.1.73", "192.168.1.80", "192.168.1.81"], + "hosts": ["192.168.1.73", "192.168.1.80", "192.168.1.81", "192.168.1.82"], "ro": false, "mapall_user": "apps", "mapall_group": "apps" diff --git a/astrololo/README.md b/astrololo/README.md index 3d3818c..61e3780 100644 --- a/astrololo/README.md +++ b/astrololo/README.md @@ -60,7 +60,7 @@ w ogóle nie został zapytany. Jądro nie znalazło programu pomocniczego ### Sprawdzenie ```bash -for N in 192.168.1.73 192.168.1.80 192.168.1.81; do +for N in 192.168.1.73 192.168.1.80 192.168.1.81 192.168.1.82; do printf "%-15s " "$N" ssh hammer@$N 'test -x /sbin/mount.nfs && echo MA-KLIENTA || echo BRAK-KLIENTA' done @@ -86,6 +86,85 @@ ssh hammer@ 'sudo apt-get update && sudo apt-get install -y nfs-common' | `access denied by server while mounting` | serwer odmawia: eksport nieprzeładowany, węzła nie ma na liście `hosts`, albo udział wyłączony | | `Permission denied` przy zapisie | montowanie działa, brakuje praw — patrz `mapall_user` i właściciel katalogu | +## ⚠️ Wymóg węzłów: rozszerzenia procesora (x86-64-v2) + +Warstwa danych używa pandas, a przez nią NumPy. Koła NumPy z PyPI są budowane +z bazą **x86-64-v2**, więc na węźle bez tych rozszerzeń kontener nie wstaje: + +``` +RuntimeError: NumPy was built with baseline optimizations: +(X86_V2) but your machine doesn't support: (X86_V2). +``` + +Komunikat mówi o „optymalizacjach", czyli o niczym, po czym dałoby się poznać, +że chodzi o **węzeł**, a nie o obraz. Pod wpada w pętlę restartów i wygląda to +na zepsuty build. + +### To NIE jest ograniczenie sprzętu + +Węzły k3s są maszynami wirtualnymi. Proxmox z domyślnym modelem CPU (`kvm64`, +„Common KVM processor") **maskuje flagi procesora** — gość nie widzi SSE4.2 ani +POPCNT, mimo że fizyczny i7-3770 obsługuje nawet x86-64-**v3**. Stąd bierze się +złudzenie, że „węzły mają różne procesory": mają ten sam sprzęt i różne maski. + +### Sprawdzenie: które węzły to udźwigną + +```bash +for N in $(kubectl get nodes -o jsonpath='{.items[*].metadata.name}'); do + kubectl run cpucheck-$N --image=busybox --restart=Never --rm -i --quiet \ + --overrides="{\"spec\":{\"nodeName\":\"$N\",\"tolerations\":[{\"operator\":\"Exists\"}]}}" \ + --command -- sh -c ' + F=$(grep -m1 ^flags /proc/cpuinfo); BRAK="" + for f in cx16 lahf_lm popcnt pni ssse3 sse4_1 sse4_2; do + echo "$F" | grep -qw "$f" || BRAK="$BRAK $f" + done + echo "$(grep -m1 "model name" /proc/cpuinfo | cut -d: -f2-)" + [ -z "$BRAK" ] && echo " x86-64-v2: TAK" || echo " x86-64-v2: NIE —$BRAK" + ' 2>/dev/null | sed "s/^/$N /" +done +``` + +**Pułapka przy czytaniu flag:** Linux raportuje SSE3 jako **`pni`** (Prescott New +Instructions), nie `sse3`. Szukanie `sse3` daje fałszywy alarm na maszynie, która +SSE3 ma — pierwsza wersja tej kontroli wskazała w ten sposób trzy zdrowe węzły +jako niesprawne. + +### Naprawa u źródła (Proxmox) + +Na węźle Proxmox, dla każdej maszyny k3s: + +```bash +qm set --cpu host +qm stop && qm start +``` + +**Sam restart z wnętrza gościa nie wystarczy** — zmiana modelu CPU wchodzi +dopiero przy pełnym wyłączeniu i włączeniu maszyny. + +`--cpu host` przekazuje pełny zestaw rozszerzeń i daje przy okazji realnie +szybszą arytmetykę. Ma jeden koszt: **blokuje migrację na żywo** między hostami +o różnych procesorach. Jeśli kiedyś zaczniemy migrować maszyny między pve2 +a NUC-iem, właściwym wyborem będzie wspólny mianownik `x86-64-v2-AES` zamiast +`host`. + +### Zabezpieczenie: etykieta zamiast wykluczania po nazwie + +`data` i `data-demo` wymagają etykiety `astrololo.czernobog.pl/cpu-x86-64-v2`. +Nowy węzeł jest domyślnie **nieoznaczony**, więc nie dostanie tych podów, dopóki +ktoś go nie sprawdzi i nie oznaczy świadomie: + +```bash +kubectl label node astrololo.czernobog.pl/cpu-x86-64-v2=true +``` + +Wykluczanie konkretnego węzła po nazwie znaczyłoby, że każdy KOLEJNY źle +postawiony węzeł znów zbierze się przez awarię. Tak wyszedł agent3: dołożony +14 dni po pozostałych, bez kroku `--cpu host`, i nikt tego nie zauważył, dopóki +scheduler nie postawił tam akurat warstwy danych. + +**KOLEJNOŚĆ MA ZNACZENIE.** Oznacz węzły ZANIM to wdrożysz — bez etykiet `data` +nie ma się gdzie uruchomić i pójdzie w Pending. + ## ⚠️ Sekret `astrololo-auth` — utwórz PRZED wdrożeniem Aplikacja wystawia treść **oryginalnych baz interpretacyjnych**, dlatego wymaga diff --git a/astrololo/astrodemo-stack.yaml b/astrololo/astrodemo-stack.yaml index 867751e..cdf10a1 100644 --- a/astrololo/astrodemo-stack.yaml +++ b/astrololo/astrodemo-stack.yaml @@ -21,6 +21,26 @@ spec: metadata: labels: { app: data-demo } spec: + # Ta usługa liczy na pandas, a przez nią na NumPy. Koła NumPy z PyPI są + # budowane z bazą x86-64-v2, więc na węźle bez tych rozszerzeń kontener + # NIE WSTAJE: `import numpy` kończy się RuntimeError, pod wpada w pętlę + # restartów, a komunikat mówi o „baseline optimizations" — czyli o niczym, + # po czym dałoby się poznać, że chodzi o węzeł. + # + # Wymagana ETYKIETA, a nie wykluczony konkretny węzeł. Nowy węzeł jest + # domyślnie NIEOZNACZONY, więc nie dostanie tu poda, dopóki ktoś go nie + # sprawdzi (skrypt w README) i nie oznaczy świadomie. Pending z czytelnym + # powodem jest lepszy niż pętla restartów z komunikatem o optymalizacjach — + # a wykluczanie węzłów po nazwie znaczyłoby, że każdy KOLEJNY źle + # postawiony węzeł znów zbiera się przez awarię. + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: astrololo.czernobog.pl/cpu-x86-64-v2 + operator: In + values: ["true"] containers: - name: data # TEN SAM obraz co produkcja — różni się wyłącznie udziałem, na którym diff --git a/astrololo/data.yaml b/astrololo/data.yaml index b96505d..f9548d6 100644 --- a/astrololo/data.yaml +++ b/astrololo/data.yaml @@ -12,6 +12,26 @@ spec: # LOG-33: pody nie rozmawiają z API Kubernetesa, więc token konta # serwisowego jest im niepotrzebny — a zamontowany byłby gotowym # punktem wyjścia do klastra dla kogoś, kto przejmie kontener. + # Ta usługa liczy na pandas, a przez nią na NumPy. Koła NumPy z PyPI są + # budowane z bazą x86-64-v2, więc na węźle bez tych rozszerzeń kontener + # NIE WSTAJE: `import numpy` kończy się RuntimeError, pod wpada w pętlę + # restartów, a komunikat mówi o „baseline optimizations" — czyli o niczym, + # po czym dałoby się poznać, że chodzi o węzeł. + # + # Wymagana ETYKIETA, a nie wykluczony konkretny węzeł. Nowy węzeł jest + # domyślnie NIEOZNACZONY, więc nie dostanie tu poda, dopóki ktoś go nie + # sprawdzi (skrypt w README) i nie oznaczy świadomie. Pending z czytelnym + # powodem jest lepszy niż pętla restartów z komunikatem o optymalizacjach — + # a wykluczanie węzłów po nazwie znaczyłoby, że każdy KOLEJNY źle + # postawiony węzeł znów zbiera się przez awarię. + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: astrololo.czernobog.pl/cpu-x86-64-v2 + operator: In + values: ["true"] automountServiceAccountToken: false imagePullSecrets: [{ name: gitea-registry }] containers: