Kubernetes Monitoring with kube-prometheus-stack
The kube-prometheus-stack combines Prometheus, Grafana, AlertManager, and node-exporter into a comprehensive monitoreo solution for Kubernetes clústers. Esta guía cubre Helm installation, ServiceMonitor configuration, PrometheusRules for alerting, Grafana dashboards, and implementing production-grade observability for your VPS and baremetal Kubernetes infrastructure.
Tabla de contenidos
- Kube-prometheus-stack Overview
- Instalaation
- Configuration
- ServiceMonitor
- PrometheusRules and Alerting
- Grafana Dashboards
- External Prometheus
- Practical Examples
- Conclusion
Kube-prometheus-stack Overview
Components
- Prometheus: Metrics collection and almacenamiento
- Grafana: Visualization and dashboarding
- AlertManager: Alert routing and management
- Prometheus Operator: Custom resource management
- node-exporter: Host-level metrics
- kube-state-metrics: Kubernetes object metrics
Arquitectura
Kubernetes Cluster
├── Prometheus Operator
├── Prometheus (time-series database)
├── AlertManager (alert routing)
├── Grafana (visualization)
├── node-exporter (host metrics)
└── kube-state-metrics (object metrics)
Instalación
Requisitos previos
- Kubernetes v1.16+
- Helm 3+
- 10GB+ free disk space (varies by retention)
- 4GB+ available memory
Helm Repository Setup
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
Basic Instalaation
helm install kube-prometheus \
prometheus-community/kube-prometheus-stack \
-n monitoring \
--create-namespace
Production Values File
Crea un values file for production:
# kube-prometheus-values.yaml
prometheus:
prometheusSpec:
retention: 30d
retentionSize: "50GB"
resources:
requests:
cpu: 500m
memory: 2Gi
limits:
cpu: 2
memory: 4Gi
storageSpec:
volumeClaimTemplate:
spec:
storageClassName: fast-ssd
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 100Gi
externalLabels:
cluster: "production"
environment: "prod"
# High availability
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- prometheus
topologyKey: kubernetes.io/hostname
alertmanager:
enabled: true
alertmanagerSpec:
storage:
volumeClaimTemplate:
spec:
storageClassName: fast-ssd
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
config:
global:
resolve_timeout: 5m
route:
group_by: ['alertname', 'cluster', 'service']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: 'default'
routes:
- match:
severity: critical
receiver: 'critical'
- match:
severity: warning
receiver: 'warning'
receivers:
- name: 'default'
slack_configs:
- api_url: 'YOUR_SLACK_WEBHOOK_URL'
channel: '#alerts'
- name: 'critical'
slack_configs:
- api_url: 'YOUR_SLACK_WEBHOOK_URL'
channel: '#critical-alerts'
pagerduty_configs:
- service_key: 'YOUR_PAGERDUTY_KEY'
grafana:
enabled: true
adminPassword: 'SetStrongPassword123'
persistence:
enabled: true
type: pvc
storageClassName: fast-ssd
size: 10Gi
datasources:
datasources.yaml:
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
url: http://kube-prometheus-prometheus:9090
isDefault: true
prometheus-node-exporter:
enabled: true
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 100m
memory: 128Mi
kube-state-metrics:
enabled: true
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
cpu: 100m
memory: 256Mi
Instala with values file:
helm install kube-prometheus \
prometheus-community/kube-prometheus-stack \
-n monitoring \
--create-namespace \
-f kube-prometheus-values.yaml
Verifica Instalaation
kubectl get pods -n monitoring
kubectl get services -n monitoring
kubectl get pvc -n monitoring
Configuración
Accessing Prometheus
Port-forward to Prometheus:
kubectl port-forward -n monitoring svc/kube-prometheus-prometheus 9090:9090
Access at http://localhost:9090
Accessing Grafana
Port-forward to Grafana:
kubectl port-forward -n monitoring svc/kube-prometheus-grafana 3000:80
Access at http://localhost:3000
Default credentials: admin / password from values
Accessing AlertManager
kubectl port-forward -n monitoring svc/kube-prometheus-alertmanager 9093:9093
Access at http://localhost:9093
ServiceMonitor
What is ServiceMonitor?
ServiceMonitor is a Kubernetes custom resource that tells Prometheus where to scrape metrics. It's espacio de nombres-scoped and targets servicios with specific labels.
Creating ServiceMonitor
Example for Kubernetes API server:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: kube-apiserver
namespace: kube-system
spec:
endpoints:
- interval: 30s
port: https
scheme: https
tlsConfig:
caFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
serverName: kubernetes
bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
selector:
matchLabels:
component: kube-apiserver
ServiceMonitor for Custom Application
Monitor a custom application exposing metrics on port 8080:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: my-app
namespace: production
spec:
selector:
matchLabels:
app: my-app
endpoints:
- port: metrics
interval: 30s
path: /metrics
scrapeTimeout: 10s
ServiceMonitor with Label Relabeling
Modify metric labels during scraping:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: postgres-exporter
namespace: databases
spec:
selector:
matchLabels:
app: postgres-exporter
endpoints:
- port: metrics
interval: 30s
relabelings:
- sourceLabels: [__meta_kubernetes_pod_name]
targetLabel: pod
- sourceLabels: [__meta_kubernetes_namespace]
targetLabel: namespace
- sourceLabels: [__meta_kubernetes_service_name]
targetLabel: service
PodMonitor Alternative
For monitoreo pods directly (not recommended, prefer Service/ServiceMonitor):
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: my-app-pods
namespace: production
spec:
selector:
matchLabels:
app: my-app
podMetricsEndpoints:
- port: metrics
interval: 30s
PrometheusRules and Alerting
PrometheusRule Structure
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: kubernetes-alerts
namespace: monitoring
spec:
groups:
- name: kubernetes.rules
interval: 30s
rules:
- alert: AlertName
expr: <promql_query>
for: 5m
labels:
severity: warning
annotations:
summary: "Alert summary"
description: "Detailed description"
Node Health Alerts
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: node-health
namespace: monitoring
spec:
groups:
- name: node.rules
interval: 30s
rules:
- alert: NodeNotReady
expr: kube_node_status_condition{condition="Ready",status="true"} == 0
for: 5m
labels:
severity: critical
annotations:
summary: "Node {{ $labels.node }} is not ready"
description: "Node {{ $labels.node }} has been unready for more than 5 minutes"
- alert: HighNodeMemoryUsage
expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) > 0.85
for: 5m
labels:
severity: warning
annotations:
summary: "High memory usage on node {{ $labels.instance }}"
description: "Memory usage is {{ $value | humanizePercentage }} on {{ $labels.instance }}"
- alert: HighNodeDiskUsage
expr: (1 - (node_filesystem_avail_bytes{fstype=~"ext4|xfs"} / node_filesystem_size_bytes)) > 0.85
for: 10m
labels:
severity: warning
annotations:
summary: "High disk usage on {{ $labels.instance }}"
description: "Disk usage is {{ $value | humanizePercentage }} on {{ $labels.instance }}"
Pod and Container Alerts
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: pod-alerts
namespace: monitoring
spec:
groups:
- name: pod.rules
interval: 30s
rules:
- alert: PodCrashLooping
expr: rate(kube_pod_container_status_restarts_total[15m]) > 0.1
for: 5m
labels:
severity: critical
annotations:
summary: "Pod {{ $labels.namespace }}/{{ $labels.pod }} is crash looping"
description: "Pod has restarted {{ $value }} times in the last 15 minutes"
- alert: PodNotHealthy
expr: |
min_over_time(sum by (namespace, pod) (kube_pod_status_phase{phase=~"Pending|Unknown|Failed"})[15m:1m]) > 0
for: 15m
labels:
severity: warning
annotations:
summary: "Pod {{ $labels.namespace }}/{{ $labels.pod }} is not healthy"
description: "Pod has been in a non-running state for more than 15 minutes"
- alert: ContainerHighCpuUsage
expr: |
(sum(rate(container_cpu_usage_seconds_total{container!=""}[5m])) by (pod, namespace) / sum(container_spec_cpu_quota{container!=""}/container_spec_cpu_period{container!=""}) by (pod, namespace)) > 0.9
for: 5m
labels:
severity: warning
annotations:
summary: "Container {{ $labels.pod }} has high CPU usage"
description: "CPU usage is {{ $value | humanizePercentage }}"
Grafana Dashboards
Accessing Dashboards
Pre-installed dashboards:
- Kubernetes Cluster Monitoring
- Node Exporter
- Prometheus Stats
- Kubernetes API Server
Access via: http://localhost:3000 → Dashboards
Creating Custom Dashboard
Access Grafana and create a new dashboard:
- Click + icon → Dashboard
- Add panels with PromQL queries
- Configura visualization
- Save with meaningful name
Example Panel Query
Query for Pod CPU Usage:
sum(rate(container_cpu_usage_seconds_total{pod=~"my-app.*"}[5m])) by (pod)
Query for Pod Memory Usage:
sum(container_memory_usage_bytes{pod=~"my-app.*"}) by (pod) / (1024^3)
Dashboard JSON Export
Export dashboard configuration:
# Get dashboard JSON
curl -s http://admin:password@localhost:3000/api/dashboards/uid/dashboard-uid | jq .dashboard > dashboard.json
# Import dashboard
curl -X POST http://admin:password@localhost:3000/api/dashboards/db \
-H "Content-Type: application/json" \
-d @dashboard.json
External Prometheus
Remote Storage Configuration
Write metrics to external almacenamiento (e.g., Prometheus Cloud):
prometheus:
prometheusSpec:
remoteWrite:
- url: "https://cortex.example.com/api/prom/push"
writeRelabelConfigs:
- sourceLabels: [__name__]
regex: 'prometheus_tsdb_.*'
action: drop
Federation
Aggregate multiple Prometheus instances:
# Central Prometheus scraping federated endpoints
- job_name: 'federate'
static_configs:
- targets:
- 'prometheus-cluster1:9090'
- 'prometheus-cluster2:9090'
metrics_path: '/federate'
params:
match[]:
- '{job="prometheus"}'
- '{__name__=~"job:.*"}'
Practical Examples
Ejemplo: Complete Monitoring Stack
# Create monitoring namespace
kubectl create namespace monitoring
# Add Helm repository
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
# Install with custom values
helm install kube-prometheus \
prometheus-community/kube-prometheus-stack \
-n monitoring \
-f kube-prometheus-values.yaml
# Wait for deployment
kubectl wait --for=condition=ready pod -l app.kubernetes.io/instance=kube-prometheus -n monitoring --timeout=300s
# Verify installation
kubectl get all -n monitoring
Ejemplo: Monitor Custom Application
---
# Service
apiVersion: v1
kind: Service
metadata:
name: my-app
namespace: production
labels:
app: my-app
spec:
ports:
- name: http
port: 8080
- name: metrics
port: 8081
selector:
app: my-app
---
# ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: my-app
namespace: monitoring
spec:
selector:
matchLabels:
app: my-app
namespaceSelector:
matchNames:
- production
endpoints:
- port: metrics
interval: 30s
path: /metrics
---
# PrometheusRule
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: my-app-alerts
namespace: monitoring
spec:
groups:
- name: my-app.rules
interval: 30s
rules:
- alert: AppHighErrorRate
expr: |
(sum(rate(app_requests_total{status=~"5.."}[5m])) by (instance) /
sum(rate(app_requests_total[5m])) by (instance)) > 0.05
for: 5m
labels:
severity: warning
annotations:
summary: "High error rate on {{ $labels.instance }}"
description: "Error rate is {{ $value | humanizePercentage }}"
Conclusión
The kube-prometheus-stack provides comprehensive monitoreo and alerting for Kubernetes clústers on VPS and baremetal infrastructure. By properly configuring ServiceMonitors for application metrics, implementing PrometheusRules for intelligent alerting, and utilizing Grafana dashboards for visualization, you create a production-grade observability platform. Start with the default dashboards and alerts, then customize based on your specific application requirements and operational needs. Regular review and tuning of alert thresholds ensure you stay informed without alert fatigue.


