Contenido

Kubernetes: Observabilidad con Prometheus y Grafana

Actualizado en marzo 2026: Este artículo usa Prometheus 3.x, Grafana 11.x y el chart kube-prometheus-stack actualizado.

Pre-requisitos

Este post continúa la serie de Kubernetes. Necesitas:

  • Todo lo del primer capítulo: Docker (u OrbStack), kubectl y Kind con un cluster activo.
  • Familiaridad con Deployments y Services del segundo capítulo.
  • Helm instalado — lo usaremos para desplegar el stack de monitoreo.

Si no tienes Helm, instálalo rápido:

# macOS
brew install helm

# Windows (Chocolatey)
choco install kubernetes-helm

Introducción

En los capítulos anteriores aprendimos a desplegar apps y escalarlas automáticamente con el HPA. Pero hay una pregunta fundamental que no hemos respondido: ¿cómo sabes qué está pasando dentro de tu cluster?

Imagina que estás conduciendo un auto sin tablero — sin velocímetro, sin indicador de combustible, sin luces de advertencia. Técnicamente puedes manejar, pero estás a ciegas. Eso es exactamente lo que es operar un cluster de Kubernetes sin observabilidad.

Prometheus y Grafana son las herramientas que te dan ese tablero. Y en este capítulo vamos a montarlas en nuestro cluster de Kind paso a paso.

Prometheus y Grafana overview

Prometheus recolecta métricas, Grafana las visualiza — juntos te dan visibilidad total de tu cluster


¿Qué es Prometheus?

Prometheus es un sistema de monitoreo y alertas open source, originalmente creado en SoundCloud y ahora parte de la Cloud Native Computing Foundation (CNCF) — al igual que Kubernetes.

Piénsalo como un recolector de datos obsesivo: cada cierto tiempo (por defecto cada 15-30 segundos) va a tus aplicaciones, les pregunta “¿cómo estás?” y almacena las respuestas como series temporales.

Arquitectura de Prometheus

Prometheus usa un modelo pull: él va a buscar las métricas a tus aplicaciones

Características clave

  • Modelo pull: Prometheus va a buscar las métricas a tus apps (scraping), no espera a que se las envíen. Esto le da control total sobre qué recolecta y cuándo.
  • Base de datos de series temporales (TSDB): almacena datos como pares de timestamp + valor, optimizado para consultas temporales.
  • PromQL: un lenguaje de consulta propio para explorar y agregar métricas.
  • Alertas: define reglas y Prometheus te avisa cuando algo está mal.
  • Service discovery: se integra nativamente con Kubernetes para descubrir automáticamente qué scrapeear.
  • OTLP nativo: desde Prometheus 3.x, soporta ingestión de métricas vía OpenTelemetry Protocol directamente.

¿Qué tipo de métricas recolecta?

Prometheus trabaja con 4 tipos de métricas:

TipoPara qué sirveEjemplo
CounterValores que solo suben (acumulativos)Total de requests HTTP, errores totales
GaugeValores que suben y bajanTemperatura, uso de memoria, Pods activos
HistogramDistribución de valores en bucketsLatencia de requests (p50, p95, p99)
SummarySimilar a histogram pero calcula percentiles en el clienteLatencia con percentiles precalculados

¿Cómo exponen métricas las aplicaciones?

Tus apps exponen métricas en un endpoint HTTP (por convención /metrics) en formato texto plano:

# HELP http_requests_total Total number of HTTP requests
# TYPE http_requests_total counter
http_requests_total{method="GET", path="/api/users", status="200"} 1234
http_requests_total{method="POST", path="/api/users", status="201"} 56

# HELP http_request_duration_seconds Duration of HTTP requests
# TYPE http_request_duration_seconds histogram
http_request_duration_seconds_bucket{le="0.1"} 500
http_request_duration_seconds_bucket{le="0.5"} 900
http_request_duration_seconds_bucket{le="1.0"} 980
http_request_duration_seconds_bucket{le="+Inf"} 1000

