GUIDESaturación de recursos: CPU, memoria, disco y red
Para métricas de saturación necesitas:
node_exporter — CPU, memoria, disco (node_*_*)kube-state-metrics — limites de recursos (kube_pod_resource_*)kubelet cAdvisor — memory/CPU de containersiostat para disco I/O (si no usas cAdvisor)Todas las queries de node_cpu_seconds_total, node_memory_* y node_filesystem_* están filtradas por la variable de dashboard $job_node (por defecto: node-exporter). Si su node_exporter es recolectado bajo un nombre de job diferente, actualice la variable en Configuración del Dashboard → Variables.
Las métricas de saturación reflejan su carga de trabajo real. En un homelab típico con uso liviano, es completamente normal ver la CPU en 2–10%, la memoria en 30–50% y el I/O de disco cercano a cero. Los valores bajos no son señal de mala configuración — indican que su infraestructura tiene capacidad disponible. Los umbrales están calibrados para cargas de trabajo de producción; no dude en reducir los límites de advertencia/crítico para adaptarlos a la línea base de su homelab.
┌────────────────────────────────────────┐ │ SATURATION — RESOURCE EXHAUSTION │ ├────────────────────────────────────────┤ │ CPU % │ Memory % │ Disk % │ Net │ │ (gauge) │ (gauge) │ (gauge) │(gau)│ ├────────────────────────────────────────┤ │ CPU + Memory Time Series [12 cols] │ │ (evolución con thresholds) │ ├────────────────────────────────────────┤ │ Disk I/O [6 cols] │ Disk Free [6 col]│ │ (read/write ops) │ (por mount) │ ├────────────────────────────────────────┤ │ Resource by Node [12 cols] │ │ (tabla: CPU, mem, disco por host) │ ├────────────────────────────────────────┤ │ Requests vs Limits [12 cols] │ │ (desglose de demanda actual vs límite)│ └────────────────────────────────────────┘
Porcentaje de CPU en uso (excluyendo idle).
Query default (excludes idle):100 - (avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
Por instancia específica:
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle",instance="server1:9100"}[5m])) * 100)
Excluir modos específicos (excluir iowait, steal):
100 - (avg(rate(node_cpu_seconds_total{mode=~"idle|iowait"}[5m])) * 100)
Thresholds recomendados: 70% yellow, 85% red
Porcentaje de memoria en uso.
Usando available (recomendado):
100 * (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes))
Usando free (menos preciso):
100 * (1 - (node_memory_MemFree_bytes / node_memory_MemTotal_bytes))
Por nodo:
100 * (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) by (instance)
Thresholds: 80% yellow, 90% red (dejar buffer para caché)
Porcentaje de disco utilizado (por mountpoint).
Default (root partition):
100 * (node_filesystem_used_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"})
Excluir tmpfs y sistemas virtuales:
100 * (node_filesystem_used_bytes{fstype!~"tmpfs|devtmpfs|fuse.*",mountpoint!~"/sys.*|/proc.*"}
/ node_filesystem_size_bytes{fstype!~"tmpfs|devtmpfs|fuse.*"}) by (device)
Por mountpoint:
sum by (mountpoint) (100 * (node_filesystem_used_bytes / node_filesystem_size_bytes))
Thresholds: 80% yellow, 90% red
Porcentaje de ancho de banda saturado.
Usando interface speed (si disponible):
100 * ((rate(node_network_transmit_bytes_total[5m]) * 8) / (node_network_speed_bytes * 1000000000))
Sin speed (normalizar por histórico):
rate(node_network_transmit_bytes_total[5m]) / avg_over_time(rate(node_network_transmit_bytes_total[5m])[1h:1m])
Por dirección (in/out):
sum by (device) (rate(node_network_receive_bytes_total[5m]))
Gráfico de línea con evolución de ambos recursos.
Query CPU:
100 - (avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
Query Memory:
100 * (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes))
Per-node breakdown:
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
Añade líneas de threshold: En panel → Alerts → 70% (warning), 85% (critical)
Operaciones de lectura/escritura por segundo.
Read ops/sec:
rate(node_disk_reads_completed_total{device="sda"}[5m])
Write ops/sec:
rate(node_disk_writes_completed_total{device="sda"}[5m])
Cambiar dispositivo: sda → nvme0n1 (NVMe), vda (virtual), etc
Utilization %:
rate(node_disk_io_time_seconds_total{device="sda"}[5m]) * 100
Nota: > 30% I/O wait indica contención de disco
Espacio disponible por punto de montaje.
Query:node_filesystem_avail_bytes{fstype!~"tmpfs|devtmpfs"} / 1024 / 1024 / 1024
Mostrar por mountpoint:
sum by (mountpoint) (node_filesystem_avail_bytes) / 1024 / 1024 / 1024
Porcentaje disponible:
100 * (node_filesystem_avail_bytes / node_filesystem_size_bytes) by (mountpoint)
Tabla dinámica con CPU, memoria y disco por nodo.
Estructura JSON para tabla multi-métrica:
sum by (instance) (100 - (rate(node_cpu_seconds_total{mode="idle"}[5m]) * 100)) // CPU
sum by (instance) (100 * (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) // Memory
sum by (instance, device) (100 * node_filesystem_used_bytes / node_filesystem_size_bytes) // Disk
Filtrar nodos de producción:
sum by (instance) (...) {instance=~"prod.*"}
Comparativa de recursos pedidos vs límites en K8s.
CPU requests:
sum by (namespace, pod) (kube_pod_container_resource_requests_cpu_cores)
CPU limits:
sum by (namespace, pod) (kube_pod_container_resource_limits_cpu_cores)
Memory (en bytes):
sum by (namespace, pod) (kube_pod_container_resource_limits_memory_bytes) / 1024 / 1024
Filtrar por namespace:
sum by (namespace, pod) (...) {namespace!~"kube-system|kube-.*"}
| Tema | OK (<70%) | Warning (70-85%) | Critical (>85%) |
|---|---|---|---|
| GREEN | #33FF00 |
#FFCC00 | #FF4444 |
| AMBER | #FFB000 |
#FF8C00 | #FF4500 |
| BLUE | #00BFFF |
#FFD700 | #FF1493 |
Gauge thresholds en JSON:
"thresholds": {
"mode": "absolute",
"steps": [
{ "color": "green", "value": null },
{ "color": "yellow", "value": 70 },
{ "color": "red", "value": 85 }
]
}
| Tipo | Stat Card Width | Graph Height | Table Height |
|---|---|---|---|
| Mobile | 6 (stack vertical) | 10 | 12 |
| Tablet 10.9" | 12 (full width) | 12 | 14 |
| iPad Pro 12.9" | 12 (full width) | 14 | 16 |
| Desktop 1920×1080 | 6 (4 cols) | 10 | 12 |
rate(node_cpu_seconds_total{mode!="idle"}[5m]) >
avg_over_time(rate(node_cpu_seconds_total{mode!="idle"}[5m])[1h:5m]) * 1.5
Alerta si CPU se eleva 50% por encima del promedio de 1h.
(node_memory_SwapFree_bytes / node_memory_SwapTotal_bytes) < 0.3
Alerta si se usa > 70% de swap (indicador de memory pressure severa).
predict_linear(node_filesystem_avail_bytes{mountpoint="/"}[1h], 86400)
Predice espacio disponible en 24h. Si < 10GB, alerta proactivamente.
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) * 1000
+ (node_load1 / count(node_cpu_seconds_total{mode="idle"}) * 100)
Suaviza latencia por factor de load (muestra impacto de saturación).