kube-prometheus-stack es el chart de Helm de la comunidad Prometheus que despliega de una vez Prometheus Operator, Prometheus, Alertmanager, Grafana, node-exporter y kube-state-metrics, junto con dashboards y reglas de alerta ya preparados para Kubernetes. En este tutorial lo instalarás con almacenamiento persistente, accederás a Prometheus y Grafana, añadirás una aplicación propia al monitoreo con un ServiceMonitor y crearás una alerta con un PrometheusRule.
Requisitos previos
Para seguir esta guía necesitas:
- Un clúster de Kubernetes 1.29 o superior con unos 4 GB de RAM y 2 vCPU libres para el stack, por ejemplo desplegado sobre VPS de CubePath.
- Una StorageClass por defecto para los volúmenes de Prometheus, Alertmanager y Grafana (
kubectl get storageclass). - Una estación de trabajo con
kubectlconfigurado contra el clúster y Helm 3 o superior.
Qué instala el chart
| Componente | Función |
|---|---|
| Prometheus Operator | Gestiona Prometheus y Alertmanager a partir de recursos personalizados (ServiceMonitor, PodMonitor, PrometheusRule). |
| Prometheus | Recoge y almacena las métricas. |
| Alertmanager | Agrupa las alertas y las envía a correo, Slack, PagerDuty, etc. |
| Grafana | Visualización, con dashboards de Kubernetes preinstalados. |
| node-exporter | DaemonSet con métricas de cada nodo: CPU, memoria, disco, red. |
| kube-state-metrics | Métricas del estado de los objetos: réplicas, reinicios, pods pendientes. |
La idea clave es que no editas la configuración de Prometheus a mano: creas objetos ServiceMonitor o PrometheusRule y el operador los traduce.
Paso 1: Añadir el repositorio de Helm
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
Comprueba que el chart está disponible:
helm search repo prometheus-community/kube-prometheus-stack
NAME CHART VERSION APP VERSION DESCRIPTION
prometheus-community/kube-prometheus-stack ... ... kube-prometheus-stack collects Kubernetes manif...
Paso 2: Preparar el fichero de valores
Los valores por defecto guardan las métricas en un volumen efímero (se pierden si el pod se reinicia) y hacen que Prometheus solo recoja los ServiceMonitor creados por el propio chart. Crea un fichero de valores que corrija ambas cosas:
nano kps-values.yaml
grafana:
adminPassword: your_strong_password
persistence:
enabled: true
size: 5Gi
prometheus:
prometheusSpec:
retention: 15d
retentionSize: 18GB
# Recoger ServiceMonitor, PodMonitor y reglas de cualquier namespace,
# no solo los que llevan la etiqueta del release de Helm
serviceMonitorSelectorNilUsesHelmValues: false
podMonitorSelectorNilUsesHelmValues: false
ruleSelectorNilUsesHelmValues: false
storageSpec:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 20Gi
alertmanager:
alertmanagerSpec:
storage:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 2Gi
Sustituye your_strong_password por una contraseña segura para el usuario admin de Grafana. retentionSize limita el espacio que ocupan las métricas; déjalo algo por debajo del tamaño del volumen para que Prometheus borre datos antiguos antes de llenar el disco.
Paso 3: Instalar kube-prometheus-stack
Instala el chart en el namespace monitoring:
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack \
--namespace monitoring --create-namespace \
-f kps-values.yaml
La primera instalación tarda uno o dos minutos. Comprueba los pods:
kubectl get pods -n monitoring
NAME READY STATUS RESTARTS AGE
alertmanager-kube-prometheus-stack-alertmanager-0 2/2 Running 0 90s
kube-prometheus-stack-grafana-5c7f9b8d6b-7xk2p 3/3 Running 0 95s
kube-prometheus-stack-kube-state-metrics-6d9c8b7f4-lm9qz 1/1 Running 0 95s
kube-prometheus-stack-operator-7b9d6c5f8-pp4tw 1/1 Running 0 95s
kube-prometheus-stack-prometheus-node-exporter-4hq8x 1/1 Running 0 95s
kube-prometheus-stack-prometheus-node-exporter-9rt2c 1/1 Running 0 95s
prometheus-kube-prometheus-stack-prometheus-0 2/2 Running 0 90s
Debe haber un pod de node-exporter por nodo. Comprueba también que los volúmenes se han creado:
kubectl get pvc -n monitoring
Los tres PVC (Prometheus, Alertmanager y Grafana) deben estar en estado Bound.
Paso 4: Acceder a Prometheus y Grafana
Los servicios del chart son de tipo ClusterIP, así que no están expuestos fuera del clúster. Para una primera prueba usa port-forward desde tu estación de trabajo:
kubectl port-forward -n monitoring svc/kube-prometheus-stack-prometheus 9090:9090
Abre http://localhost:9090 y ve a Status > Target health. Todos los objetivos deben aparecer como UP, salvo lo que se explica en la sección de solución de problemas sobre kubeadm. Prueba una consulta en la pestaña Query, por ejemplo el uso de CPU por nodo:
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
Detén el port-forward con Ctrl+C y abre el de Grafana:
kubectl port-forward -n monitoring svc/kube-prometheus-stack-grafana 3000:80
Entra en http://localhost:3000 con el usuario admin y la contraseña del fichero de valores. En Dashboards encontrarás decenas de paneles ya configurados. Empieza por:
- Kubernetes / Compute Resources / Cluster: CPU y memoria por namespace.
- Kubernetes / Compute Resources / Namespace (Pods): consumo de cada pod frente a sus
requestsylimits. - Node Exporter / Nodes: disco, red y carga de cada nodo.
Notapara acceso permanente, publica Grafana a través de tu Ingress con TLS (valores
grafana.ingress.*del chart) en lugar de exponer los servicios conNodePortoLoadBalancer. Prometheus y Alertmanager no tienen autenticación propia; no los expongas a Internet.
Paso 5: Monitorizar una aplicación con ServiceMonitor
Un ServiceMonitor le dice al operador qué Service debe consultar Prometheus y en qué puerto están las métricas. Para probarlo desplegarás podinfo, una pequeña aplicación de ejemplo que expone métricas en /metrics en el puerto 9898:
nano podinfo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: podinfo
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: podinfo
template:
metadata:
labels:
app: podinfo
spec:
containers:
- name: podinfo
image: ghcr.io/stefanprodan/podinfo:6.7.1
ports:
- name: http
containerPort: 9898
---
apiVersion: v1
kind: Service
metadata:
name: podinfo
namespace: default
labels:
app: podinfo
spec:
selector:
app: podinfo
ports:
- name: http
port: 9898
targetPort: http
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: podinfo
namespace: default
spec:
selector:
matchLabels:
app: podinfo
endpoints:
- port: http
path: /metrics
interval: 30s
Dos detalles importantes: el selector del ServiceMonitor apunta a las etiquetas del Service, no del pod, y port es el nombre del puerto del Service. Aplica el manifiesto:
kubectl apply -f podinfo.yaml
En uno o dos minutos, la página Status > Target health de Prometheus mostrará un nuevo grupo serviceMonitor/default/podinfo/0 con dos objetivos UP, uno por réplica. También puedes comprobarlo con una consulta:
up{job="podinfo"}
up{container="podinfo", endpoint="http", instance="10.244.1.23:9898", job="podinfo", namespace="default", pod="podinfo-7c9b8d5f6-2klqx", service="podinfo"} 1
up{container="podinfo", endpoint="http", instance="10.244.2.17:9898", job="podinfo", namespace="default", pod="podinfo-7c9b8d5f6-v8xrt", service="podinfo"} 1
Paso 6: Crear una alerta con PrometheusRule
Las reglas de alerta también se declaran como recursos. Crea una alerta que salte si alguna réplica de podinfo deja de responder durante dos minutos:
nano podinfo-rules.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: podinfo-alerts
namespace: default
spec:
groups:
- name: podinfo
rules:
- alert: PodinfoTargetDown
expr: up{job="podinfo"} == 0
for: 2m
labels:
severity: warning
annotations:
summary: "podinfo no responde en {{ $labels.pod }}"
description: "Prometheus no puede leer las métricas de {{ $labels.instance }} desde hace 2 minutos."
Aplica la regla:
kubectl apply -f podinfo-rules.yaml
Verifica que Prometheus la ha cargado en la página Alerts o con port-forward activo:
curl -s http://localhost:9090/api/v1/rules | grep -o '"name":"PodinfoTargetDown"'
"name":"PodinfoTargetDown"
Para probarla, escala podinfo a cero réplicas no sirve (desaparecen los objetivos en lugar de fallar). En su lugar, cambia temporalmente el path del ServiceMonitor a una ruta inexistente como /nometrics: los objetivos pasarán a DOWN y, tras dos minutos, la alerta aparecerá como Firing en Prometheus y en Alertmanager (kubectl port-forward -n monitoring svc/kube-prometheus-stack-alertmanager 9093:9093). Restaura el path al terminar.
Solución de problemas
- Los objetivos
kube-controller-manager,kube-scheduler,kube-etcdykube-proxyaparecen comoDOWNen clústeres kubeadm. Por defecto esos componentes solo escuchan en127.0.0.1. Cambia--bind-addressa0.0.0.0en los manifiestos de/etc/kubernetes/manifests/del plano de control (y--listen-metrics-urlspara etcd,metricsBindAddressen el ConfigMap de kube-proxy), protegiendo esos puertos con el firewall, o desactiva esos monitores en los valores del chart (kubeControllerManager.enabled: false, etc.) si no los necesitas. - Un ServiceMonitor no aparece en los objetivos. Comprueba que las etiquetas del
selectorcoinciden con las del Service, que el nombre del puerto es correcto y que usasteserviceMonitorSelectorNilUsesHelmValues: false. Los logs del operador ayudan:kubectl logs -n monitoring deploy/kube-prometheus-stack-operator. - Los pods de Prometheus se quedan en
Pending. Suele ser el PVC sin StorageClass. Revisakubectl describe pvc -n monitoring.
Conclusión
Tienes un stack de monitoreo completo: métricas de nodos, del plano de control y de los objetos de Kubernetes, dashboards en Grafana, y la forma declarativa de añadir tus aplicaciones y alertas con ServiceMonitor y PrometheusRule. Como siguientes pasos, configura los receptores de Alertmanager (valor alertmanager.config del chart) para recibir las alertas por correo o Slack, publica Grafana con Ingress y TLS, y ajusta la retención según el espacio disponible o envía las métricas a un almacenamiento a largo plazo con remoteWrite.
