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 <noreply@anthropic.com>
7.2 KiB
astrodemo — wdrożenie wersji demo (PRE-28/29)
Osobna usługa o dwóch funkcjach: dodanie pliku bazy i zapytanie o
interpretację urodzeniową. Opis aplikacji: services/astrodemo/README.md
w repo aplikacji.
Jak to jest odizolowane
astrodemo → logic-demo → data-demo → /mnt/Tank1/astrololo-demo
└── klientA/ ← pula konta
└── klientB/ ← pula konta
Oryginalne bazy są dla demo nieosiągalne. Nie chodzi o uprawnienia: demo ma własną warstwę danych, pracującą na osobnym udziale, pustym na starcie.
Dlaczego osobna jest też warstwa logiczna: zna ona jeden adres warstwy danych, więc astrodemo korzystający z produkcyjnej logiki i tak trafiłby na produkcyjne bazy. Izolacja musi sięgnąć obu warstw naraz, inaczej nie ma jej wcale.
Każde konto ma własną pulę — swój podkatalog na tym udziale. Konta nie widzą swoich plików nawzajem ani w liście, ani w wynikach wyszukiwania. Pula bierze się z loginu zalogowanej osoby, nigdy z pola formularza.
Krok 1 — udział astrololo-demo na TrueNAS
Ta sama procedura co przy astrololo-state, więc jeśli tamten działa, ten też
zadziała. Po SSH na NAS:
sudo zfs create Tank1/astrololo-demo # albo: sudo mkdir -p /mnt/Tank1/astrololo-demo
midclt call sharing.nfs.query '[["path","=","/mnt/Tank1/astrololo-demo"]]' \
| python3 -m json.tool
Pusta lista [] — twórz:
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", "192.168.1.82"],
"enabled": true,
"ro": false,
"mapall_user": "root",
"mapall_group": "root"
}'
Coś zwróciło — weź id i użyj sharing.nfs.update <ID> z tą samą treścią.
midclt call service.restart nfs
sudo exportfs -v | grep astrololo-demo
Musi tam być rw. Sprawdź jeszcze zapis z węzła — to jest ten test, którego
zabrakło przy poprzednim udziale:
ssh <węzeł> 'sudo mkdir -p /mnt/t && sudo mount -t nfs 192.168.1.34:/mnt/Tank1/astrololo-demo /mnt/t \
&& sudo touch /mnt/t/proba && echo ZAPIS-OK || echo ZAPIS-NIE; sudo rm -f /mnt/t/proba; sudo umount /mnt/t'
Krok 2 — konta demo
Każde konto to osobna pula, więc rozdajesz konta, nie jedno hasło.
Hasła najlepiej jako hash — wtedy nie leżą nigdzie jawnie (skrypt jest w repo
aplikacji, services/presentation/scripts/make_user.py):
python scripts/make_user.py klientA # wypisze: scrypt$…
python scripts/make_user.py klientB
kubectl -n astrololo create secret generic astrololo-astrodemo \
--from-literal=ASTRODEMO_USERS='klientA:scrypt$…,klientB:scrypt$…' \
--from-literal=SESSION_SECRET="$(openssl rand -hex 32)"
SESSION_SECRET podpisuje ciasteczka sesji (LOG-34). Pod bez niego celowo nie
wstanie. Jest WŁASNY, nie ten z pełnej aplikacji: demo i produkcja nie mają
powodu uznawać nawzajem swoich sesji.
Zdalne unieważnienie w demo działa inaczej niż w pełnej wersji. Demo nie ma własnego wolumenu, więc nie ma gdzie trzymać licznika sesji. Zamiast tego: usunięcie konta z
ASTRODEMO_USERSalbo zmiana jego hasła natychmiast ubija jego otwarte sesje — bo odcisk poświadczenia wpisany w ciasteczko przestaje pasować. RotacjaSESSION_SECRETwylogowuje wszystkich naraz.
Dodanie konta później
STARE=$(kubectl -n astrololo get secret astrololo-astrodemo -o jsonpath='{.data.ASTRODEMO_USERS}' | base64 -d)
kubectl -n astrololo create secret generic astrololo-astrodemo \
--from-literal=ASTRODEMO_USERS="${STARE},klientC:scrypt\$…" \
--dry-run=client -o yaml | kubectl apply -f -
kubectl -n astrololo rollout restart deploy/astrodemo
Odebranie dostępu
Usuń wpis z ASTRODEMO_USERS tą samą drogą. Pula zostaje na udziale — pliki
klienta nie znikają, tylko przestaje być komu je pokazywać.
Krok 3 — tag obrazu
Zanim wdrożysz. CI pcha obrazy wyłącznie pod tagiem ośmioznakowym
(TAG=${GITHUB_SHA::8}) i nigdy nie pcha latest. Manifest z newTag: latest
zatrzyma się na ImagePullBackOff, co wygląda na problem z rejestrem albo siecią,
a jest zwykłym brakiem takiego tagu.
Po zmergowaniu zmian w repozytorium aplikacji i zbudowaniu obrazu:
TAG=$(git -C ~/git/astrololo rev-parse --short=8 master)
echo "$TAG" # ten sam ciąg musi być widoczny w logu zadania „build"
Wpisz go jako newTag przy astrololo-astrodemo w kustomization.yaml. Kolejne
wersje podbija już image-updater sam — pod warunkiem, że obraz jest na jego liście
(image-updater.yaml), co ten PR załatwia.
Krok 4 — wdrożenie
kubectl apply -k astrololo
kubectl -n astrololo rollout status deploy/data-demo deploy/logic-demo deploy/astrodemo
Sprawdzenie na czas jednej sesji, bez wystawiania na świat:
kubectl -n astrololo port-forward deploy/astrodemo 8005:8005
Wejście z zewnątrz jest już w ingress.yaml: host astrodemo.czernobog.pl,
z przekierowaniem z http na https i tym samym certyfikatem co astrololo
(tls.yaml obejmuje oba hosty).
Osobny host, a nie ścieżka /demo pod adresem astrololo — CELOWO. Ścieżka
dzieliłaby z pełną aplikacją pochodzenie w rozumieniu przeglądarki, czyli
i ciasteczka: wejście do jednej ruszałoby sesję w drugiej.
Pozostaje wpis DNS: astrodemo.czernobog.pl musi wskazywać na ten sam adres co astrololo.czernobog.pl. Bez tego Traefik nigdy nie zobaczy żądania. Celowo nie zakładam tego za Ciebie: to decyzja, pod jakim adresem świat zobaczy demo.
Import puli klienta do pełnej aplikacji
Sedno całego układu: klient, który przechodzi na pełną wersję, nie traci dotychczasowych wgrań. Jego pula to jeden katalog.
1. Zobacz, co tam jest (na NAS):
LOGIN=klientA
sudo ls -la /mnt/Tank1/astrololo-demo/$LOGIN/
2. Sprawdź kolizje nazw z bazami produkcyjnymi:
comm -12 \
<(cd /mnt/Tank1/astrololo-demo/$LOGIN && ls *.xlsx 2>/dev/null | sort) \
<(cd /mnt/Tank1/astrololo && ls *.xlsx 2>/dev/null | sort)
Pusto = brak kolizji. Cokolwiek się wypisze, przenieś ręcznie pod inną nazwą — nie nadpisuj bazy produkcyjnej.
3. Skopiuj (-n = nie nadpisuj niczego, co już jest):
sudo cp -n /mnt/Tank1/astrololo-demo/$LOGIN/*.xlsx /mnt/Tank1/astrololo/
Kopiujemy tylko pliki
.xlsx. Plik.files-state.jsonzostaje — opisuje stan wewnątrz puli demo i w produkcji nie ma sensu; produkcja ma własny.
4. Włącz je w pełnej aplikacji: zakładka Pliki, nowe bazy pojawią się jako „gotowa, odstawiona". Klikasz przełącznik przy tych, które mają wejść do użytku.
To, że nie włączają się same, jest zamierzone: przeniesienie plików jest czynnością techniczną, a decyzja, które bazy biorą udział w interpretacji, należy do Ciebie.
Odcięcie całego demo
kubectl -n astrololo scale deploy/astrodemo --replicas=0
Pule i dane zostają. Skasowanie sekretu astrololo-astrodemo zatrzyma pod (nie wstanie
bez niego) i to też jest zachowanie zamierzone.