On this page
Profiling
Profiling PAC Components
Pipelines-as-Code components embed the Knative runtime profiling server,
which exposes Go runtime profiling data via the standard net/http/pprof endpoints.
This is useful for diagnosing CPU hot-spots, memory growth, goroutine leaks, and
other performance issues.
How It Works
Each PAC component starts an HTTP server on port 8008 (the default Knative profiling
port, overridable with the PROFILING_PORT environment variable). When profiling is
enabled the following endpoints are active:
| Endpoint | Description |
|---|---|
/debug/pprof/ |
Index of all available profiles |
/debug/pprof/heap |
Heap memory allocations |
/debug/pprof/goroutine |
All current goroutines |
/debug/pprof/profile |
30-second CPU profile |
/debug/pprof/trace |
Execution trace |
/debug/pprof/cmdline |
Process command line |
/debug/pprof/symbol |
Symbol lookup |
When profiling is disabled the server still listens but returns 404 for every request.
Enabling Profiling
All components read profiling configuration from the same ConfigMap:
# Enable
kubectl patch configmap pipelines-as-code-config-observability \
-n pipelines-as-code \
--type merge \
-p '{"data":{"runtime-profiling":"enabled"}}'
# Disable
kubectl patch configmap pipelines-as-code-config-observability \
-n pipelines-as-code \
--type merge \
-p '{"data":{"runtime-profiling":"disabled"}}'profiling.enable: "true" key no longer works. Use
runtime-profiling: "enabled" instead.Component-specific prerequisites
The controller reads profiling configuration from the config-observability ConfigMap
at startup. Unlike the watcher and webhook (which use the sharedmain framework), the
controller’s eventing adapter does not register a dynamic callback for profiling changes,
so a pod restart is required after enabling or disabling profiling:
kubectl rollout restart deployment/pipelines-as-code-controller \
-n pipelines-as-codeThe watcher needs PAC_DISABLE_HEALTH_PROBE=true, otherwise a port conflict on
8080 causes the profiling server to shut down. The watcher picks up ConfigMap changes
without a restart.
kubectl set env deployment/pipelines-as-code-watcher \
-n pipelines-as-code \
PAC_DISABLE_HEALTH_PROBE=trueThe webhook needs CONFIG_OBSERVABILITY_NAME set explicitly. Without it, the webhook
looks for a ConfigMap called config-observability, which does not exist in the PAC
namespace. The webhook picks up ConfigMap changes without a restart.
kubectl set env deployment/pipelines-as-code-webhook \
-n pipelines-as-code \
CONFIG_OBSERVABILITY_NAME=pipelines-as-code-config-observabilityAccessing Profiles
The profiling server listens on port 8008 by default. If that conflicts with another
service, set PROFILING_PORT on the relevant Deployment(s):
kubectl set env deployment/pipelines-as-code-watcher \
deployment/pipelines-as-code-controller \
deployment/pipelines-as-code-webhook \
-n pipelines-as-code \
PROFILING_PORT=8090Port 8008 (or your chosen port) is not declared in the container spec by default, so you need to patch the target Deployment(s) to expose it:
PROFILING_PORT="${PROFILING_PORT:-8008}"
for deploy in pipelines-as-code-watcher pipelines-as-code-controller pipelines-as-code-webhook; do
kubectl patch deployment "$deploy" \
-n pipelines-as-code \
--type json \
-p "[{\"op\":\"add\",\"path\":\"/spec/template/spec/containers/0/ports/-\",\"value\":{\"name\":\"profiling\",\"containerPort\":${PROFILING_PORT},\"protocol\":\"TCP\"}}]"
doneThis triggers a rolling restart. Once the pod is running you can access the pprof endpoints.
Using kubectl port-forward
The simplest way to reach the profiling server is kubectl port-forward. This forwards
a local port to the pod without exposing it to the cluster network.
First, grab the pod name for the component you want to profile:
# Watcher
export POD_NAME=$(kubectl get pods -n pipelines-as-code \
-l app.kubernetes.io/name=watcher \
-o jsonpath='{.items[0].metadata.name}')
# Controller
export POD_NAME=$(kubectl get pods -n pipelines-as-code \
-l app.kubernetes.io/name=controller \
-o jsonpath='{.items[0].metadata.name}')
# Webhook
export POD_NAME=$(kubectl get pods -n pipelines-as-code \
-l app.kubernetes.io/name=webhook \
-o jsonpath='{.items[0].metadata.name}')Then forward the port:
PROFILING_PORT="${PROFILING_PORT:-8008}"
kubectl port-forward -n pipelines-as-code $POD_NAME ${PROFILING_PORT}:${PROFILING_PORT}The pprof index is now at http://localhost:${PROFILING_PORT}/debug/pprof/.
Capturing profiles with go tool pprof
With kubectl port-forward running, you can analyze profiles directly:
# Heap profile
go tool pprof http://localhost:${PROFILING_PORT}/debug/pprof/heap
# 30-second CPU profile
go tool pprof http://localhost:${PROFILING_PORT}/debug/pprof/profile
# Goroutine dump
go tool pprof http://localhost:${PROFILING_PORT}/debug/pprof/goroutineSaving profiles to disk
You can save profiles for later analysis with curl:
# Save a heap profile
curl -o heap-$(date +%Y%m%d-%H%M%S).pb.gz \
http://localhost:${PROFILING_PORT}/debug/pprof/heap
# Analyze later
go tool pprof heap-<timestamp>.pb.gz
# Or open the interactive web UI (starts a browser at http://localhost:8009)
go tool pprof -http=:8009 heap-<timestamp>.pb.gzSecurity Considerations
The profiling server exposes internal runtime data. Because the profiling port is not
declared in the container spec by default, access requires an explicit Deployment patch,
limiting it to users with deployments/patch permission in the pipelines-as-code
namespace.
Do not expose the profiling port via a Service or Ingress in production. Disable
profiling (runtime-profiling: "disabled") when you are not actively investigating
an issue.