kubectl apply Command Explained

Published:
October 15, 2026
Topics:

The kubectl apply command is the main tool for creating, updating, and managing Kubernetes cluster resources. It allows the user to enforce the desired state of the cluster defined in a structured YAML or JSON manifest file.

This article explains the kubectl command, provides examples, and lists best practices for using it.

kubectl apply command explained.

What Is kubectl apply Command?

The kubectl apply command is a declarative client-side and server-side tool for Kubernetes resource management. The command reads resource definitions from files, directories, or standard input streams, and forwards the specs to the Kubernetes API server (kube-apiserver).

Note: For a full reference of CLI operations, see the Kubectl Cheat Sheet.

While imperative commands issue concrete instructions (e.g., deleting a pod or scaling a deployment), kubectl apply provides the desired configuration. The API server evaluates the payload, calculates necessary diffs, and performs incremental updates without destroying or re-creating parameters that were not the subject of the configuration change.

Standard client-side kubectl apply uses an annotation on the kubectl.kubernetes.io/last-applied-configuration resource to track modifications across executions. The annotation stores a JSON copy of the manifest from the most recent successful apply operation.

For all subsequent updates, a three-way merge algorithm compares:

  • The last-applied configuration (from the resource annotation).
  • The current live state running in the cluster.
  • The new target configuration provided in the local manifest file.

Kubernetes selectively modifies fields reconfigured in the local manifest, preserving live field alterations applied by external controllers, e.g., dynamic IP allocation or autoscaling replicas.

kubectl apply vs kubectl create

Both kubectl apply and kubectl create are used to create resources, but their underlying mechanisms and use cases differ.

kubectl create is an imperative command. It instructs the API server to create a new instance of a specified resource. If a resource with the same name and Kubernetes namespace already exists, kubectl create returns an error and halts execution.

Note: To overwrite an existing resource with kubectl create, either explicitly delete it beforehand, or include the --replace option. This action completely strips the existing object and substitutes it with the new definition.

kubectl apply is a declarative and idempotent command:

  • If a specified resource does not exist, kubectl apply creates it.
  • If the resource already exists, kubectl apply applies incremental modifications based on the aforementioned three-way merge logic.

The table below compares the two commands:

kubectl createkubectl apply
Management ModelImperative.Declarative.
IdempotencyNo (fails if resource exists).Yes (safe to execute repeatedly).
Execution PathCreates new object directly.Creates or merges changes into existing object.
State TrackingNo tracking.Injects last-applied-configuration annotation.
CI/CD IntegrationHigh risk of pipeline failure on re-runs.Recommended for automated pipelines.

kubectl apply Command Syntax

The basic syntax for the kubectl apply command is:

kubectl apply (-f [filename] | -k [directory]) [options]

The -f (or --filename) flag specifies the path to a file, directory, or URL with resource specifications. The -k (or --kustomize) flag targets a directory containing a kustomization.yaml file for dynamic configuration management.

kubectl apply Options

Optional flags can be used to modify kubectl apply execution. The table below introduces the important options:

OptionDescription
--filename, -fPath to a file, directory, or URL containing resource definitions.
--kustomize, -kPath to a Kustomize directory.
--recursive, -RRecursively processes subdirectories specified with-f.
--dry-run=[client/server/none]Simulates the operation.
--server-sideDelegates merge decisions to the API server rather than client logic.
--field-managerIdentifies the actor managing specific fields during server-side apply.
--forceReplaces resources if conflicts cannot be resolved through standard merging.
--pruneDeletes resources not present in the applied set (requires --selector).
--selector, -lFilters resources by label key-value pairs for --prune.

kubectl apply Command Examples

The following examples show how to use kubectl apply in common deployment workflows.

Applying Resources directly from YAML Manifest

The standard application of a single manifest file updates or instantiates defined objects in the target cluster.

kubectl apply -f deployment.yaml

The output confirms the creation of the deployment:

Creating a deployment in Kubernetes using kubectl apply.

When executing this command again after modifying deployment.yaml, the terminal reflects the update:

Modifying a deployment in Kubernetes using kubectl apply.

Applying Resources from URL

To stream manifest content directly from a remote location without local caching, type the URL of the manifest:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/controllers/nginx-deployment.yaml

Deploying Entire Directories and Kustomize Configurations

Manifests can be grouped into a filesystem directory for easier access. Use the command below to process every valid manifest file inside a directory:

kubectl apply -f ./manifests/
Applying manifests from a directory.

Use the --recursive flag to include all subdirectories in a target directory:

kubectl apply -f ./manifests/ --recursive

When utilizing Kustomize for multi-environment overlays (such as staging or production variants), reference the directory containing kustomization.yaml with -k:

kubectl apply -k ./overlays/production/

Updating Bare Metal High-Performance Storage Configurations

High-performance workloads like transactional databases or distributed storage layers need low-latency storage definitions. Carefully update manifests defining local persistent volumes (LocalPV) or direct block devices to preserve path references without dismounting raw block systems.

For example, the following is a storage manifest baremetal-storage.yaml that defines a storage configuration:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nvme-storage-node01
spec:
  capacity:
    storage: 1.6Ti
  volumeMode: Block
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-nvme
  local:
    path: /mnt/disks/nvme0n1
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - edge-node-01

To apply this configuration to the cluster, use the following command:

kubectl apply -f baremetal-storage.yaml

