Skip to main content
Docs / Troubleshooting

Troubleshooting

Common issues and how to diagnose them.

Most issues fall into four buckets: a workload is not being watched, a sensor is refusing to start, a sensor is running but producing more alerts than you expect, or a pod was contained and you need to know why. Each section starts with how to diagnose, then lists the usual causes.

Start here
# One sensor per node, all Ready?
kubectl get pods -n pando-system -l app.kubernetes.io/name=pando-node-sensor -o wide

# What does the sensor on this node think it is doing?
kubectl exec -n pando-system <sensor-pod> -- wget -qO- http://localhost:9090/status

/status reports the engine count, the license ceiling and any node clamp. It answers most of the questions below in one call.

A Workload Is Not Being Watched

Symptom: a pod is running, but it never appears in detections and no engine was started for it.

# Is there a sensor on that pod's node at all?
kubectl get pods -n pando-system -o wide \
  -l app.kubernetes.io/name=pando-node-sensor | grep <node>

# How many engines is that node's sensor running, and is it shedding?
kubectl exec -n pando-system <sensor-pod> -- wget -qO- http://localhost:9090/status

# Is the pod opted out?
kubectl get pod <pod> -o jsonpath='{.metadata.labels}'

Common causes

A Sensor Is Refusing Or Crash-Looping

Symptom: the sensor pod is running but /readyz returns 503 indefinitely, or the pod is in CrashLoopBackOff.

# Current and previous logs
kubectl logs -n pando-system <sensor-pod>
kubectl logs -n pando-system <sensor-pod> --previous

# Events and exit codes
kubectl describe pod -n pando-system <sensor-pod>
A refusal is not a crash, and /healthz will still say 200

When the sensor refuses to monitor it parks rather than exiting, and /healthz deliberately keeps returning 200 so the kubelet does not crash-loop the refusal logs away before you can read them. /readyz is the endpoint that reports it. A pod that looks healthy in kubectl get pods can be refusing, so check readiness rather than phase.

A refusal names one of eight reasons, which is also the label on the refusal metric: config, licence, siem, node_name, state_dir, cluster_limit, revoked or channel. A refusal is a configuration error and will not clear on its own.

The controller client certificate is mandatory

The sensor mounts the controller's client certificate Secret with optional: false, so a missing Secret fails the pod rather than starting a sensor whose evidence has nowhere to go. If the pod will not start at all and the events mention a missing Secret, that is this.

Memory or CPU pressure

The sensor requests 250m CPU and 256Mi per node, and is limited to 2 cores and 1Gi. If you have shortened the sampling cadence, raise the request to match: at the 250 ms floor the same build costs roughly four times as much CPU as at the 1000 ms default, and CPU is shared by request under contention.

helm upgrade pando-node-sensor ... \
  --set resources.requests.cpu=500m \
  --set resources.limits.memory=1Gi

Too Many Alerts

Symptom: detections firing on normal workload behaviour during batch jobs, traffic bursts or other legitimate variance.

First, confirm the workload finished learning. A profile takes 30 minutes and at least 900 samples, whichever is later, and detections before that are not meaningful. Behavioural checks that rest on longer baselines keep warming for hours beyond it, so a workload that has been watched for forty minutes is not yet fully calibrated.

kubectl exec -n pando-system <sensor-pod> -- wget -qO- http://localhost:9090/readyz

Tuning options, in order of preference

  1. Loosen sensitivity in a PandoCorePolicy for that namespace. low, medium or high, where a higher preset is a tighter gate. This is the right lever because it is per-namespace and version-controlled. See CRD Policy.
    kubectl patch pandocorepolicy default -n production \
      --type merge -p '{"spec":{"sensitivity":"low"}}'
  2. Put the workload in monitor. It keeps being watched and keeps producing evidence, and stops alerting, which is the right move while you calibrate rather than switching anything off.
    kubectl annotate deployment your-app pandocore.io/mode=monitor --overwrite
    kubectl rollout restart deployment/your-app
  3. Restart the workload to re-profile it. If its traffic pattern genuinely changed, the old profile no longer describes normal. There is no re-learn endpoint on the sensor; a workload re-profiles when its pods restart.
  4. Contact support. If the preset and a re-profile do not settle it, reach out. We would rather debug it with you.
Sensitivity is not a per-workload environment variable any more

PANDO_SENSITIVITY still exists, but on the node sensor it belongs to the DaemonSet, so it applies node-wide rather than to one workload. Use a PandoCorePolicy for per-namespace tuning, and thresholds within it for finer numeric control. Thresholds can only tighten what learning derived, never loosen it; use sensitivity to loosen.

Sensor Running But No Data

Symptom: the sensor is ready, but /metrics looks empty or the portal dashboard shows no activity.

# Metrics directly off the sensor
kubectl exec -n pando-system <sensor-pod> -- wget -qO- http://localhost:9090/metrics

# Is the controller receiving anything?
kubectl logs -n pando-system -l app.kubernetes.io/name=pando-controller --tail=100

A Pod Was Contained Unexpectedly

Symptom: a workload lost network egress and you need to understand why.

Containment is a Kubernetes NetworkPolicy, so it is visible and reversible with ordinary tooling:

# The policy PandoCore wrote
kubectl get networkpolicy -n <namespace>

# The detection that caused it
kubectl get events -n <namespace> --field-selector involvedObject.name=<pod>
  1. Read the evidence record in the portal's Events tab for the detection reason and severity.
  2. Check the workload's mode. If you expected it only to alert, confirm with kubectl get deployment your-app -o jsonpath='{.spec.template.metadata.annotations}'. Remember the annotation is read when the sensor starts watching a pod, so a recent change may not have applied to pods already running.
  3. If the behaviour subsides, the policy is removed automatically. You do not need to delete it by hand, and deleting it does not resolve the underlying detection.

If it was clearly a false positive, see Too Many Alerts above. To stop PandoCore responding immediately while you investigate, see Emergency Procedures.

Getting Help

Collect the following before reaching out:

Send to support or reply to your onboarding email thread.