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

FlagShortDescription
--filename-fFilename, directory, or URL to files that contain the configuration to apply
--recursive-RProcess the directory used in -f recursively
--dry-runMust be none, server, or client. Preview the changes without applying
--server-sideUse server-side apply. Field ownership is tracked by the API server
--force-conflictsForce apply even when there are field ownership conflicts (server-side apply)
--pruneDelete resources that are no longer in the applied configuration

Examples

Apply a configuration file

kubectl apply -f deployment.yaml

Apply all files in a directory

kubectl apply -f ./manifests/

Apply recursively from nested directories

kubectl apply -f ./env/production/ -R

Apply from a URL

kubectl apply -f https://raw.githubusercontent.com/org/repo/main/deploy.yaml

Preview changes with server-side dry run

kubectl apply -f deployment.yaml --dry-run=server

Use server-side apply with field management

kubectl apply -f deployment.yaml --server-side --field-manager=ci-pipeline

Apply and prune resources no longer in the configuration

kubectl apply -f ./manifests/ --prune -l app=myapp

When 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:

  1. The new configuration you are applying.
  2. The last-applied-configuration stored in the resource annotation.
  3. 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

How does kubectl apply differ from kubectl create and kubectl replace?
apply is declarative — it creates or updates resources by merging changes. create is imperative and fails if the resource exists. replace overwrites the entire resource, which can remove fields not in the new spec.
What is the last-applied-configuration annotation and why does it matter?
kubectl apply stores the full configuration in the kubectl.kubernetes.io/last-applied-configuration annotation. It uses this to compute a three-way merge between the last applied config, the current live state, and the new config.
What is server-side apply and when should you use it?
Server-side apply moves the merge logic to the API server and tracks field ownership per manager. It prevents conflicts when multiple controllers or users manage the same resource and is the recommended approach for complex multi-team environments.

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.

Related Commands