Repository navigation
feat(observability): deploy Tempo as the permanent trace backend - #2072
Conversation
The verdict adopts Tempo, but the ADR keeps adoption a separate, owner-approved change. This plan lays out its shape and the order it must take relative to the teardown, which CI forces by 2026-10-24, so the owner can approve or change each decision before any manifest is written. Refs #1280
The #1280 verdict (ADR 0001) adopted Tempo, mctl-native only, as a separate deployment rather than the sandbox promoted in place. The owner approved the plan on 2026-10-22 (Option A, teardown first; #2073 merged). Tempo 2.10.8 (chart 2.4.0) runs in its own `tracing` namespace, reuses the tempo-traces R2 bucket, keeps 336h and is read-bounded (api_timeout, querier and frontend concurrency) after the soak's unranged read pinned the pod. root-app renders only the Namespace and the Application; all namespaced objects come from the Application's manifestsPath, which avoids the project/namespace sync deadlock of gitops#1925. The collector exports to it over otlp/backend; Grafana gets datasource "Tempo" (uid tempo) and deletes the read-only "Tempo (eval)" leftover via provisioning, since the API refuses. Only the DevLoop workers and admins-mctl-agent export. The emptyDir WAL is an owner-accepted standing risk. The unexplained partial trace-by-id read (5,092 of 6,930 spans) is a documented limitation: no completeness claims or counts from Tempo until explained (docs/runbooks/tempo.md).
|
Claude finished @mashkovd's task in 4m 57s —— View job Review of PR #2072 — Tempo permanent trace backend
Note: Summary: this is a large, carefully-scoped change, and it reads as correct. Highlights verified:
No P1 or P2 findings. No inline comments posted.
|
Antigravity (agy) review — informationalModel: gemini-3.8-flash-high · commit No significant issues found. |
… template CI caught two consequences of the new namespace: tenant creation and deletion must refuse a tenant named `tracing` (every literal platform namespace is on the denylist), and tracing.yaml leads with a template directive, which yamllint cannot parse, like the other gated templates.
|
Claude finished @mashkovd's task in 1m 56s —— View job Review of PR #2072 — commit
|
There was a problem hiding this comment.
No P1/P2/P3 findings. This sync's delta vs. feb91c5 (already reviewed/approved) is a small, consistent fix: adds tracing to the reserved-tenant-name exact-match group in both wft-create-tenant.yaml and wft-delete-tenant-safe.yaml (both occurrences, matching the namespace tracing.yaml creates), adds tracing.yaml to the yamllint template-comment ignore list with an accurate rationale (verified the file does lead with {{- /* ... */}}), and extends test_wft_create_tenant_existing.py's MUST_REJECT list to cover it. Verified consistent across all four touched files; rest of the diff is unchanged from the prior full review.
Antigravity (agy) review — informationalModel: gemini-3.8-flash-high · commit No significant issues found. |
Adopts Tempo as the permanent trace backend: the #1280 verdict (ADR 0001, ADOPT TEMPO / mctl-native only), deployed as a separate permanent deployment, not the bake-off sandbox promoted in place. Plan:
docs/plans/tempo-adoption.md. Runbook:docs/runbooks/tempo.md.Refs #1280. The teardown (#2073) merged first (Option A).
Owner approval (2026-10-22)
Known limitation: partial reads
In the soak a bounded trace-by-id over all 139 traces returned 5,092 of 6,930 in-window spans, while ingest counters agree to the span. It is unexplained. Until it is: no promise of complete trace/span enumeration, and Tempo is not used for completeness-critical counts (count ingest with collector / distributor counters instead). Recorded in the runbook §1, the values comment and the datasource template.
What changes
tracingnamespace + Applicationtracing-tempo(bootstrap/templates/observability/tracing.yaml): charttempo2.4.0, Tempo 2.10.8, reuses R2 buckettempo-traces(ExternalSecrettempo-r2from Vaultplatform/r2-tempo), retention 336h, 1 replica, no PVC (WAL on a 2Gi emptyDir: accepted standing risk), limits 2 CPU / 2Gi,GOMEMLIMIT=1600MiB.query_frontend.api_timeout: 1m(default is none),max_outstanding_per_tenant: 100,trace_by_id.concurrent_shards: 4,querier.max_concurrent_queries: 4. Keys checked against Tempo v2.10.8 source.argocd. Every namespaced object intracing(default-deny + allow NetworkPolicies, ResourceQuota refusing PVCs, LimitRange, ExternalSecret, VMServiceScrape) lives in the Application's manifestsPathinfra-components/observability/tracing/tempo/with negative sync waves.tracingand the chart repo are derived into AppProjectdefault.otlp/backend→tempo.tracing.svc.cluster.local:4317, with a new opt-inotelCollector.backendInsecure(Tempo's receiver is plaintext in-cluster).tempo, sametracesToLogsV2; provisioningdeleteDatasourcesremoves the leftover "Tempo (eval)" (the API refuses read-only datasources, so this is the §10 cleanup of chore(observability): tear down the #1280 Tempo eval sandbox #2073). Loki'strace_idlink now points attempo.TempoEval*→Tempo*(vm-rules/tempo-alerts.yaml, namespacetracing, exporterotlp(_grpc)?/backend), Telegram routeTempo.*. promtool tests pass.admins-mctl-agentgetotel.enabled: true.docs/runbooks/tempo.md; bake-off runbook marked closed and §9 corrected (datasource removal via provisioning); plan status → approved.Tests
tests/test_otel_collector_backends_render.py: eval-machinery checks now render with the permanent backend off (golden unchanged); new "Committed default" section asserts the shipped render:otlp/backendendpoint + TLS, nothing else added to the collector, Namespace/Application/project, no namespaced root-app resource intracing, manifests (default-deny, PVC-refusing quota, negative waves), chart pin and values, datasource identity +deleteDatasources, Loki link. Mutation-checked (wrong port, wrong delete name → FAIL).validate-argocd-project-scope.py --selftest --strict default(both renders),validate-eval-teardown-date.py, kubeconform,test_adr_rubric_frozen,test_otel_collector_alert_windows,test_base_service_otel_env: pass locally. Tempo chart rendered with these values.After merge
Live verification:
tracing-tempoSynced/Healthy,tempo-0Running,tempo-r2Ready, collector config hasotlp/backend, producers carryOTEL_*, spans arrive, Grafana lists "Tempo" and no "Tempo (eval)". If root-app does deadlock anyway, selective sync of the project needs owner OK.🤖 Generated with Claude Code