Prometheus lee este endpoint periódicamente y almacena los datos. Si tu app no expone métricas nativamente, puedes usar exporters (como node-exporter para métricas del sistema operativo o kube-state-metrics para estado de objetos de Kubernetes).


¿Qué es Grafana?

Grafana es una plataforma de visualización y dashboards open source. Si Prometheus es el que recolecta los datos, Grafana es el que los convierte en gráficos bonitos y útiles.

Ejemplo de dashboard de Grafana

Grafana convierte métricas crudas en dashboards interactivos y accionables

Características clave

  • Multi-datasource: no solo Prometheus. Puede conectarse a Loki (logs), Tempo (traces), InfluxDB, Elasticsearch, CloudWatch, y muchos más.
  • Dashboards interactivos: gráficos de líneas, barras, gauges, tablas, heatmaps, y más — todo configurable sin código.
  • Alertas: Grafana tiene su propio sistema de alertas que puede complementar o reemplazar las de Prometheus.
  • Explore: modo de exploración ad-hoc para investigar métricas sin crear un dashboard.
  • Templating: variables en dashboards para filtrar por namespace, pod, nodo, etc.
  • Sharing: comparte dashboards con tu equipo o exporta como JSON.

¿Cuál es el rol de cada uno?

Esta es la clave para entender cómo se complementan:

ComponenteRolAnalogía
PrometheusRecolectar y almacenar métricasLa cámara de seguridad que graba todo
GrafanaVisualizar y explorar métricasLos monitores donde ves las grabaciones
AlertmanagerGestionar y enrutar alertasLa alarma que suena cuando algo está mal
kube-state-metricsExponer estado de objetos K8s como métricasEl inventario del cluster (cuántos pods, deployments, etc.)
node-exporterExponer métricas del sistema operativoEl chequeo médico de cada nodo (CPU, RAM, disco)

¿Cómo se nutren de métricas?

Entender el flujo de datos es fundamental. Así es como las métricas viajan desde tu app hasta un gráfico en Grafana:

Flujo de métricas

El viaje de una métrica: desde tu app hasta un dashboard de Grafana

El flujo completo

1. Tu App expone /metrics (o un exporter lo hace por ella)
         
2. Prometheus scrapea el endpoint cada N segundos
         
3. Prometheus almacena los datos en su TSDB local
         
4. Grafana consulta Prometheus vía PromQL
         
5. Grafana renderiza los datos en dashboards

¿Cómo sabe Prometheus qué scrapear en Kubernetes?

Con el Prometheus Operator (que viene incluido en el stack que instalaremos), usas CRDs para decirle a Prometheus qué monitorear:

  • ServiceMonitor: “scrapea los Pods detrás de este Service”.
  • PodMonitor: “scrapea estos Pods directamente” (sin necesidad de Service).
  • PrometheusRule: “evalúa estas reglas de alerta”.
# Ejemplo: ServiceMonitor para monitorear tu app
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: mi-app-monitor
  labels:
    release: kube-prometheus-stack  # Importante: debe matchear con el release del Helm chart
spec:
  selector:
    matchLabels:
      app: mi-app
  endpoints:
    - port: metrics
      interval: 30s
      path: /metrics

Esto le dice a Prometheus: “busca todos los Services con label app: mi-app, scrapea el puerto metrics cada 30 segundos en el path /metrics”.


Instalando el stack completo con Helm

La forma recomendada de instalar Prometheus + Grafana en Kubernetes es con el chart kube-prometheus-stack. Este chart incluye todo lo que necesitas en un solo paquete:

  • Prometheus Operator
  • Prometheus
  • Grafana
  • Alertmanager
  • kube-state-metrics
  • node-exporter
  • Dashboards y alertas pre-configurados

Paso 1: Agregar el repositorio de Helm

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

Paso 2: Crear el namespace

kubectl create namespace monitoring

Paso 3: Configurar valores para Kind

