7.3 KiB
7.3 KiB
Plan migracji na Kubernetes (mikroserwisy + CI/CD)
1) Co jest dziś w repo (stan wejściowy)
Ten projekt już ma podział “mikroserwisowy” w Docker Compose:
- DB stack (
devops/db/docker-compose.yml)postgres(TimescaleDB, port 5432)hasura(GraphQL Engine, port 8080)pgadmin(narzędzie dev, port 5050)
- App stack (
devops/app/docker-compose.yml)api= trade-api (Node, port 8787,devops/api/Dockerfile)frontend= trade-frontend (Node + statyczny build visualizera, port 8081,devops/app/frontend/Dockerfile)ingestor= worker (Node,devops/ingestor/Dockerfile) – opcjonalnie, profilingest
- One-shot bootstrap (
devops/tools/bootstrap/docker-compose.yml)db-init(aplikuje SQLdevops/db/initdb/001_init.sql)db-version/db-backfill(migracje “wersji” ticków)hasura-bootstrap(Node scriptdevops/db/hasura-bootstrap.mjs: track tabel + permissions + funkcje)
Konfiguracja i sekrety dziś są w tokens/*.json (gitignored) i są montowane jako pliki do kontenerów.
2) Docelowa architektura na K8s
Minimalny sensowny podział na K8s (1 namespace lub 2):
- timescaledb (stanowe) →
StatefulSet+PVC+Service - hasura →
Deployment+Service - trade-api →
Deployment+Service - trade-frontend →
Deployment+Service+Ingress - trade-ingestor →
Deployment(1 replika) alboCronJob(jeśli chcesz uruchamiać okresowo) - bootstrap / migracje →
Job(odpalane ręcznie albo jako część release’u)
Opcjonalnie:
pgadmintylko na dev/staging (nieprodukcyjnie).
3) Proponowane zasoby Kubernetes (mapowanie 1:1 z Compose)
3.1 timescaledb (Postgres)
StatefulSetzvolumeClaimTemplates(dane w PVC)ServicetypuClusterIP(np.timescaledb:5432)- Init schematu:
- na pierwszy start można nadal użyć mechanizmu
/docker-entrypoint-initdb.d(ConfigMap z SQL), - dla istniejących wolumenów potrzebny jest osobny
Job(odpowiednikdb-initz compose).
- na pierwszy start można nadal użyć mechanizmu
3.2 Hasura
Deployment+Service(hasura:8080)Secretna:HASURA_GRAPHQL_ADMIN_SECRET- klucz JWT (
HASURA_GRAPHQL_JWT_SECRET/HASURA_JWT_KEY) - connection string do Postgresa (albo osobno hasło)
- Bootstrap metadanych:
Joburuchamiającydevops/db/hasura-bootstrap.mjs(odpowiednikhasura-bootstrap).
3.3 trade-api
Deployment+Service(trade-api:8787)readinessProbe/livenessProbe:GET /healthz(już istnieje)- Konfiguracja:
- env:
HASURA_GRAPHQL_URL,TICKS_TABLE,CANDLES_FUNCTION,APP_VERSION,BUILD_TIMESTAMP - sekret plikowy (jak dziś):
tokens/hasura.json+tokens/api.json→Secretmontowany do/app/tokens/*
- env:
3.4 trade-frontend
Deployment+Service(trade-frontend:8081)Ingresswystawiający UI na zewnątrz (TLS opcjonalnie)readinessProbe/livenessProbe:GET /healthz(już istnieje)- Sekrety plikowe:
tokens/frontend.json(basic auth do UI)tokens/read.json(read token do proxy/api/*)- oba jako
Secretmontowany do/tokens/*
API_UPSTREAM:http://trade-api:8787(Service DNS)
3.5 trade-ingestor
Deployment(zwyklereplicas: 1)- Sekrety:
- RPC do Drift (np.
tokens/heliusN.json/rpcUrl/heliusApiKey) - write token do API (
tokens/alg.json)
- RPC do Drift (np.
- Konfiguracja:
MARKET_NAME,INTERVAL_MS,SOURCE,INGEST_API_URL=http://trade-api:8787
- Uwaga: worker wymaga egress do internetu (Helius RPC + Drift).
3.6 Jobs: db-init / db-version / db-backfill / hasura-bootstrap
Bezpieczny pattern:
- uruchamiane manualnie (kubectl) albo jako “hook” w Helm (pre/post-install)
- odpalane w tym samym namespace co DB/Hasura (żeby DNS działał prosto)
4) Sekrety i konfiguracja (z tokens/ → K8s)
Rekomendacja: rozdziel na 2 typy:
- Secret (nie commitować w git):
tokens/hasura.json(adminSecret, jwtKey)tokens/api.json(api adminSecret)tokens/frontend.json(basic auth)tokens/read.json(read token)tokens/alg.json(write token)tokens/heliusN.json(RPC token / url)
- ConfigMap:
- wersja i parametry nie-wrażliwe:
APP_VERSION,BUILD_TIMESTAMP,TICKS_TABLE,CANDLES_FUNCTION,MARKET_NAME,INTERVAL_MS
- wersja i parametry nie-wrażliwe:
Jeśli chcesz GitOps bez trzymania sekretów “na piechotę”, wybierz jedno:
- Sealed Secrets (zaszyfrowane sekrety w repo),
- External Secrets Operator (Vault / AWS / GCP / Azure),
- “na start” manualne
kubectl create secret ...per środowisko.
5) Wersjonowanie (v1, v2…) i cutover bez wyłączania DB
W scripts/ops/ jest workflow wersjonowania Compose:
- nowa wersja
api+frontend(+ingestor)działa równolegle - pisze do nowej tabeli (
drift_ticks_vN) i używa nowej funkcji (get_drift_candles_vN)
Na K8s najprościej odwzorować to tak:
- Helm release name albo suffix w nazwach zasobów:
trade-v1,trade-v2, … - wspólne DB/Hasura pozostają bez zmian
Job“version-init”:- odpala SQL migracji (odpowiednik
db-version) - odpala
hasura-bootstrapzTICKS_TABLEiCANDLES_FUNCTIONustawionymi na vN
- odpala SQL migracji (odpowiednik
- “cutover”:
- startujesz
trade-ingestorvN - stopujesz
trade-ingestorv1 - po czasie robisz
db-backfill(opcjonalnie) i sprzątasz stare zasoby
- startujesz
6) CI/CD “na gita” (build → deploy po pushu)
Opcja A (polecana): GitOps (Argo CD / Flux)
- CI (GitHub Actions / GitLab CI) buduje obrazy:
trade-apitrade-frontendtrade-ingestor
- CI publikuje je do registry (np. GHCR)
- CD (ArgoCD/Flux) automatycznie synchronizuje manifesty/Helm z repo i robi rollout
Tagowanie obrazów:
:sha-<shortsha>dla każdego commita- opcjonalnie
:vNdla release’ów
Aktualizacja tagów:
- ArgoCD Image Updater / Flux Image Automation albo
- CI robi commit do
k8s/(np. podmienia tag wvalues.yaml)
Opcja B (prostsza na start): “kubectl apply” z CI
- CI buduje i pushuje obrazy
- CI wykonuje
helm upgrade --installalbokubectl apply -k ... - Dostęp do klastra przez sekret w repo (kubeconfig / token)
7) Proponowana sekwencja migracji (checklista)
- Decyzje: gdzie stoi klaster (EKS/GKE/AKS/k3s), jakie registry, jaki Ingress, jak trzymamy sekrety.
- K8s “base”: namespace, storage class, ingress controller, certy (jeśli TLS).
- DB: wdroż Timescale (StatefulSet + PVC), odpal
db-initjob. - Hasura: wdroż Hasurę, odpal
hasura-bootstrapjob. - API: wdroż
trade-api, sprawdź/healthz. - Tokeny: wygeneruj read/write tokeny (obecnym mechanizmem API) i wgraj je jako Secrets.
- Frontend: wdroż
trade-frontend+ Ingress, sprawdź/healthzi UI. - Ingestor: wdroż
trade-ingestor(1 replika), potwierdź że ticki wpadają. - CI/CD: dodaj workflow build+push i deploy (GitOps albo kubectl).
- Staging → Prod: rollout na staging, potem prod.
8) Pytania, które domykają plan
- Jaki “git”: GitHub czy GitLab?
- Gdzie ma stać K8s: cloud (EKS/GKE/AKS) czy on-prem/k3s?
- DB w klastrze (StatefulSet) czy zewnętrzny managed Postgres/Timescale?
- Czy “po pushu” ma:
- tylko robić rollout na
main, - czy tworzyć preview env per branch/PR,
- czy startować nową wersję vN równolegle (jak
scripts/ops/)?
- tylko robić rollout na
- Jaki dostęp z zewnątrz: domena + TLS, czy wystarczy port-forward / internal?