CRD-Based Policy

Manage PandoCore configuration declaratively with Kubernetes custom resources.

Docs / CRD Policy

CRD-Based Policy

Instead of scattering environment variables across deployments, define a single PandoCorePolicy custom resource per namespace and apply it with kubectl. Policy values override environment variables automatically.

Three-Step Setup
  1. Create a pando-policy.yaml file
  2. Run kubectl apply -f pando-policy.yaml
  3. Done. Sidecars pick up the policy within 30 seconds.

Quick Start

Create a file called pando-policy.yaml:

apiVersion: pandocore.io/v1alpha1
kind: PandoCorePolicy
metadata:
  name: default
  namespace: production
spec:
  mode: enforce
  sensitivity: high

Apply it:

kubectl apply -f pando-policy.yaml

Verify:

kubectl get pcp -n production

NAME      MODE      SENSITIVITY   AGE
default   enforce   high          5s

Full Policy Reference

Every field is optional. The sidecar falls back to environment variables (or built-in defaults) for any field not specified.

apiVersion: pandocore.io/v1alpha1
kind: PandoCorePolicy
metadata:
  name: default            # must be "default", one policy per namespace
  namespace: production
spec:
  # Operating mode (modes layer additively — each does everything the prior mode does)
  mode: enforce            # monitor | alert | isolate | enforce | debug

  # Sensitivity (higher = more permissive)
  sensitivity: medium      # low | medium | high

  # Graduated response chain
  response:
    actions:
      - alert
      - isolate
      - terminate
    escalationDelaySec: 60

  # Alert integrations
  integrations:
    slack: "https://hooks.slack.com/services/T.../B.../xxx"
    pagerduty: "<routing-key>"

  # Exclusions (applied at webhook level)
  exclude:
    namespaces:
      - kube-system
      - monitoring
    labels:
      pandocore.io/skip: "true"

Precedence

PandoCore uses a layered configuration model:

Priority Source Description
1 (highest) CRD Policy Values in PandoCorePolicy win
2 Environment Variables Fallback when no CRD field is set
3 (lowest) Built-in Defaults Hardcoded sane defaults

If the CRD is deleted, the sidecar reverts to env-var-based configuration on the next poll cycle.

Spec Fields

mode

Value Description
monitor Detect and log only. No alerts, no network action, no termination.
alert Everything in monitor, plus Slack / portal alerts on trip.
isolate Everything in alert, plus a NetworkPolicy that blocks pod egress (except DNS) on trip. No pod termination. Policy is removed automatically once drift subsides.
enforce Full response chain: alert → NetworkPolicy → escalation timer → pod terminate if drift persists past the escalation window.
debug Verbose logging for troubleshooting. No response actions.

sensitivity

Value Description
low Strictest. Catches subtler deviations. Use after a workload has been running cleanly for weeks.
medium Default. Balanced for typical production workloads.
high Most permissive. Good starting point for chatty workloads (JVMs, databases, batch jobs).

For finer numeric control on individual workloads, use the PANDO_SENSITIVITY environment variable (see Configuration).

response

Field Type Description
actions array of strings Ordered response chain: alert, isolate, terminate
escalationDelaySec integer (0–3600) Seconds after isolation before escalating to terminate

integrations

Field Type Description
slack string Slack incoming webhook URL
pagerduty string PagerDuty routing key

Examples

Production Namespace

apiVersion: pandocore.io/v1alpha1
kind: PandoCorePolicy
metadata:
  name: default
  namespace: production
spec:
  mode: enforce
  sensitivity: medium
  response:
    actions: [alert, isolate, terminate]
    escalationDelaySec: 60
  integrations:
    slack: "https://hooks.slack.com/services/T.../B.../xxx"

Staging Namespace (Monitor Only)

apiVersion: pandocore.io/v1alpha1
kind: PandoCorePolicy
metadata:
  name: default
  namespace: staging
spec:
  mode: monitor
  sensitivity: high

Verifying

Check that the CRD is registered:

kubectl get crd pandocorepolicies.pandocore.io

List policies across namespaces:

kubectl get pcp --all-namespaces

Check sidecar logs for policy pickup:

kubectl logs <pod> -c pando-sidecar | grep "PandoCorePolicy"

Expected output:

PandoCorePolicy CRD found  namespace=production name=default
Applied PandoCorePolicy  mode=enforce resource_version="12345"
Advanced fields

The CRD accepts additional fields for specialized deployments (fine-grained threshold overrides, feature toggles, workload-specific tuning). These are intentionally not documented here. The fields above cover every workload we've seen in production. If you need more, talk to support.

Polling Interval

The sidecar polls for policy changes every 30 seconds by default. To customize, set PANDO_POLICY_POLL_INTERVAL_SECS on the sidecar container.

GitOps Integration

Because PandoCorePolicy is a standard Kubernetes resource, it integrates naturally with GitOps workflows:

Next Steps