Files
Luncher/k8s/README.md
T
batmanisko 67abbf19b5
CI / Generate TypeScript types (push) Successful in 10s
CI / Server unit tests (push) Successful in 20s
CI / Build server (push) Successful in 26s
CI / Build client (push) Successful in 35s
CI / Playwright E2E tests (push) Failing after 1m56s
CI / Build and push Docker image (push) Has been skipped
CI / Notify (push) Successful in 1s
feat: podpora high-availability a multi-replica nasazení
- Socket.io Redis adapter pro sdílený stav přes repliky
- graceful shutdown serveru
- WATCH/MULTI v updateData pro race-condition-safe aktualizace
- lease mechanismus pro push reminder (zabrání duplicitnímu odesílání)
- k8s/ manifesty pro testovací kind cluster
- Dockerfile: opraven EXPOSE port na 3001
- .gitignore: ignorovány Claude pracovní soubory
2026-05-20 17:16:19 +02:00

6.4 KiB

Kubernetes — Luncher HA

Manifesty pro nasazení Luncheru na Kubernetes s vysokou dostupností (3 repliky, Redis adapter pro Socket.io, WATCH/MULTI atomické zápisy, graceful shutdown).

Prerekvizity

  • kubectl nakonfigurovaný na cílový cluster
  • helm nainstalovaný
  • Redis Stack image přístupný z clusteru (redis/redis-stack-server:7.2.0-v14)
  • Obraz luncher:ha-test načtený do clusteru (viz níže)

Lokální kind cluster (testik) — setup

1. Smazat a znovu vytvořit cluster s port mappings

$env:KIND_EXPERIMENTAL_PROVIDER = "nerdctl"
# Přidat nerdctl do PATH (Rancher Desktop)
$env:PATH += ";$env:LOCALAPPDATA\Programs\Rancher Desktop\resources\resources\win32\bin"

kind delete cluster --name testik
kind create cluster --name testik --config k8s/kind/testik.yaml

2. Sestavit a načíst obraz

docker build -t luncher:ha-test .

# Uložit a načíst přes nerdctl (kind + nerdctl provider)
nerdctl save luncher:ha-test -o luncher.tar
kind load image-archive luncher.tar --name testik
Remove-Item luncher.tar

3. Nainstalovat Traefik (rke2-traefik)

Prerekvizita (Rancher Desktop): Pokud Rancher Desktop běží s kubernetes.options.traefik=true, host-switch.exe obsadí port 80 dříve než kind. Vypni traefik v k3s:

rdctl set --kubernetes.options.traefik=false

Prerekvizita — inotify limity: Čtyř-uzlový kind cluster vyčerpá výchozí fs.inotify.max_user_instances=128. kube-proxy pak padá s „too many open files". Zvyš limit v rancher-desktop WSL2 (přežije restart WSL2, ale ne reboot — přidej do /etc/sysctl.d/99-kind.conf pro trvalost):

wsl -d rancher-desktop -- sysctl -w fs.inotify.max_user_instances=1280
# rke2-traefik je v rke2-charts, ne rancher-charts
helm repo add rke2-charts https://rke2-charts.rancher.io
helm repo update

