πŸ“šBook Signing at KubeCon EU 2026Meet us at Booking.com HQ (Mon 18:30-21:00) & vCluster booth #521 (Tue 24 Mar, 12:30-1:30pm) β€” free book giveaway!RSVP Booking.com Event
Observability intermediate ⏱ 20 minutes K8s 1.28+

Continuous Profiling with Pyroscope

Deploy Pyroscope on Kubernetes for continuous CPU and memory profiling. Identify performance bottlenecks in production without overhead.

By Luca Berton β€’ β€’ πŸ“– 5 min read

πŸ’‘ Quick Answer: Deploy Pyroscope (now part of Grafana) via Helm with helm install pyroscope grafana/pyroscope. Instrument apps with the Pyroscope SDK or use eBPF-based auto-instrumentation for zero-code profiling. View flame graphs in Grafana to identify hot functions consuming CPU or memory.

The Problem

Your application is slow in production but fine in development. Traditional APM shows high latency but not which function causes it. You need always-on profiling that doesn’t impact production performance.

The Solution

Install Pyroscope

helm repo add grafana https://grafana.github.io/helm-charts
helm repo update

helm install pyroscope grafana/pyroscope \
  --namespace observability \
  --create-namespace \
  --set pyroscope.replicaCount=2 \
  --set pyroscope.persistence.enabled=true \
  --set pyroscope.persistence.size=50Gi

eBPF Auto-Discovery (Zero Code Changes)

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: pyroscope-ebpf
  namespace: observability
spec:
  selector:
    matchLabels:
      app: pyroscope-ebpf
  template:
    metadata:
      labels:
        app: pyroscope-ebpf
    spec:
      hostPID: true
      containers:
        - name: agent
          image: grafana/pyroscope:1.7
          args:
            - ebpf
            - connect
            - --server-address=http://pyroscope:4040
          securityContext:
            privileged: true
          volumeMounts:
            - name: sys
              mountPath: /sys
              readOnly: true
      volumes:
        - name: sys
          hostPath:
            path: /sys

SDK Instrumentation (Go Example)

import "github.com/grafana/pyroscope-go"

func main() {
    pyroscope.Start(pyroscope.Config{
        ApplicationName: "my-app",
        ServerAddress:   "http://pyroscope.observability:4040",
        ProfileTypes: []pyroscope.ProfileType{
            pyroscope.ProfileCPU,
            pyroscope.ProfileAllocObjects,
            pyroscope.ProfileAllocSpace,
            pyroscope.ProfileInuseObjects,
            pyroscope.ProfileInuseSpace,
            pyroscope.ProfileGoroutines,
            pyroscope.ProfileMutexCount,
            pyroscope.ProfileMutexDuration,
            pyroscope.ProfileBlockCount,
            pyroscope.ProfileBlockDuration,
        },
        Tags: map[string]string{
            "namespace": os.Getenv("POD_NAMESPACE"),
            "pod":       os.Getenv("POD_NAME"),
        },
    })
    // ... rest of application
}

Grafana Data Source

apiVersion: v1
kind: ConfigMap
metadata:
  name: grafana-datasources
  namespace: observability
data:
  pyroscope.yaml: |
    apiVersion: 1
    datasources:
      - name: Pyroscope
        type: grafana-pyroscope-datasource
        url: http://pyroscope:4040
        access: proxy
        isDefault: false

Querying Profiles

# List available applications
curl http://pyroscope:4040/api/apps

# Query CPU profile for last hour
curl "http://pyroscope:4040/render?query=my-app.cpu&from=now-1h&until=now&format=json"

Common Issues

IssueCauseFix
No profiles appearingApp not instrumentedAdd SDK or deploy eBPF agent
High storage usageAll profiles stored indefinitelySet retention: --storage.retention=7d
eBPF not workingKernel too oldRequires Linux 4.9+ (5.x recommended)
Missing symbolsStripped binariesBuild with -gcflags=-N -l or keep debug info

Best Practices

  1. Start with eBPF β€” Zero code changes, works for any language
  2. Use SDK for detailed profiling β€” Goroutine, mutex, block profiles need SDK
  3. Set retention policies β€” 7-14 days is typical for production
  4. Tag by namespace/pod β€” Essential for filtering in multi-tenant clusters
  5. Correlate with traces β€” Link Pyroscope profiles to distributed traces via exemplars

Key Takeaways

  • Continuous profiling identifies which functions consume CPU/memory in production
  • eBPF-based profiling requires zero code changes but needs privileged access
  • SDK instrumentation provides richer profile types (goroutines, mutexes)
  • Pyroscope integrates natively with Grafana for flame graph visualization
  • Overhead is typically <1% CPU for profiled applications
#profiling #pyroscope #performance #observability #grafana
Luca Berton
Written by Luca Berton

Principal Solutions Architect specializing in Kubernetes, AI/GPU infrastructure, and cloud-native platforms. Author of Kubernetes Recipes and creator of CopyPasteLearn courses.

Kubernetes Recipes book cover

Want More Kubernetes Recipes?

This recipe is from Kubernetes Recipes, our 750-page practical guide with hundreds of production-ready patterns.

Luca Berton Ansible Pilot Ansible by Example Open Empower K8s Recipes Terraform Pilot CopyPasteLearn ProteinLens