Runbook: Utilizzo Memoria Elevato
Severita: Warning
Alert Prometheus: HighMemoryUsage
Descrizione
Questo alert si attiva quando un container nel namespace pos-enterprise utilizza piu dell'80% della memoria allocata come resources.limits.memory. E un segnale proattivo: se il consumo continua a crescere, il container verra terminato con OOMKill.
Regola Prometheus:
(container_memory_working_set_bytes{namespace="pos-enterprise", container!=""}
/ on(pod, container) kube_pod_container_resource_limits{namespace="pos-enterprise", resource="memory"})
> 0.8
Impatto
- Rischio OOM imminente: se la memoria raggiunge il 100% del limite, il kernel termina il processo.
- Degradazione prestazioni: il garbage collector di Node.js diventa aggressivo, causando pause frequenti e latenza elevata.
- Swap thrashing: se il nodo K8s ha swap abilitato (sconsigliato), il sistema diventa estremamente lento.
Diagnosi
1. Identificare i pod con memoria alta
# Top pod per memoria
kubectl top pods -n pos-enterprise --sort-by=memory
# Pod sopra l'80% del limite
kubectl get pods -n pos-enterprise -o json | jq -r '
.items[] |
.metadata.name as $name |
.spec.containers[0].resources.limits.memory as $limit |
"\($name) - Limit: \($limit)"
'
2. Analisi storica in Grafana
Dashboard: https://grafana.sellogic.cloud/d/pos-memory
# Trend memoria ultimi 7 giorni per deployment
avg by (pod) (
container_memory_working_set_bytes{namespace="pos-enterprise", container="moleculer"}
) / 1024 / 1024
# Velocita di crescita (MB/ora) - utile per identificare memory leak
deriv(container_memory_working_set_bytes{namespace="pos-enterprise", container="moleculer"}[1h]) / 1024 / 1024 * 3600
# Confronto tra repliche dello stesso deployment
container_memory_working_set_bytes{namespace="pos-enterprise", pod=~"orders-node.*"}
3. Profiling memoria del processo Node.js
# Statistiche V8 heap via endpoint Moleculer interno
kubectl port-forward <POD_NAME> -n pos-enterprise 3001:3001
curl http://localhost:3001/api/~node/health | jq '.client.mem'
# Risposta: { rss, heapUsed, heapTotal, external, arrayBuffers }
4. Verificare la cache locale
I servizi Moleculer possono accumulare cache locale se Redis non e configurato correttamente:
# Verificare la configurazione del cacher
kubectl exec <POD_NAME> -n pos-enterprise -- \
node -e "const cfg = require('./moleculer.config'); console.log(JSON.stringify(cfg.cacher, null, 2))"
5. Controllare il numero di connessioni
# Connessioni TCP aperte dal processo
kubectl exec <POD_NAME> -n pos-enterprise -- \
sh -c "cat /proc/1/net/tcp | wc -l"
# Socket attivi
kubectl exec <POD_NAME> -n pos-enterprise -- \
sh -c "ls /proc/1/fd | wc -l"
6. Identificare servizi memory-intensive
Profilo tipico di consumo memoria per tipo di nodo:
| Nodo | Baseline | Sotto carico | Sospetto leak se |
|---|---|---|---|
| api-gateway | 120-180 MB | 200-350 MB | > 400 MB stabile |
| orders-node | 100-150 MB | 180-300 MB | > 350 MB stabile |
| products-node | 80-120 MB | 120-200 MB | > 250 MB stabile |
| knowledge-node | 200-300 MB | 300-500 MB | > 600 MB stabile |
| warehouse-node | 100-160 MB | 180-300 MB | > 400 MB stabile |
Risoluzione
Azione immediata: aumentare il limite
Se il pod e critico e il nodo ha risorse disponibili:
# Verificare risorse disponibili sul nodo
kubectl top nodes
# Patch del limite (esempio: da 512Mi a 768Mi)
kubectl patch deployment <DEPLOY_NAME> -n pos-enterprise --type='json' -p='[
{"op": "replace", "path": "/spec/template/spec/containers/0/resources/limits/memory", "value": "768Mi"}
]'
Ottimizzazione: tuning GC Node.js
# Impostare il limite heap V8 al 75% del container limit
# Per un container con 512Mi di limit:
kubectl set env deployment/<DEPLOY_NAME> -n pos-enterprise \
NODE_OPTIONS="--max-old-space-size=384"
Ottimizzazione: pulizia cache Redis
# Verificare la dimensione della cache
kubectl run redis-cli --rm -it --image=redis:7-alpine -n pos-enterprise -- \
redis-cli -u "redis://:<password>@redis-xxxxx.cloud.redislabs.com:16379" info memory
# Pulire cache di un servizio specifico
kubectl run redis-cli --rm -it --image=redis:7-alpine -n pos-enterprise -- \
redis-cli -u "redis://:<password>@redis-xxxxx.cloud.redislabs.com:16379" \
--scan --pattern "MOL-pos-enterprise-orders.*" | xargs -L 100 redis-cli DEL
Ottimizzazione: ridurre il pool di connessioni MongoDB
# Verificare e ridurre maxPoolSize nel connection string
# Da: mongodb+srv://...?maxPoolSize=100
# A: mongodb+srv://...?maxPoolSize=20
kubectl edit secret pos-enterprise-secrets -n pos-enterprise
Investigazione memory leak
Se la memoria cresce linearmente nel tempo:
# Abilitare heap snapshot periodici (solo staging)
kubectl set env deployment/<DEPLOY_NAME> -n pos-enterprise \
NODE_OPTIONS="--max-old-space-size=384 --heap-prof --heap-prof-interval=600000"
# Dopo un periodo di osservazione, copiare i profili
kubectl cp pos-enterprise/<POD_NAME>:/app/Heap.*.heapprofile ./heap-profiles/
# Analizzare con Chrome DevTools → Memory → Load Profile
Prevenzione
- Alert a soglie multiple: 70% (info), 80% (warning), 90% (critical).
- Dashboard team: pannello dedicato in Grafana con trend di memoria per ogni deployment.
- Review periodico dei limiti: ogni mese, confrontare l'uso reale con i limiti configurati.
- Horizontal scaling: per servizi stateless, preferire piu repliche piccole a poche grandi.
- Load testing mensile: simulare il carico di punta per validare i limiti in condizioni reali.
# Alert multi-soglia
groups:
- name: memory-alerts
rules:
- alert: HighMemoryWarning
expr: container_memory_working_set_bytes / on(pod,container) kube_pod_container_resource_limits > 0.8
for: 5m
labels:
severity: warning
- alert: HighMemoryCritical
expr: container_memory_working_set_bytes / on(pod,container) kube_pod_container_resource_limits > 0.9
for: 2m
labels:
severity: critical
Escalation
| Livello | Condizione | Contatto |
|---|---|---|
| L1 - Ops | Singolo pod > 80%, stabile | Monitorare, nessuna azione urgente |
| L1 - Ops | Trend in crescita costante | Aumentare limite, notificare Dev |
| L2 - Dev | Sospetto memory leak | Team Dev - profiling e fix |
| L3 - Infra | Multipli deployment > 80% | DevOps Lead - scaling cluster |
Tempo massimo di risposta: 30 minuti. Monitorare per 15 minuti prima di intervenire per escludere picchi temporanei.
Questa pagina ti è stata utile?