# Nejdřív CRD chart, pak samotný chart
helm install traefik-crd rke2-charts/rke2-traefik-crd -n kube-system --create-namespace
helm install traefik rke2-charts/rke2-traefik -n kube-system `
  --set "tolerations[0].key=node-role.kubernetes.io/control-plane" `
  --set "tolerations[0].operator=Exists" `
  --set "tolerations[0].effect=NoSchedule"

Ověř že Traefik DaemonSet běží na control-plane (má hostPort 80):

kubectl get ds -n kube-system traefik-rke2-traefik
kubectl get pods -n kube-system -o wide | Select-String traefik

4. Nainstalovat Reloader

stakater/Reloader sleduje změny Secret a ConfigMap a automaticky spustí rolling restart Deploymentu — odpadá nutnost ručního kubectl rollout restart po rotaci JWT_SECRET nebo ADMIN_PASSWORD.

Manifest je vendorovaný ve verzi v1.4.16 (k8s/base/reloader.yaml). Nasadit do default namespace:

kubectl apply -f k8s/base/reloader.yaml
kubectl rollout status deploy/reloader-reloader

Reloader běží cluster-wide díky ClusterRoleBinding — nepotřebuje žádnou konfiguraci per-namespace. Deployment Luncheru má anotaci reloader.stakater.com/auto: "true", která říká Reloaderu, ať sleduje všechny Secrety a ConfigMapy odkazované přes envFrom.

5. Nasadit Luncher

# Namespace + Redis
kubectl apply -f k8s/base/namespace.yaml
kubectl apply -f k8s/base/redis-statefulset.yaml
kubectl apply -f k8s/base/redis-service.yaml

# Počkat na Redis
kubectl rollout status statefulset/redis -n luncher

# Server secret (nebo použít šablonu server-secret.yaml)
kubectl create secret generic luncher-secrets -n luncher `
  --from-literal=JWT_SECRET=dev-secret-change-me `
  --from-literal=ADMIN_PASSWORD=admin

# Server
kubectl apply -f k8s/base/server-configmap.yaml
kubectl apply -f k8s/base/server-deployment.yaml
kubectl apply -f k8s/base/server-service.yaml
kubectl apply -f k8s/base/server-pdb.yaml
kubectl apply -f k8s/base/ingressroute.yaml

# Počkat na server
kubectl rollout status deploy/luncher -n luncher

Testovací scénáře

Baseline

kubectl get pods -n luncher -o wide
# Ověř: 3 pody na 3 různých worker uzlech, status Running

Rolling update bez výpadku

V jednom terminálu posílej provoz:

# Nainstaluj hey: go install github.com/rakyll/hey@latest
hey -z 60s -c 20 http://luncher.localhost/api/health

Ve druhém terminálu spusť rollout:

kubectl rollout restart deploy/luncher -n luncher

Kritérium: 0 non-2xx odpovědí, 0 connection errors.

Node drain

kubectl cordon testik-worker2
kubectl drain testik-worker2 --ignore-daemonsets --delete-emptydir-data
# PDB zabrání souběžnému drainu druhého nodu
kubectl get pods -n luncher -o wide  # pody se přeplánují
kubectl uncordon testik-worker2

Ověření Socket.io cross-pod

  1. Otevři dvě záložky prohlížeče na http://luncher.localhost
  2. Z jednoho podu vyvolej změnu:
    kubectl exec -it deploy/luncher -n luncher -- curl -s -X POST localhost:3001/api/...
    
  3. Ověř, že druhá záložka (pravděpodobně jiný pod) obdrží WebSocket event

Concurrent write test

  1. Otevři stejnou Pizza day objednávku ve dvou záložkách
  2. Simuluj souběžné odeslání (otevřít DevTools → síť → odeslat obě požadavky současně)
  3. Ověř Redis: kubectl exec -it redis-0 -n luncher -- redis-cli JSON.GET luncher:<datum> — oba zápisy musí být zachovány (WATCH/MULTI retry)

Auto-rollout při změně Secret / ConfigMap

Reloader automaticky spustí rolling restart, kdykoli se změní luncher-secrets nebo luncher-config:

# Příklad: rotace admin hesla
kubectl -n luncher patch secret luncher-secrets --type=merge `
  -p '{"stringData":{"ADMIN_PASSWORD":"nove-heslo"}}'

# Reloader detekuje změnu resourceVersion a patchne pod template
kubectl rollout status deploy/luncher -n luncher

# Ověř anotaci přidanou Reloaderem na pod template
kubectl get deploy luncher -n luncher -o yaml | Select-String "STAKATER"

Kritérium: pody se automaticky vyrolují bez ručního restartu. PDB zajistí, že alespoň jeden pod zůstane dostupný.

Pořadí aplikace manifestů

  1. reloader.yaml (do default namespace — musí být před Deployment)
  2. namespace.yaml
  3. redis-statefulset.yaml + redis-service.yaml
  4. server-configmap.yaml + server-secret.yaml
  5. server-deployment.yaml + server-service.yaml + server-pdb.yaml
  6. ingressroute.yaml