14 KiB
14 KiB
steps.md
Log działań wykonywanych w ramach migracji trade → k3s + Gitea + GitOps (pull).
Uwaga: nie zapisuję sekretów (hasła, tokeny, prywatne klucze) – jeśli pojawiają się w outputach narzędzi, są pomijane/redagowane.
2026-01-05
Repo: inwentaryzacja i plan
- Przejrzano strukturę repo (
apps/,devops/,services/,doc/) i istniejące Compose stacki:- DB:
devops/db/docker-compose.yml - App:
devops/app/docker-compose.yml - Bootstrap (one-shot):
devops/tools/bootstrap/docker-compose.yml
- DB:
- Sprawdzono Dockerfile:
- API:
devops/api/Dockerfile - Frontend:
devops/app/frontend/Dockerfile - Ingestor:
devops/ingestor/Dockerfile
- API:
- Sprawdzono skrypty wersjonowania Compose (v1/v2…):
scripts/ops/*+ env:devops/versions/v1.env. - Dodano dokument planu migracji:
doc/migration.md.
Gitea: repo GitOps (MCP Gitea)
- Utworzono repo
trade/trade-deploy(public,main, auto-init). - Dodano szkielet Kustomize:
kustomize/base/(placeholder ConfigMap)kustomize/overlays/staging/(namespace: trade-staging)kustomize/overlays/prod/(namespace: trade-prod)
- Dodano bootstrap manifesty Argo CD Application:
bootstrap/argocd/application-trade-staging.yaml(auto-sync + CreateNamespace)bootstrap/argocd/application-trade-prod.yaml(CreateNamespace, bez auto-sync)
- Dodano DB stack do
trade-deploy(manifests + bootstrap):- Postgres/Timescale:
kustomize/base/postgres/*+ init SQL:kustomize/base/initdb/001_init.sql - Hasura:
kustomize/base/hasura/*+ jobhasura-bootstrap(track tables/functions) - Staging:
kustomize/overlays/staging/pgadmin.yaml+ patch Hasury (console/dev mode) - Zaktualizowano
README.mdwtrade-deployo wymagane sekrety i port-forward.
- Postgres/Timescale:
VPS: audyt stanu (MCP SSH)
- Host:
qstack(Debian), k3s działa; dostęp do klastra uzyskany przezKUBECONFIG=/etc/rancher/k3s/k3s.yaml(bez sudo). - Ingress: Traefik działa (LB na
77.90.8.171, porty 80/443). - TLS: cert-manager działa;
ClusterIssuer/letsencrypt-prodjestReady=True. - Gitea jest zainstalowana w k3s (Helm release
giteaw namespacegitea), Ingress narv32i.pl, certrv32i-pl-tlsjestReady=True. - GitOps controller (Argo CD / Flux): nie znaleziono (brak namespace
argocdiflux-system). - Wdrożenia aplikacji
trade-*w k3s: nie znaleziono (brak deploy/podów z nazwątrade). - Registry: endpoint
https://rv32i.pl/v2/odpowiada (401 bez autoryzacji).
Gitea: audyt stanu (MCP Gitea)
- Zalogowany użytkownik:
u1(admin). - Organizacja
tradeistnieje; są utworzone repozytoria (puste, bez commitów/branchy):trade/trade-apitrade/trade-frontendtrade/trade-ingestortrade/trade-infra
- Repo
trade-deploy(manifesty GitOps): nie znaleziono.
VPS: Argo CD (MCP SSH)
- Zainstalowano Argo CD przez Helm: release
argocdw namespaceargocd(argo/argo-cd). - Utworzono
Applicationdla staging ztrade-deploy:- zastosowano
bootstrap/argocd/application-trade-staging.yaml - Argo utworzyło namespace
trade-stagingi zsynchronizowało placeholder ConfigMaptrade-deploy-info.
- zastosowano
- Uwaga: jeśli port
8080jest zajęty lokalnie (np. przez Hasurę), do port-forward użyj innego portu (np.8090:443).
VPS: Gitea Actions runner (MCP SSH)
- Wykryto wymaganie:
sudowymaga hasła, więc runner postawiony w k3s (bez instalacji binarki na hoście). - Utworzono namespace
gitea-actionsoraz zasoby dlaact_runner(DinD sidecar + runner):- manifest w
trade-deploy:bootstrap/gitea-actions/act-runner.yaml - sekret
act-runner-registration-tokenutworzony w klastrze z tokena rejestracyjnego pobranego z Gitei (API admin; token nie trafia do gita)
- manifest w
- Naprawiono start Dockera w sidecar:
- początkowo próba po unix-sockecie powodowała konflikt (
docker.sockjako katalog) - finalnie ustawiono
DOCKER_HOST=tcp://127.0.0.1:2375(runner ↔ dind po localhost), co uruchomiło runnera poprawnie.
- początkowo próba po unix-sockecie powodowała konflikt (
Uwaga: seed sekretów (blokada narzędzia)
- Przy próbie seedowania sekretów do
trade-stagingprzez MCP SSH pojawił się trwały timeout na każde polecenie (ssh-mcp/exec), więc ten krok został opisany wtrade-deploy/README.mddo wykonania ręcznie na VPS.
VPS: dostęp SSH kluczem (wymagane hasło)
- Użytkownik poprosił o używanie naszego klucza prywatnego dla VPS:
k/qstack/qstack. - Klucz jest zaszyfrowany hasłem (passphrase). Bez podania passphrase nie da się go użyć w trybie nieinteraktywnym (
ssh/ssh-keygenzwraca błąd o niepoprawnym passphrase / brakssh-askpass). - Żeby kontynuować automatyzację z tej sesji są 2 opcje:
- dostarczyć passphrase poza czatem (np. lokalnie w pliku w
tokens/, gitignored) i używaćSSH_ASKPASS, albo - wygenerować osobny klucz bez passphrase jako “deploy key” tylko do automatyzacji i dodać jego publiczną część do
~user/.ssh/authorized_keysna VPS.
- dostarczyć passphrase poza czatem (np. lokalnie w pliku w
Następne kroki (do zrobienia)
- Wybrać GitOps controller (Argo CD vs Flux) i zainstalować w k3s.
- Utworzyć repo
trade-deployi dodać strukturę Helm/Kustomize (staging/prod). - Postawić runner CI (Gitea Actions
act_runnerlub alternatywa) i dodać pipeline build+push obrazów. - Dopiero potem: manifesty K8s dla
trade-api/trade-frontend/trade-ingestor+ DB/Hasura + joby migracji.
2026-01-06
VPS: SSH kluczem projektu (passphrase)
- Użyto klucza prywatnego
k/qstack/qstackdo połączenia z VPS przezssh(zSSH_ASKPASSczytającym passphrase ztokens/vps-ssh.json, plik gitignored). - Skrypt
tokens/ssh-askpass.shbył tworzony tymczasowo i został usunięty po użyciu (żeby nie ryzykować przypadkowego commita).
Doprecyzowanie dostępu i bezpieczeństwo repo
- Dopisano w
doc/migration.mdbieżący status VPS/k3s oraz komendy do Argo CD (port-forward na8090) i logów runnera. - Zaktualizowano
.gitignore, żeby ignorować sekrety/klucze lokalne:tokens/*,k/,argo/pass,gitea/token.
k3s: seed sekretów (staging)
- Utworzono sekrety w namespace
trade-staging(wartości wygenerowane losowo, nie logowane):trade-postgres(POSTGRES_*)trade-hasura(HASURA_GRAPHQL_ADMIN_SECRET,HASURA_JWT_KEY)trade-pgadmin(PGADMIN_DEFAULT_*)
Argo CD: deploy DB stack (staging)
- Wymuszono refresh aplikacji Argo
trade-staging(annotationargocd.argoproj.io/refresh=hard). - Status:
trade-staging=Synced/Healthy. - Workloady w
trade-stagingdziałają:StatefulSet/postgres=postgres-0 RunningDeployment/hasura=RunningDeployment/pgadmin=RunningJob/hasura-bootstrap=Completed(log:[hasura-bootstrap] ok)
Portainer: dlaczego nie widać k3s (wyjaśnienie)
- Portainer uruchomiony jako kontener Docker domyślnie widzi tylko środowisko Docker; k3s używa
containerd, więc nie zobaczysz „podów” wdocker psani w Portainerze jako kontenerów Dockera. - Żeby Portainer widział „wnętrze” k3s trzeba dodać środowisko typu
Kubernetesw Portainer UI albo postawić Portainera bezpośrednio w klastrze (rekomendowane).
Portainer (opcja A): wdrożenie w k3s + Ingress portainer.rv32i.pl
- Dodano do GitOps repo
trade/trade-deploypaczkę Kustomize:kustomize/infra/portainer(Namespace+RBAC+PVC+Deployment+Service+Ingress). - Dodano Argo CD
Applicationdla Portainera:bootstrap/argocd/application-portainer.yaml. - Zastosowano
Applicationna VPS i potwierdzono status:portainer=Synced/Healthy. - Ingress utworzony na host
portainer.rv32i.pl(Traefik). - cert-manager utworzył
Certificate/portainer-rv32i-pl-tls, ale ACME jestpendingdopóki DNSportainer.rv32i.plnie wskazuje na77.90.8.171(brak rekordu A w momencie sprawdzania).
Portainer: DNS + TLS + odblokowanie „New Portainer installation timed out”
- Potwierdzono, że rekord A
portainer.rv32i.plistnieje na autorytatywnych DNS (dns*.home.pl) i rozwiązuje się na publicznych resolverach. - Zrestartowano
Deployment/portainerw namespaceportainer, żeby odblokować ekran inicjalizacji (komunikat “timed out for security purposes”). - cert-manager miał „zawieszone” HTTP-01 self-check przez cache NXDOMAIN w klastrze; zrestartowano
Deployment/corednswkube-system, po czym certyfikat stał sięReady=True(Certificate/portainer-rv32i-pl-tls).
Registry: token do Gitea Packages + docker login
- Na VPS (z poziomu poda Gitei) wygenerowano token
read:package,write:packagedla użytkownikau1:- polecenie:
gitea admin user generate-access-token --username u1 --scopes "read:package,write:package" --raw - token zapisany lokalnie w
tokens/gitea-registry.token(gitignored; wartość nie jest logowana).
- polecenie:
- Wykonano
docker login rv32i.pl(bez logowania tokena). - Zaktualizowano
.dockerignore, żeby nie wysyłać do build context katalogów z sekretami/kluczami (tokens/*,k/,gitea/,argo/).
Obrazy: build + push (trade-api, trade-ingestor)
- Zbudowano i wypchnięto obrazy do Gitea registry:
rv32i.pl/trade/trade-api:k3s-20260106013603rv32i.pl/trade/trade-ingestor:k3s-20260106013603
- Tag zapisany lokalnie w
tokens/last-image-tag.txt(gitignored).
GitOps: manifesty k3s dla API + ingestor (trade-deploy)
- Dodano do repo
trade/trade-deploy:kustomize/base/api/deployment.yaml+kustomize/base/api/service.yamlkustomize/base/ingestor/deployment.yaml- aktualizacja
kustomize/base/kustomization.yaml(dopięcie nowych zasobów).
- Konfiguracja:
trade-apiużywaHASURA_GRAPHQL_URL=http://hasura:8080/v1/graphqli sekretówtrade-hasura+trade-api(admin).trade-ingestorstartuje w trybieINGEST_VIA=hasura(bez tokenów API) i używatrade-hasura+trade-ingestor-tokens(RPC).
k3s: seedy sekretów + weryfikacja (staging)
- Utworzono w
trade-staging:Secret/gitea-registry(imagePullSecret dorv32i.pl)Secret/trade-api(API_ADMIN_SECRET, wygenerowany losowo; nie logowany)Secret/trade-ingestor-tokens(plikheliusN.json; wartość nie logowana)
- Argo CD
Application/trade-stagingpo refresh:Synced/Healthy. - Pody w
trade-staginguruchomione:trade-apiitrade-ingestor(Running). - Logi:
trade-apistartuje i maskuje sekrety (***).trade-ingestorpobiera ceny i ingestuje ticki; URL RPC jest redagowany (api-key=***).
Ingest przez API + tokeny read/write
- Zmieniono
trade-ingestornaINGEST_VIA=api(pisze dotrade-apizamiast bezpośrednio do Hasury); manifest wtrade/trade-deploy:kustomize/base/ingestor/deployment.yaml. - Utworzono tokeny w
trade-api:write(dla ingestora) orazread(dla klientów UI/odczytu)- tokeny zapisane jako K8s Secrets (wartości nie logowane):
trade-staging/Secret/trade-ingestor-tokens:alg.json(write) +heliusN.json(RPC)trade-staging/Secret/trade-read-token:read.json(read)
- Wymuszono rollout
Deployment/trade-ingestori potwierdzono w logach:ingestVia: "api",writeUrl: "http://trade-api:8787/v1/ingest/tick",auth: "bearer".
- Potwierdzono, że
trade-api /v1/ticksdziała z tokenemread(bez ujawniania tokena).
Frontend: deploy na k3s (staging) + Ingress trade.rv32i.pl
- Zbudowano i wypchnięto obraz do Gitea registry:
rv32i.pl/trade/trade-frontend:k3s-20260106013603
- Dodano manifesty do
trade/trade-deploy:kustomize/base/frontend/deployment.yaml+kustomize/base/frontend/service.yaml- staging:
kustomize/overlays/staging/frontend-ingress.yaml(hosttrade.rv32i.pl) - aktualizacje
kustomize/base/kustomization.yamlikustomize/overlays/staging/kustomization.yaml.
- Utworzono sekret
trade-staging/Secret/trade-frontend-tokens(plikifrontend.json+read.json; wartości nie logowane). - Argo CD
Application/trade-staging:Synced/Healthy;Deployment/trade-frontend=Running,/healthzdziała. - TLS dla
trade.rv32i.pljestpendingdopóki DNStrade.rv32i.plnie wskazuje na77.90.8.171(w razie cache NXDOMAIN: restartkube-system/corednsjak wcześniej).
DNS: trade.rv32i.pl (weryfikacja)
- Sprawdzono rekord A
trade.rv32i.plna autorytatywnych DNS (dns*.home.pl) oraz na publicznych resolverach: brak odpowiedzi (rekord nie był jeszcze widoczny na NS), więc cert-manager trzymatrade-rv32i-pl-tlsw staniepending(NXDOMAIN). - Uwaga: jeśli w panelu DNS dodasz rekord i nadal masz
NXDOMAIN, sprawdź czy host nie ma literówki (np.radezamiasttrade) i czy rekord jest zapisany jako A/CNAME dla właściwej nazwytrade.rv32i.pl.
DNS/TLS: trade.rv32i.pl (finalizacja)
- Użytkownik potwierdził rekord A
trade.rv32i.pl→77.90.8.171na autorytatywnych DNS (dns.home.pl). - Na VPS potwierdzono:
Ingress/trade-frontendma hosttrade.rv32i.pl.Certificate/trade-rv32i-pl-tls=Ready=True.https://trade.rv32i.plodpowiadaHTTP 401(basic auth) – czyli Ingress + TLS działają.
Weryfikacja wdrożenia (MCP SSH)
argocd/Application:trade-stagingiportainer=Synced/Healthy.trade-staging: wszystkie workloadyRunning(Postgres/Hasura/pgAdmin/trade-api/trade-ingestor/trade-frontend).trade-ingestormaINGEST_VIA=apiorazINGEST_API_URL=http://trade-api:8787(ingest przez API z tokenem write).
Portainer: odblokowanie ekranu timeout.html
- Zrestartowano
Deployment/portainerw namespaceportainer, żeby ponownie pojawił się kreator inicjalizacji (admin user/password).
Gitea: lista repo w organizacji trade
trade/trade-apitrade/trade-deploytrade/trade-doctrade/trade-frontendtrade/trade-infratrade/trade-ingestor
2026-01-06
Zmiana: log działań w doc/
- Przeniesiono log działań z
steps.md→doc/steps.md(zgodnie z nową zasadą: wszystko projektowe ląduje wdoc/).
Superproject: decyzja + plan (do akceptacji)
- Zaproponowano
trade/trade-infrajako repo główne (superproject) spinające subrepo (API/ingestor/frontend/deploy/doc). - Plan refaktoru opisany w
doc/migration.md(sekcja „Metoda superproject”). - Użytkownik zaakceptował
trade/trade-infrajako superproject; do decyzji pozostało:submodulesvssubtree(rekomendacja: submodules, jeśli chcemy zachować niezależne repo + pinowanie wersji).