๐ŸŽฏ Problem Statement

Modern Kubernetes environments face observability challenges:

  • Visibility Gap - No centralized view of cluster and application health
  • Troubleshooting - Difficulty correlating metrics, logs, and traces
  • Alert Fatigue - Too many false positives or missing critical alerts
  • Cost - Expensive commercial APM solutions
  • Scalability - Monitoring solution must scale with the cluster

๐Ÿ’ก Solution Overview

I designed and deployed a comprehensive open-source observability stack using Prometheus, Grafana, Loki, and Tempo, providing metrics, logs, traces, and alerting in a unified platform.

๐Ÿ—๏ธ Architecture

โ”Œโ”‚โ”œโ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”Œโ”‚โ”‚โ”‚โ”‚โ”‚โ””โ”Œโ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”Œโ”‚โ”‚โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€A/โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€pmโ”€โ”€โ”€โ”Œโ”‚โ”‚โ”‚โ”‚โ””โ”Œโ”‚โ”‚โ”‚โ””โ”Œโ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ””โ”Œโ”‚โ”‚โ”‚โ””โ”Œโ”‚โ”‚โ””โ”€โ”€โ”€โ”€โ”€โ”€peโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€tโ”ฌโ”ผโ”‚โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€Arโ”€โ”€โ”€โ”€โ”€---โ”€โ”€--โ”€โ”€โ”Œโ”‚โ”‚โ”‚โ”‚โ””โ”€โ”€(โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€iโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€Lโ”€โ”€-โ”€โ”€โ”€โ”€โ”€โ”€โ”€cโ”€โ”€โ”€โ”€โ”€SRAโ”€โ”€RSโ”€โ”€โ”€D---โ”€โ”€โ”€oโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€sโ”€โ”€โ”€โ”€โ”€eelโ”€โ”€olโ”€โ”€โ”€aโ”€โ”€โ”€gโ”€โ”€Cโ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚โ”‚โ”˜โ”€โ”€โ”€โ”€rceโ”€โ”€uaโ”€โ”€โ”€tPLTโ”€โ”€โ”€โ”€โ”€oโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€vorโ”€โ”€tcโ”€โ”€โ”€aroeโ”€โ”€โ”€LAโ”€โ”€lโ”€โ”€โ”€โ”€โ”€โ”€โ”Œโ”‚โ”‚โ””โ”€โ”€โ”€Oโ”€irtโ”€โ”€ikโ”€โ”€โ”€okmโ”€โ”€โ”€ogโ”€โ”€lโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€bโ”€cdโ”€โ”€n/โ”€โ”€โ”€Smipโ”€โ”€โ”€kgโ”€โ”€eโ”€โ”€โ”€โ”€โ”€โ”€โ”€A/โ”€โ”€โ”€โ”€sโ”€eiRโ”€โ”€gPโ”€โ”€โ”€oeoโ”€โ”€โ”€irโ”€โ”€Pcโ”€โ”€โ”€โ”€Kโ”€โ”€โ”€pmโ”€โ”€โ”€โ”€eโ”€PMnuโ”€โ”€Aaโ”€โ”€โ”€ut(โ”€โ”€โ”€eโ”€โ”€rtโ”€โ”€โ”€โ”€uโ”€โ”€โ”€peโ”€โ”€โ”€โ”€rโ”€roglโ”€โ”€lgโ”€โ”€โ”€rhL(โ”€โ”€โ”€gโ”€โ”€osโ”€โ”€โ”€โ”€bโ”€โ”€โ”€tโ”ฌโ”ผโ”‚โ”ดโ”€vโ”€oneโ”€โ”€eeโ”€โ”€โ”€ceoTโ”€โ”€โ”€aโ”€โ”€mโ”€โ”€โ”€โ”€eโ”€โ”€Aโ”€Brโ”€โ”€โ”€โ”€aโ”€miRsโ”€โ”€rrโ”€โ”€Gโ”€eugrโ”€โ”€โ”€tโ”€โ”€tlโ”€โ”€โ”€โ”€rโ”€โ”€pโ”€iโ”€โ”€โ”€โ”€bโ”€etuโ”€โ”€tDโ”€โ”€rโ”€sssaโ”€โ”€โ”€iโ”€โ”€aoโ”€โ”€โ”€โ”€nโ”€โ”€pโ”€cโ”€โ”€โ”€โ”€iโ”€tolโ”€โ”€muโ”€โ”€aโ”€:)cโ”€โ”€โ”€oโ”€โ”€igโ”€โ”€โ”€โ”€eโ”€โ”€lโ”€sโ”€โ”€โ”€โ”€lโ”€hreโ”€โ”€atโ”€โ”€fโ”€(eโ”€โ”€โ”€nโ”€โ”€lsโ”€โ”€โ”€โ”€tโ”€โ”€iโ”โ”‚โ”‚โ”˜โ”€โ”€โ”€iโ”€esโ”€โ”€nyโ”€โ”€aโ”€Msโ”€โ”€โ”€)โ”€โ”€โ”€โ”€โ”€โ”€eโ”€โ”€cโ”€โ”ฌโ”‚โ”ผtโ”‚โ–ผuCโ”ฌโ”‚โ–ผaโ”€โ”€nโ”€e)โ”€โ”€โ”โ”‚โ”‚โ”‚โ”˜โ”€(fโ”€โ”€โ”€โ”€sโ”€โ”€aโ”Œโ”‚โ”‚โ””โ”€โ”€โ”€yโ”€sRโ”€โ”€gโ”€โ”€aโ”€tโ”€โ”€โ”€Drโ”€โ”€โ”€โ”€โ”€โ”€tโ”€โ”€โ”€โ”€โ”€โ”€Dโ”€โ”€eโ”€โ”€โ”€rโ”€โ”€โ”€aoโ”€โ”€โ”€โ”€Cโ”€โ”€iโ”€A/โ”€โ”€โ”€โ”€Nโ”€sโ”€โ”€rโ”€โ”€โ”€iโ”€โ”€โ”Œโ”‚โ”‚โ”‚โ””โ”€emโ”€โ”€โ”€โ”€lโ”€โ”€oโ”€pmโ”€โ”€โ”€โ”€aโ”€โ”€โ”€โ”€โ”€โ”€cโ”€โ”€โ”€โ”€โ”€mโ”€โ”€โ”€โ”€uโ”€โ”€nโ”€peโ”€โ”€โ”€โ”€mโ”€โ”€โ”€โ”€โ”€โ”€sโ”€โ”€โ”€(โ”€โ”€oaโ”€โ”€โ”€โ”€sโ”€โ”€โ”€tโ”ฌโ”ผโ”‚โ”ดโ”€eโ”€โ”€โ”€โ”€โ”€โ”€)โ”€โ”€โ”€DTโ”€โ”€nlโ”€โ”€โ”€โ”€tโ”€โ”€Pโ”€Crโ”€โ”€โ”€โ”€sโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€irโ”€โ”€Slโ”€โ”€โ”€โ”€eโ”€โ”€oโ”€iโ”€โ”€โ”€โ”€pโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€saโ”€โ”€eโ”€โ”€โ”€โ”€rโ”€โ”€dโ”€cโ”€โ”€โ”€โ”€aโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€tcโ”€โ”€tpโ”€โ”€โ”€โ”€โ”€โ”€sโ”€sโ”€โ”€โ”€โ”€cโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€Triโ”€โ”€)oโ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚โ”‚โ”˜โ”€โ”€โ”€eโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€einโ”€โ”€dโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€mbgโ”€โ”€sโ”€โ”€โ”€โ”€โ”€โ”€โ”Œโ”‚โ”‚โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€pu)โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€otโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€A/โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€eโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€pmโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€dโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€peโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€tโ”ฌโ”ผโ”‚โ”˜โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚โ”‚โ”‚โ”˜โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€Drโ”€โ”€โ”€โ”โ”‚โ”˜โ”โ”‚โ”‚โ”˜โ”โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”˜โ”€โ”€โ”โ”‚โ”‚โ”˜โ”€โ”€โ”€โ”€โ”€โ”€iโ”€โ”€โ”€โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€cโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€sโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚โ”‚โ”˜โ”€โ”€โ”โ”‚โ”‚โ”‚โ”˜โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”‚โ”‚โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”˜โ”€โ”€โ”€โ”€โ”€โ”‚โ”โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”€โ”€โ”€โ”€โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”˜โ”€โ”€โ”€โ”‚โ”‚โ”‚โ”‚โ”€โ”โ”คโ”‚โ”‚โ”˜โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚โ”‚

