Skip to main content

Runbook: Pod Not Ready

Severita: Warning Alert Prometheus: PodNotReady

Descrizione

Questo alert si attiva quando un pod nel namespace pos-enterprise rimane nello stato NotReady per piu di 5 minuti. Il pod e in esecuzione ma non supera la readiness probe, quindi Kubernetes lo rimuove dagli endpoint del Service e non riceve traffico.

Ogni nodo Moleculer della piattaforma espone un health server sulla porta 3001 che verifica:

  • Stato del transporter NATS (connesso/disconnesso)
  • Stato del cacher Redis (connesso/disconnesso)
  • Stato del service broker (started/stopped)

Regola Prometheus:

kube_pod_status_ready{namespace="pos-enterprise", condition="false"} == 1

con for: 5m per evitare falsi positivi durante i deploy.

Impatto

  • Capacita ridotta: il pod non riceve traffico ma consuma risorse del cluster.
  • Carico sbilanciato: le repliche sane ricevono piu traffico del previsto.
  • Scaling inefficace: l'HPA potrebbe non scalare correttamente se conta i pod NotReady.
  • Se tutti i pod di un deployment sono NotReady: equivale a un outage del servizio.

Diagnosi

1. Identificare i pod NotReady

kubectl get pods -n pos-enterprise | grep -v "Running.*1/1"

# Dettaglio delle condizioni
kubectl get pods -n pos-enterprise -o json | jq -r '
.items[] |
select(.status.conditions[]? | select(.type == "Ready" and .status == "False")) |
"\(.metadata.name) - Phase: \(.status.phase)"
'

2. Verificare il motivo del NotReady

kubectl describe pod <POD_NAME> -n pos-enterprise

Cercare nella sezione Conditions e Events:

  • Readiness probe failed: connection refused → il servizio non e ancora avviato
  • Readiness probe failed: HTTP probe failed with statuscode: 503 → dipendenza non disponibile
  • Readiness probe failed: dial tcp ... connect: connection refused → porta 3001 non in ascolto

3. Testare l'health check manualmente

# Port-forward alla porta health del pod
kubectl port-forward <POD_NAME> -n pos-enterprise 3001:3001

# Testare l'endpoint health
curl -v http://localhost:3001/health

# Risposta attesa (200 OK):
# {
# "status": "ok",
# "transporter": { "connected": true },
# "cacher": { "connected": true },
# "services": 15,
# "uptime": 3600
# }

# Risposta problematica (503):
# {
# "status": "error",
# "transporter": { "connected": false },
# "cacher": { "connected": true }
# }

4. Verificare la connessione NATS (transporter)

kubectl logs <POD_NAME> -n pos-enterprise --tail=50 | grep -i "nats\|transporter\|connect"

# Se NATS e disconnesso, vedere runbook NATS Down

5. Verificare la connessione Redis (cacher)

kubectl logs <POD_NAME> -n pos-enterprise --tail=50 | grep -i "redis\|cacher\|connect"

# Test diretto
kubectl exec <POD_NAME> -n pos-enterprise -- \
node -e "
const Redis = require('ioredis');
const r = new Redis(process.env.REDIS_URL);
r.ping().then(v => { console.log('Redis:', v); process.exit(0); })
.catch(e => { console.error('Redis error:', e.message); process.exit(1); });
"

6. Verificare la configurazione della probe

kubectl get pod <POD_NAME> -n pos-enterprise -o jsonpath='{.spec.containers[0].readinessProbe}' | jq .

Output tipico:

{
"httpGet": {
"path": "/health",
"port": 3001,
"scheme": "HTTP"
},
"initialDelaySeconds": 10,
"periodSeconds": 10,
"timeoutSeconds": 5,
"successThreshold": 1,
"failureThreshold": 3
}

7. Verificare se e un problema di avvio lento

# Tempo di avvio del broker Moleculer
kubectl logs <POD_NAME> -n pos-enterprise | grep -i "broker started\|service started"

# Se il servizio carica molti dati all'avvio (es. cache warmup),
# l'initialDelaySeconds potrebbe essere insufficiente

