Lab 37 - Prometheus and Grafana

Lab 37 - Prometheus and Grafana

Goal: install the monitoring stack, read the cluster in Grafana, scrape your own application and write an alert. Chapter: Monitoring with Prometheus and Grafana

Install kube-prometheus-stack

# 1 -
cd ~
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
cat > kps-values.yaml <<'YAML'
prometheus:
  prometheusSpec:
    retention: 2d
    serviceMonitorSelectorNilUsesHelmValues: false   # watch ALL ServiceMonitors
    ruleSelectorNilUsesHelmValues: false             # and ALL PrometheusRules
# kubeadm binds these to localhost - skip them in the lab
kubeEtcd: { enabled: false }
kubeScheduler: { enabled: false }
kubeControllerManager: { enabled: false }
YAML
helm install kps prometheus-community/kube-prometheus-stack -n monitoring \
  --create-namespace -f kps-values.yaml --wait --timeout 10m
kubectl get pods -n monitoring
# 2 - what arrived?
kubectl get crd | grep monitoring.coreos.com
kubectl get ds,deploy,sts -n monitoring
kubectl get servicemonitors -n monitoring

Prometheus and Alertmanager (StatefulSets, run by the Prometheus Operator), Grafana, kube-state-metrics, node-exporter (DaemonSet) - and a dozen ServiceMonitors describing what to scrape.

Grafana

# 3 - password, then open Grafana and Prometheus to your PC via support01
kubectl get svc -n monitoring
kubectl get secret -n monitoring kps-grafana -o jsonpath='{.data.admin-password}' | base64 -d; echo
kubectl port-forward -n monitoring svc/kps-grafana 3000:80 --address 0.0.0.0 &
kubectl port-forward -n monitoring svc/kps-kube-prometheus-stack-prometheus 9090 --address 0.0.0.0 &

Grafana: http://192.168.56.101:3000, user admin. Then:

  • Dashboards -> Kubernetes / Compute Resources / Cluster - CPU and memory by namespace. Compare requests with usage.
  • Kubernetes / Compute Resources / Namespace (Pods) for kube-system.
  • Node Exporter / Nodes - one worker’s CPU, memory, disk, network.

Prometheus and PromQL

Prometheus: http://192.168.56.101:9090 -> Query, and try:

sum by (namespace) (rate(container_cpu_usage_seconds_total{container!=""}[5m]))
sum by (namespace) (container_memory_working_set_bytes{container!=""}) / 1024 / 1024
kube_pod_container_status_restarts_total > 0
kube_deployment_status_replicas_available != kube_deployment_spec_replicas

Status -> Targets shows every scrape target and whether it is up.

Scrape your own application

# 4 - podinfo exposes /metrics and ships a ServiceMonitor in its chart
helm repo add podinfo https://stefanprodan.github.io/podinfo
helm install podinfo podinfo/podinfo -n shop --create-namespace \
  --set replicaCount=2 --set serviceMonitor.enabled=true
kubectl get servicemonitor -n shop
# 5 - generate a little traffic
kubectl run load -n shop --image busybox:1.36 --restart=Never -- \
  sh -c 'while true; do wget -qO- http://podinfo:9898/ >/dev/null; wget -qO- http://podinfo:9898/status/500 >/dev/null 2>&1; sleep 0.2; done'

After a minute, in Prometheus:

sum by (status) (rate(http_request_duration_seconds_count{namespace="shop"}[1m]))

Rate of requests per HTTP status - the R and E of RED.

An alert

# 6 -
cat > alert.yaml <<'YAML'
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: shop-alerts
  namespace: shop
spec:
  groups:
    - name: shop
      rules:
        - alert: ShopHighErrorRate
          expr: |
            sum(rate(http_request_duration_seconds_count{namespace="shop",status=~"5.."}[2m]))
              / sum(rate(http_request_duration_seconds_count{namespace="shop"}[2m])) > 0.2
          for: 1m
          labels: { severity: warning }
          annotations:
            summary: "More than 20 % of shop requests fail"
YAML
kubectl apply -f alert.yaml

Prometheus -> Alerts: ShopHighErrorRate goes pending, then firing after 1 minute. Alertmanager (svc/kps-kube-prometheus-stack-alertmanager, port 9093) would route it to mail or Teams.

# 7 - stop the errors, watch it resolve
kubectl delete pod load -n shop

Discovery

Infodiscover

Task A. Write a PromQL query that lists containers restarted more than twice in the last hour.

increase(kube_pod_container_status_restarts_total[1h]) > 2

Task B. Find in Grafana which namespace requests the most CPU compared to what it uses.

Dashboard Kubernetes / Compute Resources / Cluster, table “CPU Quota”: compare CPU Requests with CPU Usage - the ratio shows over-provisioning. Or in PromQL:

sum by (namespace) (kube_pod_container_resource_requests{resource="cpu"})
  / sum by (namespace) (rate(container_cpu_usage_seconds_total{container!=""}[5m]))

Keep

Keep the monitoring stack, the two port-forwards and shop - Lab 38 uses them. (If the port-forwards died, start them again as in step 3.)