Skip to content

Installation

The easiest way to run the collector. The image is published to GitHub Container Registry and supports linux/amd64 and linux/arm64.

Terminal window
docker pull ghcr.io/thinkfleetai/otel-gpu-collector:latest

For per-process GPU attribution (cmdline, PID, zombie/process.state, owner), run with host PID namespace access: Docker --pid=host, Compose pid: host, or Kubernetes hostPID: true. Device-level hw.gpu.* metrics work without it.

TagDescription
latestMost recent release
1.2.3Specific version
1.2Latest patch of a minor version

Download a binary for your platform from the GitHub Releases page. Binaries are available for:

PlatformArchitecture
Linuxamd64, arm64, armv7
macOSamd64 (Intel), arm64 (Apple Silicon)
Windowsamd64, arm64
Terminal window
# Example: Linux amd64
curl -L https://github.com/ThinkfleetAI/Shield360/releases/latest/download/opentelemetry-gpu-collector-<version>-linux-amd64 \
-o opentelemetry-gpu-collector
chmod +x opentelemetry-gpu-collector
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 \
./opentelemetry-gpu-collector

Verify the SHA256 checksum from the SHA256SUMS.txt file in the release:

Terminal window
sha256sum -c SHA256SUMS.txt --ignore-missing

Requirements: Go 1.21+, CGO enabled (required for NVML on Linux).

Terminal window
git clone https://github.com/ThinkfleetAI/Shield360.git
cd shield360/opentelemetry-gpu-collector
make build
./opentelemetry-gpu-collector

For eBPF CUDA tracing support, also run:

Terminal window
make setup-bpf # installs bpftool, generates vmlinux.h
make generate # runs bpf2go code generation
make build

Run one collector per GPU node. Use the OpenTelemetry-recommended pattern: downward API → K8S_NODE_NAMEOTEL_RESOURCE_ATTRIBUTES with host.name and k8s.node.name. On GKE, AKS, and EKS the collector also auto-detects k8s.cluster.name, cloud.provider, and host.type (instance type) from the Kubernetes Node object and/or cloud metadata.

apiVersion: v1
kind: ServiceAccount
metadata:
name: otel-gpu-collector
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: otel-gpu-collector-node-get
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: otel-gpu-collector-node-get
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: otel-gpu-collector-node-get
subjects:
- kind: ServiceAccount
name: otel-gpu-collector
namespace: default # change to your namespace
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: otel-gpu-collector
spec:
selector:
matchLabels:
app: otel-gpu-collector
template:
metadata:
labels:
app: otel-gpu-collector
spec:
serviceAccountName: otel-gpu-collector
hostPID: true
containers:
- name: otel-gpu-collector
image: ghcr.io/thinkfleetai/otel-gpu-collector:latest
env:
- name: K8S_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: OTEL_SERVICE_NAME
value: otel-gpu-collector
- name: OTEL_RESOURCE_ATTRIBUTES
value: "host.name=$(K8S_NODE_NAME),k8s.node.name=$(K8S_NODE_NAME)"
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: "http://otel-collector:4317"
# Optional for on-prem / self-managed clusters:
# - name: K8S_CLUSTER_NAME
# value: my-cluster
# eBPF CUDA tracing is on by default on Linux; set false to disable:
# - name: OTEL_GPU_EBPF_ENABLED
# value: "false"
volumeMounts:
- name: pod-resources
mountPath: /var/lib/kubelet/pod-resources
readOnly: true
# AMD/Intel DRM:
# - name: dri
# mountPath: /dev/dri
securityContext:
capabilities:
add: ["SYS_ADMIN"] # or privileged / CAP_BPF+CAP_PERFMON for eBPF
volumes:
- name: pod-resources
hostPath:
path: /var/lib/kubelet/pod-resources
# - name: dri
# hostPath:
# path: /dev/dri

See Configuration for identity env vars and detection order.


Terminal window
docker pull ghcr.io/thinkfleetai/otel-gpu-collector:latest
docker stop otel-gpu-collector
docker rm otel-gpu-collector
# re-run with same flags

Download the new binary from the Releases page, replace the existing file, and restart the process.


Terminal window
docker stop otel-gpu-collector
docker rm otel-gpu-collector
docker rmi ghcr.io/thinkfleetai/otel-gpu-collector:latest
Terminal window
rm /usr/local/bin/opentelemetry-gpu-collector

No GPU metrics - collector starts but reports no hw.gpu.* metrics
  • Confirm the host has a supported GPU: lspci | grep -E 'VGA|3D|Display'
  • For NVIDIA: verify libnvidia-ml.so is present: ldconfig -p | grep nvidia-ml
  • For Docker: ensure --gpus all (NVIDIA) or --device /dev/dri (AMD/Intel) is passed
  • Check logs: docker logs otel-gpu-collector for "discovered GPU" entries
eBPF tracing not working
  • On Linux it is enabled by default; confirm it is not disabled via OTEL_GPU_EBPF_ENABLED=false
  • Check kernel version: uname -r (requires 5.8+)
  • The process needs CAP_BPF and CAP_PERFMON, or run as root
  • For Docker: --cap-add CAP_BPF --cap-add CAP_PERFMON, --pid=host, and --ulimit memlock=-1:-1 (BPF maps need locked memory; no CUDA mount needed)
  • For Kubernetes: hostPID: true plus BPF capabilities (or SYS_ADMIN); raise memlock if map create returns EPERM
  • If no CUDA process is running yet, the collector rescans /proc every 30s
  • Verify a workload has loaded CUDA: grep -E 'libcudart|libcuda.so' /proc/*/maps 2>/dev/null | head
Connection refused / no data reaching backend
  • Verify OTEL_EXPORTER_OTLP_ENDPOINT is reachable from the container: curl http://<endpoint>/health
  • For Docker networking: use the host IP or service name, not localhost
  • Check if gRPC vs HTTP/protobuf matches the backend: set OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf for HTTP backends (port 4318)
Intel GPU not detected
  • Verify the i915 or Xe driver is loaded: lsmod | grep -E 'i915|xe'
  • Check DRM entries exist: ls /sys/class/drm/
  • Requires Linux kernel 5.10+ for sysfs metric exposure
  • Fan speed requires kernel 6.16+