xpeditis2.0/docs/deployment/hetzner/08-redis-setup.md
2026-03-26 18:08:28 +01:00

314 lines
7.4 KiB
Markdown

# 08 — Redis Setup
Redis est utilisé dans Xpeditis pour :
1. **Cache des rate quotes** — clés `rate:{origin}:{destination}:{containerType}`, TTL 15 min
2. **Pub/sub WebSocket** — Socket.IO multi-pods nécessite Redis pour broadcaster les notifications
---
## Option A — Upstash (recommandé pour MVP)
### Pourquoi Upstash
- Redis serverless, pay-per-use ($0.2 per 100K commands)
- Free tier : 10 000 commandes/jour, 256 MB (suffisant pour 100 users)
- Compatible avec l'interface Redis standard (ioredis)
- Support TLS natif
- Régions EU disponibles (Frankfurt)
- **Pas de serveur à gérer**
### Setup Upstash
1. Créez un compte sur https://upstash.com
2. **Create Database**
- Name: `xpeditis-prod`
- Region: `EU-WEST-1 (Frankfurt)` ← le plus proche de Hetzner FSN1
- Type: **Regional** (pas Global pour commencer)
- Eviction: **Allkeys-LRU** (expire les clés les plus anciennes si mémoire pleine)
- TLS: **Enabled**
3. Copiez les credentials affichés
### Variables d'environnement
```bash
# Upstash fournit une URL Redis complète
REDIS_HOST=your-redis.upstash.io
REDIS_PORT=6379
REDIS_PASSWORD=<upstash_token>
REDIS_DB=0
# OU avec URL (si le code le supporte)
REDIS_URL=redis://:password@your-redis.upstash.io:6379
```
### Vérification de la connexion
```bash
# Test avec redis-cli
redis-cli -h your-redis.upstash.io -p 6379 -a <password> --tls ping
# PONG
# Test de set/get
redis-cli -h your-redis.upstash.io -p 6379 -a <password> --tls \
SET test:connection "xpeditis-ok" EX 60
redis-cli -h your-redis.upstash.io -p 6379 -a <password> --tls \
GET test:connection
# "xpeditis-ok"
```
### Configuration dans l'app Xpeditis
Le code NestJS utilise `ioredis`. Vérifiez que TLS est activé dans la config cache :
Dans `apps/backend/src/infrastructure/cache/cache.module.ts`, assurez-vous que la config Redis accepte TLS :
```typescript
// La config doit inclure TLS pour Upstash
const redisOptions = {
host: configService.get('REDIS_HOST'),
port: configService.get<number>('REDIS_PORT', 6379),
password: configService.get('REDIS_PASSWORD'),
db: configService.get<number>('REDIS_DB', 0),
// TLS requis pour Upstash
tls: configService.get('NODE_ENV') === 'production' ? {} : undefined,
};
```
> Si la config actuelle ne supporte pas TLS, ajoutez la variable `REDIS_TLS=true` et adaptez le cache module en conséquence.
---
## Option B — Redis self-hosted dans k3s
### Quand choisir cette option
- 1 000+ users (le free tier Upstash devient limité)
- Besoin de Redis Cluster pour le WebSocket à grande échelle
- Contrôle total des données
### StatefulSet Redis dans Kubernetes
```bash
# Créer le namespace si pas encore fait
kubectl create namespace xpeditis-prod 2>/dev/null || true
# Créer le Secret Redis
cat > /tmp/redis-secret.yaml << 'EOF'
apiVersion: v1
kind: Secret
metadata:
name: redis-secret
namespace: xpeditis-prod
type: Opaque
stringData:
REDIS_PASSWORD: "<MOT_DE_PASSE_FORT_REDIS>"
EOF
kubectl apply -f /tmp/redis-secret.yaml
# Créer la ConfigMap Redis
cat > /tmp/redis-config.yaml << 'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-config
namespace: xpeditis-prod
data:
redis.conf: |
# Sécurité
requirepass <MOT_DE_PASSE_FORT_REDIS>
protected-mode yes
# Persistance (AOF pour durabilité)
appendonly yes
appendfsync everysec
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# Mémoire
maxmemory 512mb
maxmemory-policy allkeys-lru
# Réseau
bind 0.0.0.0
tcp-backlog 511
timeout 0
tcp-keepalive 300
# Logging
loglevel notice
# Performances
lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
EOF
kubectl apply -f /tmp/redis-config.yaml
# Créer le StatefulSet Redis
cat > /tmp/redis-statefulset.yaml << 'EOF'
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
namespace: xpeditis-prod
spec:
serviceName: redis-headless
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7-alpine
ports:
- containerPort: 6379
name: redis
command:
- redis-server
- /etc/redis/redis.conf
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: redis-secret
key: REDIS_PASSWORD
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
volumeMounts:
- name: redis-config-vol
mountPath: /etc/redis
- name: redis-data
mountPath: /data
readinessProbe:
exec:
command:
- redis-cli
- -a
- $(REDIS_PASSWORD)
- ping
initialDelaySeconds: 10
periodSeconds: 5
livenessProbe:
exec:
command:
- redis-cli
- -a
- $(REDIS_PASSWORD)
- ping
initialDelaySeconds: 30
periodSeconds: 30
volumes:
- name: redis-config-vol
configMap:
name: redis-config
volumeClaimTemplates:
- metadata:
name: redis-data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: hcloud-volumes
resources:
requests:
storage: 5Gi
---
apiVersion: v1
kind: Service
metadata:
name: redis-headless
namespace: xpeditis-prod
spec:
clusterIP: None
selector:
app: redis
ports:
- port: 6379
targetPort: 6379
---
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: xpeditis-prod
spec:
selector:
app: redis
ports:
- port: 6379
targetPort: 6379
type: ClusterIP
EOF
kubectl apply -f /tmp/redis-statefulset.yaml
# Attendre que Redis soit prêt
kubectl rollout status statefulset/redis -n xpeditis-prod --timeout=120s
# Tester Redis
kubectl exec -it redis-0 -n xpeditis-prod -- redis-cli -a <password> ping
# PONG
```
### Variables d'environnement pour Redis self-hosted
```bash
REDIS_HOST=redis.xpeditis-prod.svc.cluster.local
REDIS_PORT=6379
REDIS_PASSWORD=<MOT_DE_PASSE_FORT_REDIS>
REDIS_DB=0
# Pas de TLS (réseau privé interne k3s)
```
---
## Vérification du cache Redis dans Xpeditis
Après déploiement de l'application, vérifiez que le cache fonctionne :
```bash
# Se connecter à Redis
kubectl exec -it redis-0 -n xpeditis-prod -- redis-cli -a <password>
# Après quelques rate searches depuis l'app :
KEYS rate:*
# 1) "rate:FRNCE:DEHAM:20ft"
# 2) "rate:FRNCE:NLRTM:20ft"
# ...
# Vérifier un TTL (doit être < 900 = 15 min)
TTL "rate:FRNCE:DEHAM:20ft"
# (integer) 647
# Stats globales
INFO stats
# keyspace_hits: 1234
# keyspace_misses: 156
# → Taux de hit = 1234/(1234+156) = 88% ✅
```
---
## Comparaison des options
| Critère | Upstash (Option A) | Self-hosted (Option B) |
|---|---|---|
| **Coût 100 users** | $0 (free tier) | ~€5/mois (stockage) |
| **Coût 1 000 users** | ~$5-10/mois | ~€5-10/mois |
| **Setup** | 5 minutes | 30 minutes |
| **HA** | Automatique | Non (StatefulSet 1 replica) |
| **TLS** | Forcé | Non (cluster interne) |
| **Ops** | Aucun | Monitoring mémoire |
| **Latence** | ~5-10ms (Frankfurt) | <1ms (cluster interne) |
**Recommandation :**
- MVP **Upstash free tier** (zéro coût, zéro ops)
- 1 000+ users **Self-hosted dans k3s** (latence minimale, contrôle complet)