KubernetesLXXIX · API DeprecationAPI deprecation
--dry-run=server for manifest review — server-side validation
What you'll learn
- Use kubectl --dry-run=server to validate manifests
- Identify server-side deprecated API warnings
- Integrate --dry-run=server with CI/CD
- Distinguish --dry-run=client, --dry-run=server, and live apply
Prerequisites
Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16
kubectl --dry-run=server is the canonical pre-flight
check for manifest review. It validates a manifest against
the live apiserver without persisting the change. The
mode is the cluster-side analog of kubectl apply. This
lesson walks the mode, the warnings, and the CI/CD
integration.
The three dry-run modes
kubectl supports three dry-run modes:
kubectl apply -f manifest.yaml --dry-run=client
kubectl apply -f manifest.yaml --dry-run=server
kubectl apply -f manifest.yaml
The modes:
--dry-run=client: The client validates the manifest (schema, parser) but does not contact the apiserver.--dry-run=server: The client sends the manifest to the apiserver; the apiserver validates the manifest (schema, admission chain); the apiserver does not persist the change.- No flag: The client sends the manifest; the apiserver validates and persists.
flowchart LR
A[manifest.yaml] --> B[kubectl apply]
B --> C{dry-run mode?}
C -->|client| D[Client validation only]
C -->|server| E[Server validation]
E --> F[No persistence]
C -->|none| G[Server validation]
G --> H[Persist]
The server-side validation
kubectl apply -f manifest.yaml --dry-run=server
deployment.apps/my-app created (server dry run)
The manifest is sent to the apiserver; the apiserver validates and returns the result. The cluster’s state is unchanged.
For a deprecated API:
# manifest.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress
kubectl apply -f manifest.yaml --dry-run=server
Warning: extensions/v1beta1 Ingress is deprecated, use networking.k8s.io/v1 Ingress
ingress.extensions/my-ingress created (server dry run)
The warning is server-side; the apiserver is the source of the deprecation message.
The full admission chain
--dry-run=server exercises the full admission chain:
- Authentication. The kubectl client authenticates to the apiserver.
- Authorization (RBAC). The apiserver checks the client’s verb permissions.
- MutatingAdmissionWebhook. The mutating webhooks fire.
- ValidatingAdmissionWebhook. The validating webhooks fire.
- Built-in admission. PodSecurity, ResourceQuota, LimitRange, etc.
- Schema validation. The manifest’s schema is validated against the API.
The result is the same as a live apply, except the manifest is not persisted.
sequenceDiagram
participant K as kubectl
participant AS as apiserver
participant W as Webhooks
participant R as Built-in admission
K->>AS: Apply (dry-run=server)
AS->>AS: Authentication
AS->>AS: RBAC
AS->>W: Mutating webhooks
AS->>W: Validating webhooks
AS->>R: Built-in admission
AS->>AS: Schema validation
AS-->>K: Result (no persistence)
The side-by-side comparison
# Client-side validation only
kubectl apply -f manifest.yaml --dry-run=client
# Server-side validation
kubectl apply -f manifest.yaml --dry-run=server
# Live apply
kubectl apply -f manifest.yaml
The differences:
| Mode | Validation | Admission | Persistence |
|---|---|---|---|
| client | Client schema | None | No |
| server | Server schema | Full | No |
| live | Server schema | Full | Yes |
The CI/CD integration
# .github/workflows/k8s-validate.yml
- name: Server-side validate
run: |
kubectl apply -f manifests/ --dry-run=server --validate=true
The CI/CD pipeline validates every manifest against the live apiserver. The pipeline fails if:
- The manifest has a deprecated API.
- The manifest has a removed API.
- The manifest violates an admission policy.
- The manifest has a schema error.
flowchart LR
A[PR] --> B[kubectl apply --dry-run=server]
B --> C[Validation result]
C --> D[PR passes]
C --> E[PR fails]
E --> F[Block merge]
The validate flag
kubectl apply -f manifest.yaml --dry-run=server --validate=true
The --validate=true flag ensures schema validation
(client-side schema check). The flag is the default.
kubectl apply -f manifest.yaml --dry-run=server --validate=false
The --validate=false flag skips client-side validation.
The server-side validation still applies.
The application into the cluster
After the dry-run validation passes:
kubectl apply -f manifest.yaml
The manifest is applied. The cluster state is updated.
Cross-course references
- The CI/CD course covers pipeline integration patterns.
- The Linux course covers JSON schema validation.
- The Helm course covers chart template validation.
Quiz
Knowledge check · 4 questions
Q1. Which --dry-run mode exercises the full admission chain without persisting the change?
Q2. kubectl --dry-run=server emits warnings for deprecated APIs.
Q3. Walk the --dry-run=server validation of a manifest.
Manifest with a deployment using `extensions/v1beta1` Ingress. The team is preparing to apply the manifest to a 1.34.x cluster.
Q4. What is the difference between --dry-run=client and --dry-run=server?
Passing score: 75%. Answers are checked in this browser.
Production discipline
- Use —dry-run=server for production manifests. The server-side validation is the source of truth.
- Run —dry-run=server in CI/CD. The pipeline fails on warnings.
- Address warnings before applying. Deprecation warnings are signals to update.
- Use —validate=true with —dry-run=server. Client-side schema validation is the first check.
- Document the dry-run in the runbook. The validation, the result, the action.
The dry-run is the canonical pre-flight check. Operating it well is using it in CI/CD and acting on the warnings.