summaryrefslogtreecommitdiff
path: root/f3s/tempo
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-12-28 16:29:46 +0200
committerPaul Buetow <paul@buetow.org>2025-12-28 16:29:46 +0200
commitb0abd815be8b147eacc979bb89b7300a716c4f31 (patch)
tree6530b86727ffa0e57e523786a2c9541fd8b29d64 /f3s/tempo
parent49086b43aeebfd3fdd06cd330cca8130d32e5202 (diff)
Add Grafana Tempo distributed tracing with demo application
- Deploy Grafana Tempo in monolithic mode for distributed tracing - Configure Tempo with OTLP receivers (gRPC:4317, HTTP:4318) - Set up 10Gi filesystem storage with 7-day retention - Integrate Tempo datasource in Grafana with traces-to-logs and traces-to-metrics correlation - Update Grafana Alloy to collect and forward traces - Add OTLP receiver configuration to alloy-values.yaml - Configure batch processor for efficient trace forwarding to Tempo - Patch Alloy service to expose OTLP ports 4317/4318 - Create demo tracing application (frontend, middleware, backend) - Implement three-tier Python Flask application with OpenTelemetry instrumentation - Auto-instrument with OpenTelemetry for Flask and requests libraries - Push Docker images to private registry (registry.lan.buetow.org:30001) - Deploy via Helm chart with Traefik ingress at tracing-demo.f3s.buetow.org - Update Grafana configuration in prometheus/persistence-values.yaml - Add Tempo to additionalDataSources for automatic provisioning Files added: - tempo/values.yaml: Tempo Helm chart configuration - tempo/persistent-volumes.yaml: Storage configuration (10Gi PV/PVC) - tempo/datasource-configmap.yaml: Grafana datasource with correlations - tempo/Justfile: Installation automation - tempo/README.md: Documentation - tracing-demo/docker/frontend/: Python Flask frontend with OTel - tracing-demo/docker/middleware/: Python Flask middleware with OTel - tracing-demo/docker/backend/: Python Flask backend with OTel - tracing-demo/helm-chart/: Kubernetes deployments, services, ingress - tracing-demo/docker-image-Justfile: Docker build/push automation - tracing-demo/Justfile: Helm deployment automation - tracing-demo/README.md: Documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Diffstat (limited to 'f3s/tempo')
-rw-r--r--f3s/tempo/Justfile33
-rw-r--r--f3s/tempo/README.md182
-rw-r--r--f3s/tempo/datasource-configmap.yaml47
-rw-r--r--f3s/tempo/persistent-volumes.yaml31
-rw-r--r--f3s/tempo/values.yaml76
5 files changed, 369 insertions, 0 deletions
diff --git a/f3s/tempo/Justfile b/f3s/tempo/Justfile
new file mode 100644
index 0000000..361f5c6
--- /dev/null
+++ b/f3s/tempo/Justfile
@@ -0,0 +1,33 @@
+# Grafana Tempo deployment automation
+# Following the pattern from Loki Justfile
+
+install:
+ helm repo add grafana https://grafana.github.io/helm-charts || true
+ helm repo update
+ kubectl apply -f persistent-volumes.yaml
+ helm install tempo grafana/tempo --namespace monitoring -f values.yaml
+ kubectl apply -f datasource-configmap.yaml
+
+uninstall:
+ kubectl delete -f datasource-configmap.yaml || true
+ helm uninstall tempo --namespace monitoring || true
+ kubectl delete -f persistent-volumes.yaml || true
+
+upgrade:
+ helm upgrade tempo grafana/tempo --namespace monitoring -f values.yaml
+ kubectl apply -f datasource-configmap.yaml
+
+status:
+ kubectl get pods -n monitoring -l app.kubernetes.io/name=tempo
+ kubectl get svc -n monitoring -l app.kubernetes.io/name=tempo
+ kubectl get pvc -n monitoring tempo-data-pvc
+
+logs:
+ kubectl logs -n monitoring -l app.kubernetes.io/name=tempo --tail=100 -f
+
+check:
+ @echo "Checking Tempo readiness..."
+ kubectl exec -n monitoring $(kubectl get pod -n monitoring -l app.kubernetes.io/name=tempo -o jsonpath='{.items[0].metadata.name}') -- wget -qO- http://localhost:3200/ready
+ @echo ""
+ @echo "Checking OTLP ports..."
+ kubectl exec -n monitoring $(kubectl get pod -n monitoring -l app.kubernetes.io/name=tempo -o jsonpath='{.items[0].metadata.name}') -- netstat -ln | grep -E ':(4317|4318|3200)'
diff --git a/f3s/tempo/README.md b/f3s/tempo/README.md
new file mode 100644
index 0000000..ee59311
--- /dev/null
+++ b/f3s/tempo/README.md
@@ -0,0 +1,182 @@
+# Grafana Tempo - Distributed Tracing
+
+Grafana Tempo deployment for the f3s Kubernetes cluster in monolithic mode.
+
+## Overview
+
+- **Deployment Mode**: Monolithic (all components in one process)
+- **Storage Backend**: Filesystem (local storage on hostPath)
+- **Storage Size**: 10Gi
+- **Retention**: 7 days (168h)
+- **Namespace**: `monitoring`
+
+## Components
+
+- **Tempo**: Distributed tracing backend
+- **OTLP Receivers**: Accepts traces via gRPC (4317) and HTTP (4318)
+- **Query Frontend**: Query interface on port 3200
+- **Grafana Datasource**: Auto-discovered via ConfigMap label
+
+## Architecture
+
+```
+Applications → Alloy (OTLP collector) → Tempo → Grafana
+```
+
+## Installation
+
+```bash
+just install
+```
+
+This will:
+1. Add Grafana Helm repo and update
+2. Create PersistentVolume and PersistentVolumeClaim
+3. Install Tempo via Helm
+4. Create Grafana datasource ConfigMap
+
+## Configuration
+
+### values.yaml
+
+- Monolithic mode configuration
+- OTLP receivers on ports 4317 (gRPC) and 4318 (HTTP)
+- Local filesystem storage at `/var/tempo/traces`
+- Resource limits: 2Gi memory, 1 CPU
+
+### persistent-volumes.yaml
+
+- PV: `tempo-data-pv` at `/data/nfs/k3svolumes/tempo/data`
+- PVC: `tempo-data-pvc` (10Gi, ReadWriteOnce)
+
+### datasource-configmap.yaml
+
+- Auto-discovered by Grafana sidecar
+- Enables traces-to-logs correlation with Loki
+- Enables traces-to-metrics correlation with Prometheus
+- Enables service graph visualization
+
+## Grafana Integration
+
+The datasource is automatically discovered by Grafana through the ConfigMap with label `grafana_datasource: "1"`.
+
+To access traces in Grafana:
+1. Navigate to Explore
+2. Select "Tempo" datasource
+3. Use Search or TraceQL queries
+
+### Example TraceQL Queries
+
+```
+# Find all traces from demo app
+{ resource.service.namespace = "tracing-demo" }
+
+# Find slow requests (>200ms)
+{ duration > 200ms }
+
+# Find errors
+{ status = error }
+
+# Find traces from specific service
+{ resource.service.name = "frontend" }
+```
+
+## Verification
+
+Check that Tempo is running:
+```bash
+just status
+```
+
+Check Tempo readiness and OTLP ports:
+```bash
+just check
+```
+
+View logs:
+```bash
+just logs
+```
+
+## Sending Traces
+
+Applications should send traces to Alloy's OTLP receivers:
+- gRPC: `alloy.monitoring.svc.cluster.local:4317`
+- HTTP: `alloy.monitoring.svc.cluster.local:4318`
+
+Alloy forwards traces to Tempo at `tempo.monitoring.svc.cluster.local:4317`.
+
+## Maintenance
+
+### Upgrade
+
+```bash
+just upgrade
+```
+
+### Uninstall
+
+```bash
+just uninstall
+```
+
+### Check Storage Usage
+
+```bash
+kubectl exec -n monitoring $(kubectl get pod -n monitoring -l app.kubernetes.io/name=tempo -o jsonpath='{.items[0].metadata.name}') -- df -h /var/tempo
+```
+
+## Troubleshooting
+
+### Tempo pod not starting
+
+Check events:
+```bash
+kubectl describe pod -n monitoring -l app.kubernetes.io/name=tempo
+```
+
+Check PVC binding:
+```bash
+kubectl get pvc -n monitoring tempo-data-pvc
+```
+
+### No traces appearing
+
+1. Verify Alloy is forwarding traces:
+```bash
+kubectl logs -n monitoring -l app.kubernetes.io/name=alloy | grep -i tempo
+```
+
+2. Check Tempo logs:
+```bash
+just logs
+```
+
+3. Verify OTLP receivers are listening:
+```bash
+just check
+```
+
+### Grafana datasource not appearing
+
+1. Check ConfigMap exists:
+```bash
+kubectl get cm -n monitoring tempo-grafana-datasource --show-labels
+```
+
+2. Check Grafana sidecar logs:
+```bash
+kubectl logs -n monitoring $(kubectl get pod -n monitoring -l app.kubernetes.io/name=grafana -o jsonpath='{.items[0].metadata.name}') -c grafana-sc-datasources
+```
+
+3. Restart Grafana pod if needed:
+```bash
+kubectl delete pod -n monitoring -l app.kubernetes.io/name=grafana
+```
+
+## References
+
+- [Grafana Tempo Documentation](https://grafana.com/docs/tempo/latest/)
+- [Tempo Helm Chart](https://github.com/grafana/helm-charts/tree/main/charts/tempo)
+- [OpenTelemetry Protocol (OTLP)](https://opentelemetry.io/docs/specs/otlp/)
+- [TraceQL Query Language](https://grafana.com/docs/tempo/latest/traceql/)
diff --git a/f3s/tempo/datasource-configmap.yaml b/f3s/tempo/datasource-configmap.yaml
new file mode 100644
index 0000000..00fb972
--- /dev/null
+++ b/f3s/tempo/datasource-configmap.yaml
@@ -0,0 +1,47 @@
+# Grafana Datasource ConfigMap for Tempo
+# Auto-discovered by Grafana sidecar via label grafana_datasource: "1"
+# Enables traces-to-logs and traces-to-metrics correlation
+
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: tempo-grafana-datasource
+ namespace: monitoring
+ labels:
+ grafana_datasource: "1" # Must be string "1" for auto-discovery
+data:
+ tempo-datasource.yaml: |-
+ apiVersion: 1
+ datasources:
+ - name: "Tempo"
+ type: tempo
+ uid: tempo
+ url: http://tempo.monitoring.svc.cluster.local:3200
+ access: proxy
+ isDefault: false
+ editable: true
+ jsonData:
+ httpMethod: GET
+ # Enable traces-to-logs correlation with Loki
+ tracesToLogsV2:
+ datasourceUid: 'loki'
+ spanStartTimeShift: '-1h'
+ spanEndTimeShift: '1h'
+ filterByTraceID: false
+ filterBySpanID: false
+ tags: ['cluster', 'namespace', 'pod', 'app']
+ # Enable traces-to-metrics correlation with Prometheus
+ tracesToMetrics:
+ datasourceUid: 'prometheus'
+ # Enable service graph visualization
+ serviceMap:
+ datasourceUid: 'prometheus'
+ # Enable node graph for visualization
+ nodeGraph:
+ enabled: true
+ # Enable search
+ search:
+ hide: false
+ # Enable Loki search integration
+ lokiSearch:
+ datasourceUid: 'loki'
diff --git a/f3s/tempo/persistent-volumes.yaml b/f3s/tempo/persistent-volumes.yaml
new file mode 100644
index 0000000..fc4c378
--- /dev/null
+++ b/f3s/tempo/persistent-volumes.yaml
@@ -0,0 +1,31 @@
+# Persistent Volume and Claim for Grafana Tempo trace storage
+# Following the pattern from Loki deployment
+# Storage: 10Gi at /data/nfs/k3svolumes/tempo/data
+
+apiVersion: v1
+kind: PersistentVolume
+metadata:
+ name: tempo-data-pv
+spec:
+ capacity:
+ storage: 10Gi
+ volumeMode: Filesystem
+ accessModes:
+ - ReadWriteOnce
+ persistentVolumeReclaimPolicy: Retain
+ hostPath:
+ path: /data/nfs/k3svolumes/tempo/data
+ type: DirectoryOrCreate
+---
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+ name: tempo-data-pvc
+ namespace: monitoring
+spec:
+ storageClassName: "" # Empty for manual binding to PV
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: 10Gi
diff --git a/f3s/tempo/values.yaml b/f3s/tempo/values.yaml
new file mode 100644
index 0000000..d118b63
--- /dev/null
+++ b/f3s/tempo/values.yaml
@@ -0,0 +1,76 @@
+# Grafana Tempo - Monolithic Mode Configuration
+# Following the pattern from Loki SingleBinary deployment
+
+tempo:
+ # Retention policy for traces (7 days)
+ retention: 168h
+
+ # Storage configuration - Local filesystem backend
+ # This is required for monolithic mode
+ storage:
+ trace:
+ backend: local
+ local:
+ path: /var/tempo/traces
+ wal:
+ path: /var/tempo/wal
+
+ # Distributor configuration with OTLP receivers
+ # Bind to 0.0.0.0 to avoid Tempo 2.7+ localhost-only binding issue
+ receivers:
+ otlp:
+ protocols:
+ grpc:
+ endpoint: 0.0.0.0:4317
+ http:
+ endpoint: 0.0.0.0:4318
+
+ # Query frontend configuration
+ # Enabled by default in monolithic mode
+
+# Persistence configuration using hostPath PV
+# Matches the pattern from Loki deployment
+persistence:
+ enabled: true
+ size: 10Gi
+ storageClassName: "" # Empty string for manual PV binding
+ accessModes:
+ - ReadWriteOnce
+
+# Service configuration
+# Expose OTLP ports and query endpoint
+service:
+ type: ClusterIP
+
+# Resource limits to prevent runaway resource usage
+# Adjusted for monolithic deployment
+resources:
+ limits:
+ cpu: 1000m
+ memory: 2Gi
+ requests:
+ cpu: 500m
+ memory: 1Gi
+
+# Security context following best practices
+# Using non-root user
+securityContext:
+ fsGroup: 10001
+ runAsUser: 10001
+ runAsGroup: 10001
+ runAsNonRoot: true
+
+# Disable components not needed in monolithic mode
+gateway:
+ enabled: false
+
+# Monitoring integration with Prometheus
+# Enables ServiceMonitor for automatic scraping
+serviceMonitor:
+ enabled: true
+ labels:
+ release: prometheus
+
+# Test pod disabled to reduce overhead
+test:
+ enabled: false