En Kind hay algunos componentes del control plane que no son accesibles desde los Pods. Crea un archivo prometheus-values.yaml con estos ajustes:

# prometheus-values.yaml

# Desactivar componentes que no son accesibles en Kind
kubeEtcd:
  enabled: false
kubeScheduler:
  enabled: false
kubeControllerManager:
  enabled: false
kubeProxy:
  enabled: false

# Configuración de Prometheus
prometheus:
  prometheusSpec:
    # Recursos ajustados para Kind (no estamos en producción)
    resources:
      requests:
        memory: 400Mi
        cpu: 200m
      limits:
        memory: 800Mi
        cpu: 500m
    # Retención de datos
    retention: 7d
    # Seleccionar todos los ServiceMonitors (sin filtrar por label)
    serviceMonitorSelectorNilUsesHelmValues: false
    podMonitorSelectorNilUsesHelmValues: false

# Configuración de Grafana
grafana:
  resources:
    requests:
      memory: 128Mi
      cpu: 100m
    limits:
      memory: 256Mi
      cpu: 200m
  # Password de admin (en producción usa un Secret)
  adminPassword: "admin123"

# Configuración de Alertmanager
alertmanager:
  alertmanagerSpec:
    resources:
      requests:
        memory: 64Mi
        cpu: 50m
      limits:
        memory: 128Mi
        cpu: 100m

¿Por qué desactivamos etcd, scheduler, controller-manager y proxy? En Kind, estos componentes corren dentro del contenedor del control plane y sus endpoints de métricas están bindeados a 127.0.0.1 — Prometheus no puede alcanzarlos desde un Pod. En un cluster gestionado (EKS, GKE, AKS) esto no es problema porque el proveedor expone estas métricas.

Paso 4: Instalar el chart

helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack \
  --namespace monitoring \
  --values prometheus-values.yaml

Esto tarda unos minutos. Verifica que todos los Pods estén corriendo:

kubectl get pods -n monitoring
NAME                                                        READY   STATUS    RESTARTS   AGE
alertmanager-kube-prometheus-stack-alertmanager-0            2/2     Running   0          2m
kube-prometheus-stack-grafana-7b9f5c4d5-x2k8j               3/3     Running   0          2m
kube-prometheus-stack-kube-state-metrics-6c4d7b9f8-abc12     1/1     Running   0          2m
kube-prometheus-stack-operator-5d8f7b6c4-def34               1/1     Running   0          2m
kube-prometheus-stack-prometheus-node-exporter-ghi56          1/1     Running   0          2m
prometheus-kube-prometheus-stack-prometheus-0                 2/2     Running   0          2m

Verifica los Services creados:

kubectl get svc -n monitoring
NAME                                              TYPE        CLUSTER-IP      PORT(S)    AGE
alertmanager-operated                             ClusterIP   None            9093/TCP   2m
kube-prometheus-stack-alertmanager                ClusterIP   10.96.10.1      9093/TCP   2m
kube-prometheus-stack-grafana                     ClusterIP   10.96.10.2      80/TCP     2m
kube-prometheus-stack-kube-state-metrics          ClusterIP   10.96.10.3      8080/TCP   2m
kube-prometheus-stack-operator                    ClusterIP   10.96.10.4      443/TCP    2m
kube-prometheus-stack-prometheus                  ClusterIP   10.96.10.5      9090/TCP   2m
kube-prometheus-stack-prometheus-node-exporter    ClusterIP   10.96.10.6      9100/TCP   2m
prometheus-operated                               ClusterIP   None            9090/TCP   2m
Pods del stack de monitoreo

Todos los componentes del stack corriendo en el namespace monitoring


Accediendo a Grafana

Con el stack instalado, accedamos a Grafana usando port-forward:

kubectl port-forward svc/kube-prometheus-stack-grafana 3000:80 -n monitoring

Abre tu navegador en http://localhost:3000 y entra con:

  • Usuario: admin
  • Password: admin123 (el que pusimos en el values)
