Skip to content

Observability stack: pinned charts and the rule selector

The learner deploys upstream charts for tracing, metrics, and dashboards and pins them in deploy/observability/Chart.lock. These versions are the ones the course tests against; a newer version is a dependency upgrade (craft.15, drill ops.06), never a silent drift. Versions were taken from each project’s official Helm repository index, choosing the newest release published at least two weeks before contract 0.2.0 (2026-10-09).

ChartRepositoryVersionApp versionFrom
jaegerhttps://jaegertracing.github.io/helm-charts4.14.02.21.0Pass 1 (dep.00), all-in-one
opentelemetry-collectorhttps://open-telemetry.github.io/opentelemetry-helm-charts0.173.10.160.0Pass 7 (dep.03, obs.01)
kube-prometheus-stackhttps://prometheus-community.github.io/helm-charts91.5.2v0.94.1Pass 7 (dep.03, obs.02)
tempohttps://grafana.github.io/helm-charts1.24.42.9.0Pass 7 (obs.01)
kedahttps://kedacore.github.io/charts2.21.02.21.0Pass 8 (dep.06)
ThingValue
Namespace and Helm release of the stackobservability (one release name per chart: jaeger, otel-collector, observability for kube-prometheus-stack, tempo, keda in namespace keda)
Collector Serviceotel-collector.observability, OTLP gRPC 4317, OTLP/HTTP 4318 (the [otel].endpoint of runtime.toml)
Jaeger query (Pass 1)NodePort 30686
PrometheusNodePort 30090
GrafanaNodePort 30300
Tempo query APIport 3200, NodePort 30320

kube-prometheus-stack’s Prometheus loads only the PrometheusRule objects that match its rule selector. The course leaves the chart’s default (prometheus.prometheusSpec.ruleSelectorNilUsesHelmValues: true), which selects rules labelled with the stack’s release name. So every rule file the learner renders from slo.yaml (otel/slo.schema.json) is a PrometheusRule with:

metadata:
labels:
release: observability

The same holds for ServiceMonitor objects that scrape the services’ health ports (:9464/metrics): label release: observability. A rule without the label is valid YAML and silently ignored, which is exactly the failure obs.03’s check catches.

  • Traces: every service exports OTLP to the collector, which sends them to Tempo (Pass 7 on) or Jaeger (Pass 1).
  • Service metrics: Prometheus scrapes each Go and Rust service’s health port (:9464/metrics) through a ServiceMonitor; those services do not also push metrics over OTLP, so no series exists twice.
  • Python metrics: training and corpus subprocesses cannot be scraped (D9), so they push OTLP metrics to the collector, whose prometheus exporter (scraped by its own ServiceMonitor) translates the names to the prometheus names of otel/metrics.yaml.