Guida allo Scaling della Piattaforma
Principi di Scaling
La piattaforma Impronto Enterprise e composta da 13 tipi di nodo Moleculer, ciascuno con caratteristiche di scaling diverse. La regola fondamentale e: non tutti i nodi si scalano allo stesso modo.
Matrice di Scaling per Tipo di Nodo
| Tipo Nodo | HPA | Repliche Min | Repliche Max | Note |
|---|---|---|---|---|
| gateway | Si (CPU) | 2 | 10 | Entry point, scala con il traffico HTTP |
| core | Si (CPU) | 2 | 8 | Ordini, prodotti, clienti |
| auth | Si (CPU) | 2 | 6 | Validazione JWT, sessioni |
| commerce | Si (CPU) | 2 | 8 | Pagamenti, fiscale |
| warehouse | Si (CPU) | 1 | 4 | Magazzino, movimentazione |
| media | Si (CPU) | 1 | 4 | Upload immagini, S3 proxy |
| reports | Si (CPU) | 1 | 4 | Generazione report pesanti |
| platform | Si (CPU) | 1 | 3 | Gestione tenant e reseller |
| finance | Si (CPU) | 1 | 3 | Fatturazione, abbonamenti |
| knowledge | Si (CPU) | 1 | 3 | Documentazione, AI chat |
| cash | Si (CPU) | 1 | 4 | Prima nota, sessioni cassa |
| scheduler | No | 1 | 1 | Singleton - cron job, mai scalare |
| simulator | No | 0 | 1 | Solo in ambiente di test |
Il nodo scheduler esegue cron job (archiviazione, ETL, alert). Scalare a piu di 1 replica causerebbe esecuzione duplicata di tutti i job schedulati. Utilizzare sempre replicas: 1 con strategy: Recreate.
Horizontal Pod Autoscaler (HPA)
Configurazione Attuale (CPU-based)
# k8s/hpa/gateway-hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: pos-gateway-hpa
namespace: pos-enterprise
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: pos-gateway
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 65 # Scala quando CPU media > 65%
behavior:
scaleUp:
stabilizationWindowSeconds: 60 # Attendi 1 min prima di scale-up
policies:
- type: Pods
value: 2
periodSeconds: 60 # Max 2 pod ogni 60s
scaleDown:
stabilizationWindowSeconds: 300 # Attendi 5 min prima di scale-down
policies:
- type: Pods
value: 1
periodSeconds: 120 # Max 1 pod ogni 2 min
# k8s/hpa/core-hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: pos-core-hpa
namespace: pos-enterprise
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: pos-core
minReplicas: 2
maxReplicas: 8
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
behavior:
scaleDown:
stabilizationWindowSeconds: 300
Applicazione e Verifica
# Applicare gli HPA
kubectl apply -f k8s/hpa/
# Verificare stato degli HPA
kubectl get hpa -n pos-enterprise
# Output tipico:
# NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
# pos-gateway-hpa Deployment/pos-gateway 42%/65% 2 10 3 5d
# pos-core-hpa Deployment/pos-core 55%/70% 2 8 2 5d
# Dettaglio di un HPA specifico
kubectl describe hpa pos-gateway-hpa -n pos-enterprise
Evoluzione: HPA basato su Metriche Prometheus (Futuro)
L'obiettivo futuro e scalare basandosi su metriche applicative (request queue depth, action latency):
# Esempio futuro con Prometheus Adapter
spec:
metrics:
- type: Pods
pods:
metric:
name: moleculer_action_queue_depth
target:
type: AverageValue
averageValue: 50 # Scala quando la coda media > 50
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
Requisiti per l'implementazione:
- Installare Prometheus Adapter
- Configurare le metriche custom da esporre all'HPA
- Testare il comportamento di scaling in staging
Scaling Verticale: Risorse per Nodo
Limiti di Risorse Raccomandati
# Profilo risorse per tipo di nodo
resources:
# gateway - leggero, I/O bound
gateway:
requests: { cpu: "200m", memory: "256Mi" }
limits: { cpu: "1000m", memory: "512Mi" }
# core - medio, CPU e memory per CRUD
core:
requests: { cpu: "300m", memory: "512Mi" }
limits: { cpu: "1500m", memory: "1Gi" }
# commerce - medio-alto, calcoli fiscali
commerce:
requests: { cpu: "300m", memory: "512Mi" }
limits: { cpu: "1500m", memory: "1Gi" }
# reports - pesante, generazione PDF
reports:
requests: { cpu: "500m", memory: "1Gi" }
limits: { cpu: "2000m", memory: "2Gi" }
# scheduler - singleton, esecuzione cron job
scheduler:
requests: { cpu: "200m", memory: "512Mi" }
limits: { cpu: "1000m", memory: "1Gi" }
# knowledge - AI embeddings e search
knowledge:
requests: { cpu: "300m", memory: "512Mi" }
limits: { cpu: "1500m", memory: "1.5Gi" }
# Verificare l'utilizzo effettivo vs limiti
kubectl top pods -n pos-enterprise --sort-by=cpu
kubectl top pods -n pos-enterprise --sort-by=memory
# Dettaglio per un pod specifico
kubectl describe pod -n pos-enterprise pos-core-xxxxx | grep -A5 "Limits\|Requests"
Impostare il NODE_OPTIONS --max-old-space-size al 75% del memory limit del container. Esempio: limit 1Gi -> --max-old-space-size=768.
Scaling MongoDB
Strategia per Cluster Pool
MongoDB Atlas utilizza un cluster condiviso. La strategia di scaling prevede la separazione in pool quando il numero di tenant cresce:
| Tenant Count | Strategia | Cluster |
|---|---|---|
| 1-500 | Singolo cluster M30 | pos-prod-1 |
| 500-2000 | Singolo cluster M40 | pos-prod-1 (upgrade) |
| 2000-4000 | 2 cluster M30, routing per hash | pos-prod-1, pos-prod-2 |
| 4000+ | N cluster, routing centralizzato | pos-prod-N |
Il routing tra cluster e gestito dal servizio platform che mantiene una mappa tenantId -> clusterId:
// Logica di routing (semplificata)
getClusterForTenant(tenantId) {
const tenantConfig = await this.broker.call("tenant-management.get", { id: tenantId });
return tenantConfig.clusterId || "pos-prod-1"; // Default al cluster primario
}
Scaling Verticale Atlas
# Upgrade tier via Atlas CLI (richiede downtime minimo, rolling restart)
atlas clusters update pos-production \
--tier M40 \
--diskSizeGB 100
# Aggiungere storage (zero downtime)
atlas clusters update pos-production \
--diskSizeGB 200
Scaling Redis Cloud
Redis Cloud scala automaticamente con il piano scelto. Monitorare:
# Utilizzo memoria Redis (alert a 80%)
pos_redis_memory_used_bytes / pos_redis_memory_max_bytes
# Connessioni attive
redis_connected_clients
# Operazioni al secondo
rate(redis_commands_processed_total[5m])
Se necessario, scalare il piano Redis Cloud dal portale o via API.
Aggiungere Nuovi Nodi al Cluster K8s
Quando il cluster non ha abbastanza risorse per ospitare nuovi pod:
# Verificare le risorse disponibili nel cluster
kubectl describe nodes | grep -A5 "Allocated resources"
# Verificare pod in stato Pending (risorse insufficienti)
kubectl get pods -n pos-enterprise --field-selector=status.phase=Pending
# Se su IBM Cloud Kubernetes Service:
ibmcloud ks worker-pool resize \
--cluster pos-production \
--worker-pool default \
--size-per-zone 5 # Numero di nodi per zona
# Verificare i nuovi nodi
kubectl get nodes -o wide
Node Affinity per Workload Pesanti
# I nodi reports e knowledge preferiscono worker con piu RAM
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: node-type
operator: In
values: ["high-memory"]
Monitoraggio Scaling
# Cronologia eventi HPA
kubectl describe hpa -n pos-enterprise pos-gateway-hpa | grep -A20 "Events"
# Verificare che il PDB (Pod Disruption Budget) sia rispettato
kubectl get pdb -n pos-enterprise
# Numero repliche attuali vs desiderate
kube_horizontalpodautoscaler_status_current_replicas{namespace="pos-enterprise"}
kube_horizontalpodautoscaler_status_desired_replicas{namespace="pos-enterprise"}
# Pod in stato Pending (cluster pieno)
kube_pod_status_phase{namespace="pos-enterprise", phase="Pending"}
Riferimenti Incrociati
- Ottimizzazione delle Prestazioni - Prima di scalare, ottimizzare
- Health Check e Probes - Readiness probe e interazione con HPA
- Manutenzione Database - Scaling database
- Sistema di Alerting - Alert per saturazione risorse