Risoluzione

Causa: Transporter NATS disconnesso

# Verificare prima lo stato di NATS (vedi runbook nats-down.md)
# Se NATS e ok ma il pod non si connette, riavviare il pod
kubectl delete pod <POD_NAME> -n pos-enterprise

Causa: Cacher Redis non raggiungibile

# Verificare lo stato di Redis Cloud
kubectl run redis-test --rm -it --image=redis:7-alpine -n pos-enterprise -- \
redis-cli -u "$REDIS_URL" ping

# Se Redis e down, i servizi possono funzionare senza cache
# Disabilitare temporaneamente il cacher
kubectl set env deployment/<DEPLOY_NAME> -n pos-enterprise CACHER=""

# ATTENZIONE: senza cacher Redis, le performance degradano significativamente

Causa: Startup lento (initialDelaySeconds insufficiente)

# Aumentare il delay iniziale della readiness probe
kubectl patch deployment <DEPLOY_NAME> -n pos-enterprise --type='json' -p='[
{"op": "replace",
"path": "/spec/template/spec/containers/0/readinessProbe/initialDelaySeconds",
"value": 30},
{"op": "replace",
"path": "/spec/template/spec/containers/0/readinessProbe/failureThreshold",
"value": 6}
]'

Causa: Startup probe mancante

Per servizi con avvio lento, aggiungere una startup probe separata:

kubectl patch deployment <DEPLOY_NAME> -n pos-enterprise --type='json' -p='[
{"op": "add",
"path": "/spec/template/spec/containers/0/startupProbe",
"value": {
"httpGet": {"path": "/health", "port": 3001},
"periodSeconds": 5,
"failureThreshold": 30
}}
]'

Questo da al servizio fino a 150 secondi (5s x 30) per avviarsi, senza influire sulla readiness probe post-startup.

Causa: Risoluzione DNS lenta

# Verificare la risoluzione DNS dal pod
kubectl exec <POD_NAME> -n pos-enterprise -- nslookup nats.sellogic.cloud

# Se la risoluzione e lenta, verificare il CoreDNS
kubectl get pods -n kube-system -l k8s-app=kube-dns
kubectl logs -n kube-system -l k8s-app=kube-dns --tail=20

Riavvio selettivo

# Riavviare solo i pod NotReady di un deployment
kubectl get pods -n pos-enterprise -l app=<APP_LABEL> | \
grep -v "1/1.*Running" | awk 'NR>1{print $1}' | \
xargs -I {} kubectl delete pod {} -n pos-enterprise

Prevenzione

  • Startup probe su tutti i deployment: separare la verifica di avvio dalla readiness continua.
  • Dipendenze resilienti: il health check non dovrebbe fallire per dipendenze non critiche (es. cache miss non deve rendere il pod NotReady).
  • Timeout adeguati: timeoutSeconds della probe deve essere > tempo massimo di risposta dell'health endpoint.
  • Monitorare il tempo di avvio: tracciare la metrica moleculer_broker_started_seconds per ogni nodo.
# Configurazione probe raccomandata
readinessProbe:
httpGet:
path: /health
port: 3001
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
startupProbe:
httpGet:
path: /health
port: 3001
periodSeconds: 5
failureThreshold: 30
livenessProbe:
httpGet:
path: /health
port: 3001
initialDelaySeconds: 30
periodSeconds: 15
timeoutSeconds: 5
failureThreshold: 5

Escalation

LivelloCondizioneContatto
L1 - OpsSingolo pod NotReady, altre repliche saneMonitorare 10 min, poi riavviare
L1 - OpsPod NotReady post-deployVerificare probe config, rollback se necessario
L2 - OpsTutti i pod di un deployment NotReadyDiagnosi dipendenze (NATS, Redis)
L3 - DevNotReady causato da bug nell'health checkTeam Dev

Tempo massimo di risposta: 15 minuti. Se tutti i pod di un deployment critico (api-gateway, orders-node) sono NotReady, trattare come Critical.

Questa pagina ti è stata utile?