Add Beyla eBPF tracing DaemonSet for ringtail

Deploys a privileged Alloy DaemonSet on ringtail's k3s that
uses Beyla eBPF to auto-instrument HTTP services (Frigate,
ntfy, Ollama, Immich) without code changes. Traces are
exported via OTLP HTTP to Tempo on indri.

Separate from the existing unprivileged alloy-ringtail to
preserve least-privilege for metrics/logs collection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Erich Blume 2026-03-05 10:08:17 -08:00
commit 3512eb10b6
5 changed files with 213 additions and 0 deletions

View file

@ -0,0 +1,17 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: alloy-tracing-ringtail
namespace: argocd
spec:
project: default
source:
repoURL: ssh://forgejo@forge.ops.eblu.me:2222/eblume/blumeops.git
targetRevision: main
path: argocd/manifests/alloy-tracing-ringtail
destination:
server: https://ringtail.tail8d86e.ts.net:6443
namespace: alloy
syncPolicy:
syncOptions:
- CreateNamespace=true

View file

@ -0,0 +1,93 @@
// Alloy tracing configuration for ringtail
// Uses Beyla eBPF to auto-instrument HTTP services and export traces to Tempo on indri
// ============== BEYLA eBPF AUTO-INSTRUMENTATION ==============
beyla.ebpf "http_services" {
discovery {
// Instrument HTTP services on common ports
instrument {
open_ports = "80-9999"
}
// Exclude infrastructure pods
exclude_instrument {
kubernetes {
namespace = "kube-system"
}
}
exclude_instrument {
kubernetes {
namespace = "tailscale"
}
}
exclude_instrument {
kubernetes {
pod_labels = { app = "alloy" }
}
}
exclude_instrument {
kubernetes {
pod_labels = { app = "alloy-tracing" }
}
}
exclude_instrument {
kubernetes {
pod_labels = { app = "kube-state-metrics" }
}
}
exclude_instrument {
kubernetes {
pod_labels = { "app.kubernetes.io/name" = "nvidia-device-plugin" }
}
}
}
attributes {
kubernetes {
enable = "true"
cluster_name = "ringtail"
}
}
traces {
instrumentations = ["http"]
}
output {
traces = [otelcol.processor.batch.default.input]
}
}
// ============== OTEL TRACE PIPELINE ==============
// Batch traces before export
otelcol.processor.batch "default" {
output {
traces = [otelcol.processor.attributes.add_cluster.input]
}
}
// Add cluster label to all spans
otelcol.processor.attributes "add_cluster" {
action {
key = "cluster"
value = "ringtail"
action = "upsert"
}
output {
traces = [otelcol.exporter.otlphttp.tempo.input]
}
}
// Export traces to Tempo on indri via Tailscale
otelcol.exporter.otlphttp "tempo" {
client {
endpoint = "https://tempo-otlp.tail8d86e.ts.net"
tls {
insecure_skip_verify = true
}
}
}

View file

@ -0,0 +1,56 @@
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alloy-tracing
namespace: alloy
labels:
app: alloy-tracing
spec:
selector:
matchLabels:
app: alloy-tracing
template:
metadata:
labels:
app: alloy-tracing
spec:
serviceAccountName: alloy-tracing
hostPID: true
containers:
- name: alloy
image: grafana/alloy
args:
- run
- --server.http.listen-addr=0.0.0.0:12346
- --storage.path=/var/lib/alloy/data
- /etc/alloy/config.alloy
ports:
- containerPort: 12346
name: http
env:
- name: HOSTNAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: "1"
memory: 1Gi
volumeMounts:
- name: config
mountPath: /etc/alloy
- name: data
mountPath: /var/lib/alloy/data
securityContext:
privileged: true
tolerations:
- operator: Exists
volumes:
- name: config
configMap:
name: alloy-tracing-config
- name: data
emptyDir: {}

View file

@ -0,0 +1,17 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: alloy
resources:
- rbac.yaml
- daemonset.yaml
images:
- name: grafana/alloy
newTag: v1.13.1
configMapGenerator:
- name: alloy-tracing-config
files:
- config.alloy

View file

@ -0,0 +1,30 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: alloy-tracing
namespace: alloy
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: alloy-tracing
rules:
- apiGroups: [""]
resources: ["pods", "services", "endpoints", "nodes", "namespaces"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments", "replicasets", "statefulsets", "daemonsets"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: alloy-tracing
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: alloy-tracing
subjects:
- kind: ServiceAccount
name: alloy-tracing
namespace: alloy