Login de Grafana

Pantalla de login de Grafana — usa las credenciales configuradas en el Helm values

Dashboards que vienen incluidos

El chart instala más de 15 dashboards pre-configurados listos para usar. Los más útiles:

DashboardQué muestra
Kubernetes / Compute Resources / ClusterVista general del cluster: CPU, memoria y red totales
Kubernetes / Compute Resources / Namespace (Pods)Uso de recursos por namespace
Kubernetes / Compute Resources / PodDetalle de un Pod individual
Kubernetes / Compute Resources / WorkloadRecursos por Deployment/StatefulSet/DaemonSet
Kubernetes / KubeletSalud del kubelet y lifecycle de Pods
Kubernetes / API ServerRequest rates, latencias y errores del API Server
Kubernetes / CoreDNSQueries DNS, latencias y errores
Kubernetes / Networking / ClusterTráfico de red por namespace
Kubernetes / Persistent VolumesUso de almacenamiento persistente
Node Exporter / FullMétricas a nivel de sistema operativo por nodo
Prometheus / OverviewAuto-monitoreo de Prometheus

Para encontrarlos, ve a Dashboards (icono de cuadros en el menú lateral) y busca en la carpeta “General” o “Default”.

Dashboard de cluster en Grafana

Dashboard pre-configurado mostrando recursos del cluster: CPU, memoria y uso de red


Accediendo a Prometheus

También puedes acceder directamente a la UI de Prometheus para hacer queries con PromQL:

kubectl port-forward svc/kube-prometheus-stack-prometheus 9090:9090 -n monitoring

Abre http://localhost:9090 en tu navegador.

UI de Prometheus

La UI de Prometheus te permite ejecutar queries PromQL y explorar métricas directamente

Probando algunas queries PromQL

En la barra de consulta de Prometheus, prueba estas queries:

# Uso de CPU por Pod (en cores)
rate(container_cpu_usage_seconds_total{namespace="default"}[5m])

# Memoria usada por Pod (en bytes)
container_memory_working_set_bytes{namespace="default"}

# Total de Pods por namespace
count by (namespace) (kube_pod_info)

# Pods que no están Ready
kube_pod_status_ready{condition="false"}

# Requests HTTP al API Server (por segundo)
rate(apiserver_request_total[5m])

Tip: PromQL es un lenguaje poderoso. La función rate() calcula la tasa de cambio por segundo de un counter, y [5m] indica el rango de tiempo a considerar. Para una guía completa, revisa la documentación de PromQL.


Verificando los targets de Prometheus

Un target es cada endpoint que Prometheus scrapea. Para verificar que todo está siendo monitoreado:

En la UI de Prometheus, ve a Status → Targets (o accede directamente a http://localhost:9090/targets).

Targets de Prometheus

Todos los targets deben aparecer en estado UP (verde) — si alguno está DOWN, revisa la conectividad

Deberías ver targets como:

  • serviceMonitor/monitoring/kube-prometheus-stack-kubelet — UP
  • serviceMonitor/monitoring/kube-prometheus-stack-apiserver — UP
  • serviceMonitor/monitoring/kube-prometheus-stack-kube-state-metrics — UP
  • serviceMonitor/monitoring/kube-prometheus-stack-node-exporter — UP
  • serviceMonitor/monitoring/kube-prometheus-stack-prometheus — UP
  • serviceMonitor/monitoring/kube-prometheus-stack-grafana — UP

Si algún target está DOWN, revisa:

  1. ¿El Pod del exporter está corriendo? (kubectl get pods -n monitoring)
  2. ¿El Service tiene endpoints? (kubectl get endpoints -n monitoring)
  3. ¿Las labels del ServiceMonitor matchean con el Service?

Alertmanager: el sistema de alertas

El stack incluye Alertmanager, que gestiona las alertas que Prometheus genera. No es solo “disparar un email” — es un sistema sofisticado que:

  1. Agrupa alertas relacionadas para no bombardearte.
  2. Deduplica alertas repetidas.
  3. Enruta a diferentes canales según la severidad (Slack para warnings, PagerDuty para critical).
  4. Silencia alertas temporalmente (útil durante mantenimiento).

Accede a la UI del Alertmanager:

kubectl port-forward svc/kube-prometheus-stack-alertmanager 9093:9093 -n monitoring

Abre http://localhost:9093.

UI de Alertmanager

Alertmanager agrupa, deduplica y enruta alertas — aquí ves las alertas activas

Alertas que vienen pre-configuradas

El chart incluye decenas de alertas listas. Algunas de las más importantes:

AlertaQué detectaSeveridad
KubePodCrashLoopingUn Pod que se reinicia constantementewarning
KubePodNotReadyUn Pod que no pasa a Readywarning
KubeDeploymentReplicasMismatchUn Deployment con menos réplicas de las deseadaswarning
NodeNotReadyUn nodo que dejó de funcionarcritical
NodeMemoryHighUtilizationUn nodo con más de 90% de memoria usadawarning
PrometheusTargetDownUn target que dejó de responderwarning
WatchdogAlerta que siempre está activa (para verificar que el pipeline funciona)none

Para ver las reglas configuradas:

kubectl get prometheusrules -n monitoring

Monitoreando tu propia app

Hasta ahora vemos métricas del cluster. ¿Cómo agregamos métricas de tu app? Necesitas dos cosas:

1. Que tu app exponga métricas

Si tu app es en Node.js, Python, Go, Java o cualquier lenguaje, hay librerías de Prometheus que te facilitan esto. Por ejemplo, para un app genérica que expone /metrics:

# deployment con puerto de métricas
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mi-app
  labels:
    app: mi-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mi-app
  template:
    metadata:
      labels:
        app: mi-app
    spec:
      containers:
        - name: mi-app
          image: mi-app:latest
          ports:
            - name: http
              containerPort: 8080
            - name: metrics
              containerPort: 9090
# Service que expone ambos puertos
apiVersion: v1
kind: Service
metadata:
  name: mi-app-svc
  labels:
    app: mi-app
spec:
  selector:
    app: mi-app
  ports:
    - name: http
      port: 8080
      targetPort: 8080
    - name: metrics
      port: 9090
      targetPort: 9090

2. Crear un ServiceMonitor

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: mi-app-monitor
  namespace: monitoring
  labels:
    release: kube-prometheus-stack
spec:
  namespaceSelector:
    matchNames:
      - default
  selector:
    matchLabels:
      app: mi-app
  endpoints:
    - port: metrics
      interval: 15s
      path: /metrics
kubectl apply -f servicemonitor.yaml

Después de unos segundos, ve a los targets de Prometheus y deberías ver tu app listada. Sus métricas estarán disponibles en Grafana.

Importante: El label release: kube-prometheus-stack en el ServiceMonitor es clave. Debe matchear con el nombre del release de Helm. Sin este label, Prometheus no descubrirá tu ServiceMonitor.


Creando tu primer dashboard en Grafana

Los dashboards pre-configurados están geniales, pero eventualmente querrás crear los tuyos. Aquí va el proceso:

Paso 1: Crear un nuevo dashboard

En Grafana, ve a Dashboards → New → New Dashboard → Add visualization.

Paso 2: Seleccionar datasource

Selecciona Prometheus como data source (ya está configurado automáticamente).

Paso 3: Escribir la query

Por ejemplo, para ver el uso de CPU de tu app:

rate(container_cpu_usage_seconds_total{namespace="default", pod=~"mi-app.*"}[5m])

Paso 4: Personalizar la visualización

  • Elige el tipo de gráfico (Time series, Gauge, Stat, etc.).
  • Configura el título, leyendas, unidades (CPU en cores, memoria en bytes, etc.).
  • Agrega variables para poder filtrar por namespace o pod dinámicamente.

Paso 5: Guardar

Dale un nombre y guarda. También puedes exportar el dashboard como JSON para versionarlo en Git.

Dashboard custom en Grafana

Crea dashboards personalizados para monitorear exactamente lo que tu equipo necesita

Tip: Grafana tiene un repositorio de dashboards comunitarios con miles de dashboards listos para importar. Busca por “kubernetes” y encontrarás opciones excelentes.


Arquitectura completa del stack

Para que tengas la foto completa de cómo encaja todo:

Arquitectura completa del stack de observabilidad

Arquitectura del stack: exporters → Prometheus → Grafana + Alertmanager → Notificaciones

┌──────────────────────────────────────────────────────────────────┐
                    Kubernetes Cluster                             
                                                                  
  ┌─────────────┐   ┌──────────────┐   ┌─────────────────────┐  
   Tu App          kube-state-      node-exporter         
   /metrics        metrics          (métricas del nodo)   
  └──────┬──────┘   └──────┬───────┘   └──────────┬──────────┘  
                                                               
         └────────┬────────┴───────────────────────┘              
                                                                 
         ┌────────────────┐                                       
            Prometheus   │←── PrometheusRules (alertas)          
            (scraping +                                         
             TSDB)                                              
         └───┬─────┬──────┘                                       
                                                                
                                                                
     ┌───────────┐ ┌──────────────┐                               
       Grafana    Alertmanager │──→ Slack, PagerDuty, Email   
     (dashboards   (routing)                                  
     └───────────┘ └──────────────┘                               
└──────────────────────────────────────────────────────────────────┘

Comandos útiles del día a día

# Ver todos los recursos del stack
kubectl get all -n monitoring

# Ver los ServiceMonitors configurados
kubectl get servicemonitors -n monitoring

# Ver las reglas de alerta
kubectl get prometheusrules -n monitoring

# Ver la configuración de Prometheus
kubectl get prometheus -n monitoring -o yaml

# Port-forward a Grafana
kubectl port-forward svc/kube-prometheus-stack-grafana 3000:80 -n monitoring

# Port-forward a Prometheus
kubectl port-forward svc/kube-prometheus-stack-prometheus 9090:9090 -n monitoring

# Port-forward a Alertmanager
kubectl port-forward svc/kube-prometheus-stack-alertmanager 9093:9093 -n monitoring

# Ver los logs de Prometheus
kubectl logs -n monitoring prometheus-kube-prometheus-stack-prometheus-0 -c prometheus

# Actualizar el stack (después de modificar values)
helm upgrade kube-prometheus-stack prometheus-community/kube-prometheus-stack \
  --namespace monitoring \
  --values prometheus-values.yaml

Referencias oficiales


Resumen

Hoy montamos el stack completo de observabilidad en nuestro cluster:

  • Prometheus recolecta métricas con un modelo pull, scrapeando endpoints /metrics cada N segundos.
  • Grafana visualiza esas métricas en dashboards interactivos y pre-configurados.
  • Alertmanager gestiona alertas: las agrupa, deduplica y enruta a tus canales de notificación.
  • kube-state-metrics expone el estado de objetos Kubernetes como métricas.
  • node-exporter expone métricas a nivel de sistema operativo de cada nodo.
  • Todo se instala con un solo chart de Helm: kube-prometheus-stack.
  • Usamos ServiceMonitors para decirle a Prometheus qué scrapear.
  • Las métricas viajan: App → Prometheus (scraping) → Grafana (visualización).

Con Prometheus y Grafana tienes visibilidad total de tu cluster. Ya no estás a ciegas — ahora puedes ver exactamente qué está pasando, cuándo y por qué.

En el próximo capítulo pondremos todo a prueba: desplegaremos dos apps reales (Python y Java) con métricas, HPA, y veremos cómo se comportan bajo carga en Grafana. Teoría + práctica completa.


¿Te gustó este artículo? Compártelo con alguien que esté montando su stack de observabilidad. Y si tienes dudas, ¡déjame un comentario!