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

187 lines
6.4 KiB
Markdown

# 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
```powershell
$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
```powershell
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:
> ```powershell
> 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):
> ```powershell
> wsl -d rancher-desktop -- sysctl -w fs.inotify.max_user_instances=1280
> ```
```powershell
# 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):
```powershell
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](https://github.com/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:
```powershell
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
```powershell
# 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
```powershell
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:
```powershell
# 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:
```powershell
kubectl rollout restart deploy/luncher -n luncher
```
**Kritérium: 0 non-2xx odpovědí, 0 connection errors.**
### Node drain
```powershell
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:
```powershell
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`:
```powershell
# 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`