The Kubernetes API server writes no audit events unless you give it a policy file. A policy is an ordered list of rules, the first matching rule sets the level, and the levels range from None to RequestResponse. A sensible start is Metadata for everything, with bodies only where you need them.
Stages and levels
Each request produces events at stages: RequestReceived, ResponseStarted (only for long-running requests such as watches), ResponseComplete and Panic. Many teams omit RequestReceived to halve the volume.
The four levels, from the Kubernetes docs:
- None: do not log.
- Metadata: user, timestamp, resource, verb and similar, without request or response bodies.
- Request: metadata plus the request body.
- RequestResponse: metadata plus request and response bodies.
Request and RequestResponse do not apply to non-resource requests.
Rule order matters
Rules are checked in order and the first match wins. Put specific rules above general ones. A policy must contain at least one rule, and if you do not pass the policy file flag, no events are logged at all.
A starter policy
apiVersion: audit.k8s.io/v1
kind: Policy
omitStages:
- "RequestReceived"
rules:
- level: RequestResponse
resources:
- group: ""
resources: ["pods"]
- level: Metadata
resources:
- group: ""
resources: ["secrets", "configmaps"]
- level: Metadata
Pod changes are logged in full. Secrets and ConfigMaps are logged at Metadata, so you see who touched them without storing their contents in the log. The last rule catches everything else at Metadata. The docs example follows the same idea: because secrets match a Metadata rule, their bodies are not recorded.
Never log Secret bodies. An audit log with plain text credentials is a second place to protect.
Turning it on
Pass the policy file to the API server, and choose a backend. The log backend writes JSON lines to a file, with flags for path, retention days, backup count and rotation size. The webhook backend sends events to an external service. On managed clusters you often cannot set these flags yourself, so use the provider's audit log feature and check what level it records.
kube-apiserver --audit-policy-file=/etc/kubernetes/audit.yaml --audit-log-path=/var/log/kube-audit.log
If the API server runs as a pod, mount the policy and log locations with hostPath so records survive restarts.
What to look for
- Secrets read by one user across many namespaces.
- Creation of pods with privileged settings.
- Changes to RBAC bindings.
- Requests from system:anonymous.
Pod Security admission audit mode also writes annotations here, so the same log shows what would fail under a stricter level. See Pod Security admission rollout.
Quick check
I turned on a policy but see no events. Why?
Check that the API server flags point to the file and a backend, and that a rule matches. With no matching rule, nothing is logged.
Is RequestResponse for everything a good idea?
No. It is large and can capture sensitive bodies. Use it narrowly.
Sources
Last reviewed: 19 October 2026.