kubectl diff
Diff the live cluster state against the configuration that would be applied. A dry-run comparison tool for safe deployments.
kubectl diff -f FILENAME [flags]Common Flags
| Flag | Short | Description |
|---|---|---|
| -f | --filename | Filename, directory, or URL containing the configuration to diff |
| -R | --recursive | Process the directory used in -f recursively |
| -l | --selector | Filter by label selector |
| --field-manager | — | Name of the manager used to track field ownership |
| --force-conflicts | — | If true, server-side apply force conflicts |
Examples
Diff a single manifest against live state
kubectl diff -f deployment.yamlDiff an entire directory
kubectl diff -f manifests/Diff with kustomize output
kubectl kustomize overlays/staging | kubectl diff -f -Diff a Helm template
helm template my-release chart/ | kubectl diff -f -Diff recursively through subdirectories
kubectl diff -f manifests/ -RWhen to Use kubectl diff
kubectl diff shows you exactly what would change if you ran kubectl apply. It compares your local manifest against the live cluster state and outputs a unified diff. This is essential for safe deployments, code reviews, and CI/CD pipelines.
Basic Usage
kubectl diff -f deployment.yaml
The output looks like a standard unified diff:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
- replicas: 3
+ replicas: 5
template:
spec:
containers:
- name: app
- image: my-app:v1.2.0
+ image: my-app:v1.3.0
Lines prefixed with - show the current live state, and + shows what the new state would be.
Exit Codes
The exit codes are meaningful and designed for scripting:
| Exit Code | Meaning | |-----------|---------| | 0 | No differences — cluster matches local manifests | | 1 | Differences exist — apply would make changes | | >1 | An error occurred (e.g., invalid YAML, connection failure) |
kubectl diff -f deployment.yaml
if [ $? -eq 0 ]; then
echo "No changes to apply."
elif [ $? -eq 1 ]; then
echo "Changes detected — review and apply."
else
echo "Error occurred."
fi
CI/CD Integration
In deployment pipelines, diff provides visibility before apply:
#!/bin/bash
# Generate the diff
DIFF_OUTPUT=$(kubectl diff -f manifests/ 2>&1)
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
echo "No changes to deploy."
exit 0
elif [ $EXIT_CODE -eq 1 ]; then
echo "Changes to be applied:"
echo "$DIFF_OUTPUT"
# Post diff as a comment on the PR for review
kubectl apply -f manifests/
else
echo "Error running diff: $DIFF_OUTPUT"
exit 1
fi
Using with Kustomize
Diff works seamlessly with kustomize and Helm:
# Kustomize
kubectl kustomize overlays/production | kubectl diff -f -
# Helm
helm template my-release ./chart --values values-prod.yaml | kubectl diff -f -
Piping through stdin (-f -) lets you diff generated manifests without writing temporary files.
Detecting Configuration Drift
Use diff to detect when live resources have been modified outside of your GitOps workflow:
# Check if any resources have drifted
kubectl diff -f manifests/
# If exit code is 1, someone modified resources directly
In a GitOps setup, any differences indicate drift — either from manual kubectl edits, admission webhook mutations, or controller-applied defaults.
Handling Server-Side Defaults
Kubernetes often adds default values to resources (e.g., default container resource limits, service account mounts). These appear in diff output even if you didn't change them. To reduce noise:
# Use server-side apply field manager to track ownership
kubectl diff -f deployment.yaml --field-manager=my-pipeline --force-conflicts
Server-side apply with field managers means diff only shows fields you own, reducing false positives from server-set defaults.
Comparing Directories
For multi-file deployments:
# Diff all files in a directory
kubectl diff -f manifests/
# Recursively diff subdirectories
kubectl diff -f manifests/ -R
# Diff only specific resources by label
kubectl diff -f manifests/ -l app=frontend
Permissions Required
kubectl diff requires the same permissions as kubectl get for the resources being diffed. Specifically:
geton the resource types being comparedlistif diffing multiple resources
If you lack permissions, the diff fails with a forbidden error. This is important to consider when setting up service accounts for CI/CD pipelines.
Limitations
- Diff does not show resources that exist in the cluster but are absent from your manifests (i.e., it won't detect orphaned resources).
- New resources appear as entirely new content in the diff.
- Diff sets the
KUBECTL_EXTERNAL_DIFFenvironment variable if you want to use an external diff tool likedyfffor better YAML-aware output:
export KUBECTL_EXTERNAL_DIFF="dyff between --omit-header"
kubectl diff -f deployment.yaml
Interview Questions About This Command
Common Mistakes
- Treating exit code 1 as an error — it simply means differences exist, which is expected when deploying changes.
- Not using diff before apply in production, missing unintended configuration drift.
- Forgetting that diff requires read access to the cluster — it fetches live state for comparison.