๐Ÿ› ๏ธ Technologies Used

ComponentTechnologyPurpose
MetricsPrometheusTime-series metrics collection
VisualizationGrafanaDashboards and alerting UI
LogsLoki + PromtailLog aggregation
TracesTempoDistributed tracing
AlertingAlertmanagerAlert routing and notifications
DeploymentHelm + ArgoCDGitOps-based deployment
StorageThanosLong-term metrics storage

๐Ÿ“ Project Structure

kโ”œโ”‚โ”‚โ”‚โ”‚โ”‚โ”œโ”‚โ”‚โ”‚โ”‚โ”œโ”‚โ”‚โ”‚โ”‚โ”œโ”‚โ””8โ”€โ”€โ”€โ”€โ”€sโ”€โ”€โ”€โ”€โ”€-ohโ””dโ”œโ”œโ”œโ””aโ”œโ”œโ”œโ””sโ””kbeโ”€aโ”€โ”€โ”€โ”€lโ”€โ”€โ”€โ”€eโ”€uslโ”€sโ”€โ”€โ”€โ”€eโ”€โ”€โ”€โ”€rโ”€semhrvtr/vโ”œโ”œโ”œโ””bcpnatnpasiaoaโ”€โ”€โ”€โ”€oloopsoplcpmalโ”€โ”€โ”€โ”€auddpddpoepiburs-ele-l-mlziepgltdtm-i-aiaoialsrroeseeecalclncti/oakm/rtxaleaeiaitmfip-rptertrttoyea-ooioirtitoin/tnv-vcrotsosro.haavestns.n.snye-lar.e-.y-y/-auvulvjrmyaaammsaeuis.eamlmol-lseeojtmlelnvu.swnsrlriaey..oittlsayjncsou.mass.reylmo.yssalnja..msmyylolaanmmll

