El problema de observabilidad en Kubernetes no es la falta de herramientas. Es el exceso de datos sin señal. La mayoría de equipos que llegan a nosotros con incidentes prolongados tienen Prometheus y Grafana en marcha. Tienen dashboards. Tienen alertas. Y aun así, cuando hay un problema real, tardan horas en localizar la causa porque el dashboard que necesitan no existe todavía o porque las alertas llevan meses disparando falsos positivos que nadie se toma en serio.
El efecto es predecible: los ingenieros aprenden a ignorar las alertas, el on-call se convierte en un proceso de investigación manual desde cero, y el tiempo medio de resolución sube hasta niveles que tienen un coste directo en ingresos o en reputación. Tener telemetría no es lo mismo que tener observabilidad. Esta guía cubre la diferencia, con decisiones concretas sobre qué medir, cómo estructurarlo y qué stack funciona en entornos que ya tienen presión real.
Cuándo tener métricas no es lo mismo que tener observabilidad
La distinción importa en producción. Recoger datos es el paso cero. Observabilidad es la capacidad de responder preguntas sobre el comportamiento del sistema sin necesidad de desplegar código nuevo para diagnosticar. Si cada vez que hay un incidente el equipo necesita SSH a un nodo, añadir un log temporal o correlacionar manualmente tres herramientas distintas, el sistema tiene monitorización pero no observabilidad.
El primer fallo operativo que agrava esta situación es la fatiga de alertas. Cuando el sistema genera más alertas que las que el equipo puede procesar, la respuesta humana natural es dejar de reaccionar. Las alertas dejan de ser señales y se convierten en ruido. El resultado es que cuando ocurre algo que requiere atención inmediata, el equipo no tiene el reflejo entrenado de actuar. La alerta llega, se revisa con escepticismo, y el tiempo de respuesta se dilata.
La raíz del problema suele estar en cómo se definen los umbrales. Un umbral arbitrario, como alertar cuando el CPU supera el 80%, no refleja el impacto en el usuario. El CPU puede estar al 90% sin que nadie lo note, o puede estar al 40% mientras la latencia se dispara porque el cuello de botella es otro. Alertar sobre métricas de infraestructura sin conectarlas con experiencia de usuario genera ruido. Y el ruido tiene un coste: degrada la capacidad del equipo de detectar señales reales.
Los SLOs, Service Level Objectives, cambian el modelo operativo. En lugar de preguntar "está el sistema sano", preguntan "está el sistema dando la experiencia que prometimos a los usuarios". La diferencia parece semántica pero tiene consecuencias prácticas. Un SLO define un objetivo medible sobre un periodo de tiempo. Un error budget es lo que queda entre el nivel actual y el máximo de degradación aceptable. Cuando el error budget se consume más rápido de lo esperado, hay un burn rate alto que requiere atención. Cuando hay margen, el equipo puede desplegar con más confianza.
Este modelo no solo mejora la detección. Cambia las conversaciones sobre riesgo entre ingeniería y negocio. El error budget convierte "queremos desplegar esta semana" en una decisión con datos: cuánto budget queda, a qué ritmo se consume, si el despliegue propuesto cabe o no en la ventana disponible.
Métricas en Kubernetes: qué medir y por qué
El framework de los cuatro golden signals, desarrollado por el equipo de SRE de Google, sigue siendo la mejor guía para priorizar qué medir en sistemas distribuidos. No porque sea exhaustivo, sino porque fuerza a conectar la métrica con el impacto en el usuario.
Latencia mide el tiempo que tarda el sistema en responder. La distinción crítica es medir la latencia de las peticiones fallidas por separado, porque incluirlas en el percentil general puede ocultar problemas. En Kubernetes, la latencia de un workload específico se obtiene a través de métricas de la aplicación o de un proxy como Envoy, no del propio cluster.
Tráfico mide el volumen de demanda sobre el sistema. En servicios HTTP, son peticiones por segundo. En streaming, mensajes procesados. En batch, registros por intervalo. Esta métrica es el denominador para calcular tasas de error y es la referencia para entender si un cambio de latencia está correlacionado con un cambio de carga.
Errores miden la tasa de peticiones que fallan, ya sea por códigos HTTP 5xx, errores de negocio explícitos, o timeouts. La tasa de error es el indicador más directo de impacto en el usuario. Un aumento de la tasa de error sin cambio de tráfico es siempre una señal que requiere atención inmediata.
Saturación mide qué tan cerca está el sistema de su límite. CPU, memoria, conexiones de base de datos, espacio en disco: cualquier recurso que, cuando se agota, degrada el servicio. La saturación es el único golden signal que mide el estado del sistema, no el impacto en el usuario. Por eso es útil como señal de predicción, no como señal de alerta primaria.
En Kubernetes, las fuentes de estas métricas son específicas por capa:
| Signal | Fuente principal | Métrica Prometheus | Condición de alerta |
|---|---|---|---|
| Latencia | Aplicación / Envoy | http_request_duration_seconds (p99) | p99 > SLO target durante 5m |
| Tráfico | Aplicación / kube-state-metrics | http_requests_total | Caída brusca vs baseline (anomalía) |
| Errores | Aplicación / Ingress | http_requests_total{status=~"5.."} | Tasa de error > error budget burn rate |
| Saturación CPU | cAdvisor | container_cpu_usage_seconds_total | Throttling > 25% en ventana de 10m |
| Saturación memoria | cAdvisor | container_memory_working_set_bytes | Working set > 90% del limit |
| Estado de pods | kube-state-metrics | kube_pod_status_phase | Pods en estado Failed o Pending > 5m |
| Saturación nodo | node-exporter | node_filesystem_avail_bytes | Disco disponible < 15% |
| Réplicas disponibles | kube-state-metrics | kube_deployment_status_replicas_available | Disponibles < deseadas durante 3m |
kube-state-metrics expone el estado de los objetos de la API de Kubernetes: deployments, pods, replicasets, jobs. No mide consumo de recursos. Mide estado declarativo contra estado real. Es la fuente correcta para alertar sobre pods crashlooping, deployments atascados o jobs fallidos.
cAdvisor está embebido en el kubelet y expone métricas de consumo de recursos por contenedor. Es la fuente para CPU, memoria, red y disco a nivel de workload.
node-exporter expone métricas del sistema operativo del nodo: disco, red, memoria del host, descriptores de fichero. Necesario para detectar problemas que afectan a todos los pods en un nodo antes de que los pods lo manifiesten.
Las métricas de aplicación son las más valiosas y las más frecuentemente ausentes. Un pod de Kubernetes puede parecer perfectamente sano a nivel de cluster mientras el servicio está degradado internamente. Sin métricas propias de la aplicación, la observabilidad tiene un techo bajo.
Logs estructurados: de stdout a búsqueda operacional en segundos
Los logs no estructurados son una deuda operativa que se paga en tiempo de incidente. Cuando un sistema genera miles de líneas de texto libre por segundo, buscar la causa de un fallo específico se convierte en un proceso manual que depende de la experiencia del ingeniero, no de la capacidad del sistema. En producción, esto se traduce en MTTR alto y en conocimiento que no se transfiere entre miembros del equipo.
Los logs estructurados resuelven esto. El principio es simple: cada línea de log es un objeto con campos definidos, no una cadena de texto que un humano tiene que parsear. El formato más común es JSON. Un log estructurado tiene al menos: timestamp en ISO 8601, nivel de severidad, mensaje, servicio de origen, y un trace ID o correlation ID que permite conectar este log con la petición que lo generó.
El correlation ID es el elemento más infravalorado de un sistema de logging operacional. Sin él, investigar un fallo requiere correlacionar manualmente los logs de cada servicio por timestamp, lo cual en sistemas distribuidos con varios nodos y relojes no perfectamente sincronizados es frágil. Con un correlation ID propagado correctamente a través de las cabeceras HTTP, típicamente X-Request-ID o el formato W3C traceparent, puedes filtrar todos los logs de todos los servicios implicados en una petición fallida con una sola query.
La elección del stack de agregación de logs tiene implicaciones de coste importantes:
Loki (de Grafana Labs) indexa solo los labels del log, no el contenido completo. Esto lo hace significativamente más barato de operar que Elasticsearch para volúmenes altos. La contrapartida es que las queries sobre el contenido del mensaje son más lentas: Loki tiene que escanear los logs comprimidos en lugar de buscar en un índice invertido. Para la mayoría de casos de uso operacional, donde filtras por servicio, nivel y correlation ID antes de explorar el contenido, Loki es la opción más rentable.
Elasticsearch con OpenSearch o Elastic Cloud tiene un indexado completo del contenido, lo que permite queries arbitrarias sobre cualquier campo. El coste operativo es más alto: más memoria, más complejidad de administración, clusters que requieren atención. Justificado cuando los casos de uso incluyen búsqueda de texto libre sobre el contenido de los mensajes, análisis de logs de seguridad, o compliance que requiere retenciones largas con queries ad-hoc.
CloudWatch Logs (AWS), Cloud Logging (GCP), Azure Monitor eliminan el coste operativo de gestionar el stack pero tienen un coste por ingestión y por query que puede escalar rápidamente con volumen. Son la opción correcta cuando el equipo no tiene capacidad para operar infraestructura de logs y el volumen es moderado.
Para reducir coste sin perder utilidad, las decisiones que más impactan son: filtrar logs al nivel correcto por entorno, DEBUG solo en desarrollo, INFO en producción por defecto, con capacidad de bajar a DEBUG en un servicio específico sin reinicio, establecer retenciones diferenciadas por criticidad del dato, y evitar loguear estructuras completas de objetos cuando solo necesitas un identificador.
Trazas distribuidas con OpenTelemetry: cómo encontrar el cuello de botella en 5 minutos
Las trazas distribuidas son el componente de observabilidad que más frecuentemente falta en plataformas que ya tienen métricas y logs. La razón es que instrumentar métricas es relativamente sencillo y el valor es inmediato. Las trazas requieren instrumentación en cada servicio y propagación del contexto entre ellos, lo que parece un esfuerzo mayor. El problema con ignorarlas es que, en un sistema de microservicios, las métricas te dicen que hay un problema y los logs te dan contexto sobre un servicio individual, pero solo las trazas te muestran el camino completo de una petición a través del sistema y dónde se gasta el tiempo.
OpenTelemetry es el estándar de facto para instrumentación de observabilidad. Unifica la recopilación de métricas, logs y trazas en un SDK y un protocolo común, OTLP. Tiene soporte en todos los lenguajes principales y permite cambiar el backend de observabilidad sin cambiar el código de instrumentación. Elegir OpenTelemetry en lugar de SDKs propietarios de un vendor específico es una decisión de arquitectura con impacto a largo plazo: reduces el lock-in y mantienes la flexibilidad de cambiar Jaeger por Tempo o por Honeycomb sin retocar aplicaciones.
La primera decisión práctica es auto-instrumentación vs instrumentación manual. La auto-instrumentación, disponible para Java, Python, Node.js y otros runtimes, inyecta instrumentación automáticamente sin cambios de código. Captura traces de llamadas HTTP, base de datos, colas de mensajes y otros sistemas usando instrumentaciones de librerías conocidas. Es la forma más rápida de conseguir cobertura básica y el punto de partida recomendado. La instrumentación manual añade spans personalizados para operaciones de negocio que la auto-instrumentación no puede capturar: una transacción de inventario, una regla de pricing, un pipeline de procesamiento interno. Ambas conviven y son complementarias.
La segunda decisión crítica es la estrategia de sampling. No puedes ni debes guardar todas las trazas en producción con tráfico alto: el coste de almacenamiento y la sobrecarga de procesamiento son prohibitivos. El sampling head-based toma la decisión de samplear en el primer servicio que recibe la petición, antes de conocer el resultado. Simple de implementar pero ciega: tienes la misma probabilidad de samplear una petición rápida y exitosa que una que va a fallar. El sampling tail-based toma la decisión al final, cuando la traza está completa. Esto permite samplear el 100% de las peticiones con error, el 100% de las lentas, y un porcentaje bajo del resto. Es más caro de operar, requiere un collector con estado, pero produce un corpus de trazas mucho más útil para diagnóstico.
Para la propagación del contexto de traza, el estándar W3C TraceContext, traceparent header, es el formato correcto. Asegúrate de que todos los servicios, incluyendo proxies, API gateways y colas de mensajes, preservan y propagan este header. Un break en la cadena de propagación produce trazas fragmentadas que no conectan entre servicios.
La elección del backend de trazas tiene implicaciones operativas distintas:
Jaeger es el backend open source más maduro. Buena UI, soporte de queries por servicio, operación, duration y tags. Requiere gestión de la infraestructura de almacenamiento, Cassandra o Elasticsearch en producción.
Tempo (Grafana Labs) está optimizado para coste: almacena trazas en object storage, S3 o GCS, en lugar de bases de datos especializadas. Se integra nativamente con Grafana y permite correlacionar métricas, logs y trazas en la misma interfaz. Para equipos que ya usan el stack LGTM, es la elección natural.
AWS X-Ray elimina la gestión de infraestructura pero tiene un modelo de datos propietario. La integración con otros servicios AWS es buena. El lock-in es real: migrar fuera de X-Ray requiere cambios de instrumentación.
SLOs y error budgets: la base de una guardia sostenible
La sostenibilidad del on-call es un problema de ingeniería, no de actitud. Los equipos que se queman en guardia no lo hacen porque les falte dedicación. Lo hacen porque el sistema no les da suficiente información para distinguir lo urgente de lo que puede esperar, y porque cada alerta requiere investigación manual desde cero. Los SLOs bien definidos no resuelven todos estos problemas, pero cambian la estructura del problema.
Un SLO es un objetivo medible sobre la fiabilidad del servicio desde la perspectiva del usuario. No "el servidor tiene que tener CPU por debajo del 80%", sino "el 99.5% de las peticiones de búsqueda tienen que completarse en menos de 400ms en una ventana de 30 días". El nivel de exigencia del objetivo, el SLI, Service Level Indicator, que lo mide, y la ventana de tiempo son las tres decisiones que determinan si el SLO es útil o no.
Los errores que más frecuentemente producen SLOs inútiles son: definirlos sobre métricas de infraestructura en lugar de experiencia de usuario, hacer la ventana demasiado corta, diaria, o poner el objetivo tan alto, 99.99%, que el error budget desaparece con el primer deploy.
El error budget es el complemento operativo del SLO. Si el SLO es 99.5% de disponibilidad en 30 días, el error budget es 0.5% de ese periodo, aproximadamente 3.6 horas de degradación permitida al mes. Este budget no es "margen para fallar". Es el recurso que permite tomar riesgos calculados: despliegues, experimentos, cambios de infraestructura. Cuando el budget se consume más rápido de lo esperado, el sistema envía una señal clara: hay que frenar los cambios y estabilizar.
Las alertas de burn rate son la implementación práctica del error budget como señal de guardia. En lugar de alertar cuando la tasa de error supera un umbral estático, alertas cuando el error budget se está consumiendo a una velocidad que, si se mantiene, lo agotará antes de que termine el periodo. Un burn rate de 1x significa que se consume exactamente al ritmo esperado. Un burn rate de 14x significa que el budget mensual se agotará en dos días si el problema no se resuelve. Esta distinción importa para calibrar la urgencia de la respuesta.
La conexión entre SLOs y sostenibilidad del on-call es directa. Con un error budget bien gestionado, el equipo tiene un criterio objetivo para decidir si un pager merece despertar a alguien a las 3am. Si el burn rate es bajo y el budget tiene margen, puede esperar. Si el burn rate es alto, la urgencia está justificada. Esto reduce las alertas sin urgencia real y reserva la interrupción nocturna para los casos que la merecen.
El stack de observabilidad que funciona en producción
El stack LGTM de Grafana, Loki, Grafana, Tempo, Mimir o Prometheus, se ha consolidado como la combinación más común para equipos que quieren observabilidad completa con control sobre el coste. Prometheus para métricas, Loki para logs, Tempo para trazas, y Grafana como capa de visualización y correlación. La ventaja principal es la integración nativa entre componentes: puedes saltar de una métrica a los logs correlacionados a la traza asociada dentro de la misma interfaz. El coste de operarlo es real y requiere capacidad de plataforma.
Grafana Cloud ofrece el mismo stack como servicio gestionado. El modelo de precios escala con volumen de métricas activas, logs ingestados y trazas almacenadas. Para equipos con volumen moderado y sin capacidad de plataforma dedicada, el coste total suele ser inferior al de operar la infraestructura propia, incluyendo tiempo de ingeniería y incidentes de la propia plataforma de observabilidad.
Datadog tiene la propuesta de valor de la plataforma integrada: APM, logs, métricas, sintetic monitoring, y security en una sola herramienta con una sola UI. El coste por host y por servicio instrumentado puede volverse significativo a escala, pero la experiencia de correlación y el tiempo hasta el primer valor son de los mejores del mercado. Justificado para organizaciones donde el tiempo de ingeniería tiene un coste alto y la correlación entre señales es crítica.
Honeycomb está optimizado para análisis de alta cardinalidad sobre eventos. Si tu caso de uso principal es debuggear problemas en sistemas de microservicios con muchas dimensiones, user ID, tenant, region, version, feature flag, Honeycomb tiene una ventaja técnica real sobre herramientas orientadas a métricas agregadas. La curva de adopción es distinta: requiere cambiar el modelo mental de "métricas y dashboards" a "eventos y queries".
La decisión de self-host vs gestionado depende de tres variables: volumen de datos, a volumen muy alto self-host puede ser más barato, capacidad del equipo, operar Prometheus en alta disponibilidad, Loki con compactación, Tempo con object storage no es trivial, y tolerancia a incidentes de la propia plataforma de observabilidad.
Checklist de observabilidad antes de ir a producción
Antes de exponer un nuevo servicio o feature a tráfico real, estas son las comprobaciones que reducen el riesgo de incidentes sin diagnóstico:
| # | Criterio | Verificación |
|---|---|---|
| 1 | Métricas de golden signals expuestas | El servicio expone endpoint /metrics con latencia, tráfico, errores y saturación |
| 2 | SLO definido y documentado | Existe un objetivo medible sobre experiencia de usuario, no sobre infraestructura |
| 3 | Alertas de burn rate configuradas | Al menos alerta de burn rate alto, 14x, y burn rate moderado, 6x |
| 4 | Logs en formato estructurado, JSON | Todos los logs incluyen timestamp, nivel, servicio, mensaje y correlation ID |
| 5 | Correlation ID propagado | El trace ID se propaga en headers entre todos los servicios del flujo |
| 6 | Auto-instrumentación OpenTelemetry activa | Trazas generadas para llamadas HTTP y base de datos sin instrumentación manual |
| 7 | Dashboard de servicio creado | Existe un dashboard con los golden signals del servicio, accesible al equipo |
| 8 | Runbook enlazado desde las alertas | Cada alerta tiene un enlace al runbook de respuesta inicial |
| 9 | Retenciones de log configuradas | Política de retención diferenciada por nivel, DEBUG 3d, INFO 15d, ERROR 90d |
| 10 | Sampling de trazas configurado | Trazas con error al 100%, trazas lentas al 100%, resto al 5-10% |
| 11 | kube-state-metrics cubriendo el namespace | Alertas de pod en crashloop y deployment atascado activas |
| 12 | Test de observabilidad en staging | El equipo ha validado que un fallo simulado es detectable en menos de 5 minutos |
Cuándo los incidentes tardan más de lo aceptable en resolverse
Si los incidentes en tu plataforma Kubernetes duran más tiempo del que puedes justificar, el problema rara vez es la herramienta que falta. Es la ausencia de una capa de observabilidad que conecte métricas, logs y trazas con el impacto real en el usuario. Construir esa capa requiere decisiones de arquitectura, no solo instalación de software.
En Valendra trabajamos con equipos que operan Kubernetes en producción y necesitan reducir MTTR, eliminar la fatiga de alertas y establecer SLOs que reflejen experiencia de usuario real. Si eso describe tu situación, hablemos.