If the local device mount point shifts from /mnt/disks/nvme0n1 to /mnt/disks/nvme1n1, modify baremetal-storage.yaml and execute kubectl apply using the --server-side flag to validate against API rules:

kubectl apply -f baremetal-storage.yaml --server-side --field-manager=storage-admin
Executing kubectl apply with the server side flag.

Validating Manifest Syntax with Dry-Run Execution

Prevent runtime disruptions by validating manifest structure before altering a live environment. A dry-run operation simulates an API submission without committing changes to the cluster database (etcd).

Evaluate the syntax locally by using client as the value in the --dry-run option:

kubectl apply -f application.yaml --dry-run=client
Executing a kubectl apply dry run.

For a full schema validation, admission webhooks checks, and RBAC authorization verification, use the server value:

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

Pruning Obsolete Resources Automatically

Running standard kubectl apply commands does not remove live cluster components that stopped existing in local source code.
Clean up resources by using the --prune option and a label selector matching the target workload group:

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

The command above scans the ./manifests/ directory, compares it against active cluster objects matching app=analytics, and removes any live resources missing from the manifests.

Managing Configurations via Server-Side Apply

Server-side apply transfers field ownership and merge calculations from the client binary to the kube-apiserver. It prevents conflicting edits between human administrators and automated CI/CD controllers.

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

If another entity modified fields owned by ci-pipeline, the API server rejects the application and prints conflicting parameters. Force ownership reassignment with the following command:

kubectl apply -f service.yaml --server-side --field-manager=ci-pipeline --force-conflicts

Common Problems When Using kubectl apply Command

kubectl apply is designed to be reliable, but state errors or application failures can still appear in edge cases. Read the sections below for troubleshooting tips.

"Conflict" and Last-Applied-Configuration Mismatch Errors

When resources are managed through mixed paradigms, i.e., modifying an object imperatively using kubectl edit, kubectl scale, or kubectl patch, and later executed declaratively via kubectl apply, a mismatch can occur.

The error happens because imperative commands bypass updates to the kubectl.kubernetes.io/last-applied-configuration annotation, so the client-side three-way merge algorithm encounters conflicting base states. When used, the command may print a warning or overwrite imperative edits.

Note: If the annotation grows excessively large (for example, when embedding large raw configs in ConfigMap manifests), the operation fails due to annotation size limitations (exceeding 262,144 bytes).

To keep the current live cluster state and align the local YAML file with it for future kubectl apply runs:

1. Export the current live configuration (including imperative changes) to a local YAML file:

kubectl get -o yaml > updated-manifest.yaml

2. Clean up runtime metadata from updated-manifest.yaml (remove fields like status, uid, resourceVersion, creationTimestamp, and existing kubectl.kubernetes.io/last-applied-configuration annotations).

3. Overwrite the annotation using the --overwrite flag:

kubectl apply -f updated-manifest.yaml --overwrite

4. Confirm the annotation matches the updated file:

kubectl get -o jsonpath='{.metadata.annotations.kubectl.kubernetes.io/last-applied-configuration}'

Field Management and Server-Side Apply Conflicts

For server-side apply, Kubernetes tracks field ownership using the resource's managedFields metadata array. If kubectl apply --server-side tries to change a parameter managed by a different entity (such as an ingress controller, horizontal pod autoscaler, or GitOps agent), the operation raises the following error:

error: Apply failed with 1 conflict: conflict with "helm" manager on path: spec.replicas

To resolve the error, omit the contested field from the local manifest, cede field ownership, or explicitly pass the --force-conflicts flag.

Attempting to Modify Immutable Fields

Some Kubernetes resource specification parameters are immutable after creation. For example, most fields in a PodSpec (such as spec.containers[*].name or persistent volume claim bindings) cannot be modified on a running pod instance.

If a local manifest attempts to change an immutable field, running kubectl apply throws an error, for example:

The Deployment "web-server" is invalid: spec.template: Invalid value: ... field is immutable

To replace resources with immutable field changes, re-create the object using:

kubectl replace --force -f [filename].yaml

Alternatively, delete the object before executing kubectl apply.

Best Practices When Using kubectl apply Command

Follow the best practices below to optimize use of the kubectl apply command:

  • Maintain manifests in version control. Store all resource specifications in a structured Git repository to maintain traceability, code reviews, and automated deployment auditing.
  • Adopt server-side apply for pipelines. Utilize kubectl apply --server-side in CI/CD automation to leverage fine-grained field tracking and centralize merge logic within the API server.
  • Run server-side dry runs in validation steps. Integrate --dry-run=server checks into pre-merge pull request tests to intercept syntax mistakes, schema mismatches, and authorization issues prior to production deployment.
  • Avoid mixing imperative and declarative operations. Refrain from running manual kubectl edit or kubectl patch commands on resources managed via kubectl apply to prevent state tracking drift.
  • Define explicit field managers. Always provide a named --field-manager identifier when using server-side apply to track modifications cleanly across human operators and automated agents.
  • Consistently label resources for safe pruning. Apply standardized labels across manifests to safely use the --prune flag.

Conclusion

After reading this article, you should understand how to use the kubectl apply command in your cluster. The article covered the command's mechanics, syntax flags, and behavior, and provided troubleshooting steps and best-practice tips.

Next, read our Terraform vs. Kubernetes comparison guide.

Was this article helpful?
YesNo