--- title: "Cómo monitorizar Kubernetes con kube-prometheus-stack" description: "Despliega kube-prometheus-stack con Helm, accede a Prometheus y Grafana, monitoriza tus aplicaciones con ServiceMonitor y crea alertas con PrometheusRule." category: "Kubernetes Avanzado" language: es source: https://cubepath.com/es/docs/kubernetes-avanzado/monitoreo-de-kubernetes-con-kube-prometheus-stack updated: 2026-09-25 --- # Cómo monitorizar Kubernetes con kube-prometheus-stack 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 `kubectl` configurado contra el clúster y [Helm](https://helm.sh/docs/intro/install/) 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 ```bash helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo update ``` Comprueba que el chart está disponible: ```bash helm search repo prometheus-community/kube-prometheus-stack ``` ```output 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: ```bash nano kps-values.yaml ``` ```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`: ```bash 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: ```bash kubectl get pods -n monitoring ``` ```output 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: ```bash 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: ```bash 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: ```text 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: ```bash 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 `requests` y `limits`. - **Node Exporter / Nodes**: disco, red y carga de cada nodo. > Nota: para acceso permanente, publica Grafana a través de tu Ingress con TLS (valores `grafana.ingress.*` del chart) en lugar de exponer los servicios con `NodePort` o `LoadBalancer`. 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: ```bash nano podinfo.yaml ``` ```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: ```bash 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: ```text up{job="podinfo"} ``` ```output 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: ```bash nano podinfo-rules.yaml ``` ```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: ```bash kubectl apply -f podinfo-rules.yaml ``` Verifica que Prometheus la ha cargado en la página **Alerts** o con `port-forward` activo: ```bash curl -s http://localhost:9090/api/v1/rules | grep -o '"name":"PodinfoTargetDown"' ``` ```output "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-etcd` y `kube-proxy` aparecen como `DOWN` en clústeres kubeadm.** Por defecto esos componentes solo escuchan en `127.0.0.1`. Cambia `--bind-address` a `0.0.0.0` en los manifiestos de `/etc/kubernetes/manifests/` del plano de control (y `--listen-metrics-urls` para etcd, `metricsBindAddress` en 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 `selector` coinciden con las del Service, que el nombre del puerto es correcto y que usaste `serviceMonitorSelectorNilUsesHelmValues: 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. Revisa `kubectl 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`.