kubectl apply
Apply a configuration to a resource by file, stdin, or URL. Creates the resource if it does not exist, updates it if it does.
kubectl apply -f [FILE] [flags]Common Flags
| Flag | Short | Description |
|---|---|---|
| --filename | -f | Filename, directory, or URL to files that contain the configuration to apply |
| --recursive | -R | Process the directory used in -f recursively |
| --dry-run | — | Must be none, server, or client. Preview the changes without applying |
| --server-side | — | Use server-side apply. Field ownership is tracked by the API server |
| --force-conflicts | — | Force apply even when there are field ownership conflicts (server-side apply) |
| --prune | — | Delete resources that are no longer in the applied configuration |
Examples
Apply a configuration file
kubectl apply -f deployment.yamlApply all files in a directory
kubectl apply -f ./manifests/Apply recursively from nested directories
kubectl apply -f ./env/production/ -RApply from a URL
kubectl apply -f https://raw.githubusercontent.com/org/repo/main/deploy.yamlPreview changes with server-side dry run
kubectl apply -f deployment.yaml --dry-run=serverUse server-side apply with field management
kubectl apply -f deployment.yaml --server-side --field-manager=ci-pipelineApply and prune resources no longer in the configuration
kubectl apply -f ./manifests/ --prune -l app=myappWhen to Use kubectl apply
kubectl apply is the cornerstone of declarative resource management in Kubernetes. It is the recommended way to manage production workloads because it creates resources that do not exist and updates resources that do, using a three-way merge strategy that preserves changes made by other actors like controllers and autoscalers.
The Three-Way Merge
When you run kubectl apply, Kubernetes compares three versions of the resource:
- The new configuration you are applying.
- The last-applied-configuration stored in the resource annotation.
- The live state of the resource in the cluster.
This three-way merge means that fields removed from your manifest will be deleted, fields added will be set, and fields you never managed (like status or controller-set values) will be preserved.
# Apply a deployment
kubectl apply -f deployment.yaml
# View the last-applied-configuration annotation
kubectl get deployment my-app -o jsonpath='{.metadata.annotations.kubectl\.kubernetes\.io/last-applied-configuration}' | jq .
Server-Side Apply
Server-side apply (SSA) is the evolution of client-side apply. It moves the merge logic to the API server and introduces the concept of field ownership. Each field is tracked by a field manager, preventing accidental overwrites.
# Apply with server-side apply
kubectl apply -f deployment.yaml --server-side
# Specify a field manager for CI/CD pipelines
kubectl apply -f deployment.yaml --server-side --field-manager=argocd
# Force through conflicts if you own the resource
kubectl apply -f deployment.yaml --server-side --force-conflicts
Server-side apply is particularly valuable when multiple tools manage the same resource. For example, your CI/CD pipeline might manage the image tag while an HPA manages the replica count. SSA prevents these from conflicting.
Working with Directories and Kustomize
Apply works naturally with directory structures and Kustomize overlays:
# Apply an entire directory of manifests
kubectl apply -f ./base/
# Apply recursively through subdirectories
kubectl apply -f ./environments/production/ -R
# Apply a Kustomize overlay
kubectl apply -k ./overlays/production/
The -k flag integrates with Kustomize directly, allowing you to apply transformed manifests without running kustomize build separately.
Pruning Deleted Resources
The --prune flag removes resources that exist in the cluster but are no longer present in the applied configuration. This is essential for keeping the cluster in sync with your Git repository:
# Prune resources labeled app=myapp that are no longer in the manifests
kubectl apply -f ./manifests/ --prune -l app=myapp
# Prune specific resource types only
kubectl apply -f ./manifests/ --prune -l app=myapp \
--prune-allowlist=core/v1/ConfigMap \
--prune-allowlist=apps/v1/Deployment
Use pruning cautiously. Always use a label selector to scope the prune operation, and consider using --dry-run=server first to preview what would be deleted.
Dry Run and Diff
Before applying changes to production, preview what will change:
# Client-side dry run — validates locally
kubectl apply -f deployment.yaml --dry-run=client
# Server-side dry run — validates with API server
kubectl apply -f deployment.yaml --dry-run=server
# Show what would change with diff
kubectl diff -f deployment.yaml
The kubectl diff command is especially useful in CI/CD pipelines to show exactly what fields would change before applying.
Common Patterns in Production
In GitOps workflows, kubectl apply is typically executed by a controller like ArgoCD or Flux rather than manually. However, understanding how apply works is critical for debugging:
# Apply with verbose output to see API calls
kubectl apply -f deployment.yaml -v=6
# Apply and record the command in the change-cause annotation
kubectl apply -f deployment.yaml
# Validate before applying
kubectl apply -f deployment.yaml --validate=true --dry-run=server
Managing Configuration Drift
When the live state drifts from your desired configuration, apply will reconcile the difference. You can detect drift before applying:
# Check for differences between local and live state
kubectl diff -f deployment.yaml
# Force apply to resolve drift
kubectl apply -f deployment.yaml
If you find that apply is not removing fields you expected it to, check whether the resource was originally created with kubectl create without --save-config. Without the last-applied-configuration annotation, the three-way merge cannot detect removed fields.
Best Practices
Always store your manifests in version control and apply from there. Use namespaced directories to organize by environment. Prefer server-side apply for multi-team environments. Use kubectl diff in CI pipelines to surface changes for review before deployment. Avoid mixing imperative and declarative management for the same resource.
Interview Questions About This Command
Common Mistakes
- Mixing kubectl create and kubectl apply for the same resource, which can cause issues with the last-applied-configuration annotation being missing.
- Using --prune without a label selector, which can accidentally delete resources you did not intend to remove.
- Not understanding the three-way merge and being surprised when fields set by controllers (like replicas set by HPA) get overwritten.