Server dry run catches policy errors. Client dry run only prints the object that would be sent, so admission controllers never see it. Server dry run submits the request to the API server, which runs it through admission and validation, then stops before saving anything. Use it in CI to test policy before a real rollout.
The two modes
The kubectl apply reference describes the dry run option with three values: none, server and client. With the client strategy, kubectl only prints the object that would be sent, without sending it. With the server strategy, it submits a server side request without persisting the resource.
The Kubernetes API documentation explains what the server mode does. Dry run evaluates a request through the typical request stages, including the admission chain, validation and merge conflicts, up until persisting objects to storage. It guarantees that dry run requests will not be persisted or have other side effects. The response is as close as possible to a real one.
Which catches what
| Problem | Client dry run | Server dry run |
|---|---|---|
| Malformed YAML | Often yes | Yes |
| Unknown field or wrong type | Depends on validation settings | Yes |
| Rejected by validating admission policy | No | Yes |
| Changed by a mutating webhook | No | Yes, shown in the response |
| Conflicts with existing object | No | Yes |
| Needs cluster access | No | Yes |
The key row is admission. Policy tools that run as admission controllers only act when the API server receives a request. A client dry run never reaches them.
Using it in CI
- Give the pipeline a service account that can create the objects in a test or staging namespace, or a dedicated read mostly role for dry runs.
- Run
kubectl apply --dry-run=server -f rendered.yaml. - Fail the job on any error and print the admission message, which usually names the policy.
- Follow with
kubectl diffto see what would change on the live object.
The role used for dry runs still needs permission for the verbs involved, so scope it to namespaces you intend to test in.
Common surprises
- A passing client dry run does not mean the cluster will accept the manifest.
- Server dry run only reflects the policies on that cluster. A staging cluster with weaker policy gives false comfort.
- Mutating webhooks may change the object. Look at the returned manifest, not just the exit code.
Try it yourself
Click through it at your own pace, or open it full screen.
Watch where a failing check blocks the change in the demo. A server dry run is the cluster side version of the same gate.
Quick check
Does server dry run change anything in the cluster?
No. Kubernetes states that dry run requests are not persisted and have no other side effects.
Can I use client dry run to test admission policy?
No. It does not send the request to the API server.
Safeguard runs policies and gates on pull requests, so a failed rule can hold a merge, and its dependency and SBOM scanning covers the packages your infrastructure code pulls in. You can try a free scan at gold.safeguard.sh/scan.
Sources
- kubectl apply reference, Kubernetes documentation
- Kubernetes API concepts, dry run, Kubernetes documentation
Last reviewed: 19 October 2026.