๐Ÿ”ง Implementation Highlights

Prometheus ServiceMonitor

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: app-metrics
  namespace: observability
  labels:
    release: prometheus
spec:
  selector:
    matchLabels:
      app: my-application
  namespaceSelector:
    matchNames:
      - production
      - staging
  endpoints:
    - port: metrics
      interval: 30s
      path: /metrics
      scrapeTimeout: 10s

Alert Rules for SLOs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: slo-alerts
  namespace: observability
spec:
  groups:
    - name: slo.rules
      rules:
        - alert: HighErrorRate
          expr: |
            (
              sum(rate(http_requests_total{status=~"5.."}[5m]))
              /
              sum(rate(http_requests_total[5m]))
            ) > 0.01
          for: 5m
          labels:
            severity: critical
          annotations:
            summary: "High error rate detected"
            description: "Error rate is {{ $value | humanizePercentage }} (>1% threshold)"
            runbook_url: "https://runbooks.example.com/high-error-rate"

        - alert: HighLatencyP99
          expr: |
            histogram_quantile(0.99,
              sum(rate(http_request_duration_seconds_bucket[5m])) by (le, service)
            ) > 0.5
          for: 10m
          labels:
            severity: warning
          annotations:
            summary: "P99 latency is high"
            description: "P99 latency for {{ $labels.service }} is {{ $value }}s"

Grafana Dashboard as Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
apiVersion: v1
kind: ConfigMap
metadata:
  name: grafana-dashboards
  namespace: observability
  labels:
    grafana_dashboard: "1"
data:
  cluster-overview.json: |
    {
      "dashboard": {
        "title": "Cluster Overview",
        "panels": [
          {
            "title": "CPU Usage",
            "type": "graph",
            "targets": [
              {
                "expr": "sum(rate(container_cpu_usage_seconds_total[5m])) by (namespace)",
                "legendFormat": "{{namespace}}"
              }
            ]
          },
          {
            "title": "Memory Usage",
            "type": "graph",
            "targets": [
              {
                "expr": "sum(container_memory_usage_bytes) by (namespace) / 1024 / 1024 / 1024",
                "legendFormat": "{{namespace}} (GB)"
              }
            ]
          }
        ]
      }
    }

Loki Log Queries

1
2
3
4
5
6
7
8
# Error logs from production namespace
{namespace="production"} |= "error" | json | line_format "{{.message}}"

# Slow requests (>1s response time)
{app="api-gateway"} | json | response_time > 1000

# Failed Kubernetes events
{job="kubernetes-events"} | json | type="Warning"

๐Ÿ“Š Dashboards Created

DashboardPurpose
Cluster OverviewNode health, resource utilization, pod status
Namespace MetricsPer-namespace resource consumption
Application SLOsError rates, latency percentiles, throughput
Node ExporterDetailed node-level metrics
Kubernetes EventsCluster events and warnings
Cost AnalysisResource costs by namespace/team

๐Ÿ”” Alerting Strategy

Alert Severity Levels

SeverityResponse TimeNotification Channel
CriticalImmediatePagerDuty + Slack
Warning1 hourSlack
InfoNext business dayEmail

SLO-Based Alerting

  • Availability SLO: 99.9% uptime
  • Latency SLO: P99 < 500ms
  • Error Budget: Alert when 50% consumed in 24h

๐Ÿ“ˆ Results & Metrics

MetricAchievement
MTTRReduced from 2 hours to 15 minutes
Alert NoiseReduced false positives by 80%
Cost Savings$50k/year vs commercial APM
Log Retention30 days with 99.9% query performance
Dashboard Load< 3 seconds for complex queries

๐Ÿ”‘ Key Learnings

  1. Start with SLOs - Define SLOs first, then build alerts around them
  2. Reduce Cardinality - High cardinality labels kill Prometheus performance
  3. Retention Tiers - Different retention for different metric types
  4. Runbooks - Every alert should link to a runbook
  5. On-Call Experience - Invest in alert routing and escalation

๐Ÿ”— Resources


Need help with observability? Contact me!