| Tested on | Rocky Linux 10.2 (Red Quartz) workstation |
|---|---|
| Package | kubectl 1.36.3 |
| Applies to | Linux or macOS shell with kubectl configured; any Kubernetes cluster |
| Cert prep | CKA · CKAD |
| Lab environment | Multi-node kubeadm cluster with containerd — install Kubernetes with kubeadm |
| Privilege | Normal user (no sudo required on the workstation) |
| Scope | kubectl apply, diff, client and server dry-run, edit, strategic merge, JSON merge, and JSON Patch, patch files, replace and replace --force, server-side apply overview, manifest drift, comparison tables, and troubleshooting. Does not cover basic get/create/delete, full YAML anatomy, Kustomize overlays, Deployment rollout rollback, Helm, GitOps, or managed-fields internals. |
| Related guides | Kubernetes labels and selectors |
This walkthrough uses one web Deployment in the kubectl-lab namespace. You apply a starter manifest, then update it with apply, diff, dry-run, edit, patch, and replace so you can pick the right tool for each situation.
If kubectl syntax, namespaces, or YAML basics are new, start with kubectl command examples before this chapter.
Different methods to update Kubernetes Resource
Kubernetes objects change over time. The command you choose depends on whether you maintain YAML on disk, need a quick live edit, or want to replace the whole object.
| Command | Best suited for |
|---|---|
kubectl apply |
Declaratively create or update resources from manifests |
kubectl edit |
Make an immediate interactive change to a live object |
kubectl patch |
Change selected fields without supplying the full object |
kubectl replace |
Replace the existing object using a complete manifest |
kubectl diff |
Preview differences before applying |
--dry-run |
Validate or preview a command without making the normal change |
The sections below walk through each method on the same Deployment.
Prepare the Example Deployment
Create a namespace and a Deployment with two replicas, one nginx container, matching selector labels, and a version label on the Pod template.
Save namespace.yaml:
apiVersion: v1
kind: Namespace
metadata:
name: kubectl-labSave deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: kubectl-lab
labels:
app: web
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
version: v1
spec:
containers:
- name: nginx
image: nginx:1.25.4
ports:
- containerPort: 80Apply the namespace first, then the Deployment:
kubectl apply -f namespace.yamlkubectl apply -f deployment.yamlSample output:
namespace/kubectl-lab created
deployment.apps/web createdConfirm the initial shape:
kubectl get deployment web -n kubectl-labSample output:
NAME READY UP-TO-DATE AVAILABLE AGE
web 0/2 2 0 0sUP-TO-DATE shows how many replicas use the Deployment's latest desired Pod template. It does not mean those Pods are already scheduled or Ready. READY may lag briefly while images pull.
Every update example in this article targets this same web Deployment.
Update Resources with kubectl apply
kubectl apply creates a resource when it does not exist and updates it when the manifest changes. Treat the YAML file as the maintained source of configuration for declarative workflows.
Re-run apply against an unchanged file:
kubectl apply -f deployment.yamlWhen the maintained configuration has not changed, kubectl normally reports unchanged. configured indicates that kubectl submitted an update.
Edit the maintained manifest
Edit deployment.yaml on disk:
- Set
replicasto3 - Change the image to
nginx:1.27.0 - Change the Pod-template label
versionfromv1tov2
Preview changes with kubectl diff
kubectl diff compares your manifest against the live object without applying it:
kubectl diff -f deployment.yamlSample output (trimmed):
diff -u -N /tmp/LIVE-316227394/apps.v1.Deployment.kubectl-lab.web /tmp/MERGED-4285196381/apps.v1.Deployment.kubectl-lab.web
--- /tmp/LIVE-316227394/apps.v1.Deployment.kubectl-lab.web
+++ /tmp/MERGED-4285196381/apps.v1.Deployment.kubectl-lab.web
@@ -15,7 +15,7 @@
uid: ecbd21e9-b47d-4f3f-aa6c-a3cc90b09ece
spec:
progressDeadlineSeconds: 600
- replicas: 2
+ replicas: 3
revisionHistoryLimit: 10
@@ -29,10 +29,10 @@
metadata:
labels:
app: web
- version: v1
+ version: v2
spec:
containers:
- - image: nginx:1.25.4
+ - image: nginx:1.27.0kubectl diff returns 0 when no differences exist, 1 when differences are found, and a value greater than 1 for an error. This matters in scripts and CI pipelines.
Lines prefixed with - show current cluster values. Lines with + show what the manifest would set. The command exits after printing the diff; it does not change the Deployment.
Validate with client and server dry-run
--dry-run validates or previews a command without persisting the normal change.
Client dry-run builds the object locally:
kubectl apply -f deployment.yaml --dry-run=client -o yamlSample output (trimmed):
replicas: 3
version: v2
- image: nginx:1.27.0kubectl processes the file on your workstation and prints the resulting object. The API server does not persist it.
Server dry-run sends the request to the API server for validation:
kubectl apply -f deployment.yaml --dry-run=server -o yamlThe output shape matches client dry-run for this Deployment, but admission controllers and validation run on the server. Use server dry-run when you need API-level checks before a real apply.
| Mode | Uses API server validation | Persists change |
|---|---|---|
client |
No | No |
server |
Yes | No |
Apply the updated manifest
Apply the edited file:
kubectl apply -f deployment.yamlSample output:
deployment.apps/web configuredVerify the live spec:
kubectl get deployment web -n kubectl-lab -o jsonpath='replicas={.spec.replicas} image={.spec.template.spec.containers[0].image} version={.spec.template.metadata.labels.version}{"\n"}'Sample output:
replicas=3 image=nginx:1.27.0 version=v2The Deployment controller rolls out a new ReplicaSet when the Pod template changes.
Apply multiple files
apply accepts several inputs:
- Multiple files:
kubectl apply -f namespace.yaml -f deployment.yaml - A directory:
kubectl apply -f ./manifests/ - Standard input:
kubectl apply -f -(pipe YAML into kubectl)
Kustomize overlays use kubectl apply -k on a directory with kustomization.yaml. That path is covered in Kubernetes Kustomize; this article stays on plain -f manifests.
Server-side apply
Server-side apply lets the API server track field ownership and detect conflicts when several actors manage one object. Conflicting changes are normally rejected rather than automatically resolved unless ownership is deliberately forced.
kubectl apply --server-side -f deployment.yamlSample output:
deployment.apps/web serverside-appliedUse server-side apply when multiple actors need explicit field ownership. Actors should normally manage distinct fields; attempting to change a differently valued field owned by another manager causes a conflict unless ownership is deliberately forced. This article does not dive into managed-fields internals.
Edit a Live Resource with kubectl edit
kubectl edit opens the current object in your editor and submits changes when you save.
kubectl edit deployment web -n kubectl-labkubectl fetches the live Deployment, opens it in $KUBE_EDITOR or $EDITOR, and applies your edits when the editor exits successfully. The local deployment.yaml file is not updated automatically.
Change spec.replicas from 3 to 2, save the file, and close the editor.
kubectl get deployment web -n kubectl-lab -o jsonpath='replicas={.spec.replicas}{"\n"}'Sample output:
replicas=2After a successful edit, deployment.yaml still contains replicas: 3, demonstrating manifest drift.
Configure the editor
Set the editor before running edit:
export KUBE_EDITOR=nanoEDITOR is used when KUBE_EDITOR is unset.
When to use kubectl edit
kubectl edit fits fast lab changes, temporary troubleshooting, and small interactive updates. Avoid it when Git-managed YAML must remain the single source of truth—record important edits back into the manifest and apply from there.
Patch Selected Resource Fields
kubectl patch changes only the fields you specify instead of sending the complete object.
Strategic merge patch
Strategic merge is the default patch type for supported built-in resources such as Deployments.
Scale replicas:
kubectl patch deployment web -n kubectl-lab -p '{"spec":{"replicas":4}}'Sample output:
deployment.apps/web patchedConfirm:
kubectl get deployment web -n kubectl-lab -o jsonpath='replicas={.spec.replicas}{"\n"}'Sample output:
replicas=4Change the container image with the same patch type:
kubectl patch deployment web -n kubectl-lab \
-p '{"spec":{"template":{"spec":{"containers":[{"name":"nginx","image":"nginx:1.27.1"}]}}}}'kubectl get deployment web -n kubectl-lab -o jsonpath='image={.spec.template.spec.containers[0].image}{"\n"}'Sample output:
image=nginx:1.27.1Strategic merge merges lists such as containers by name rather than replacing the entire list blindly.
Use kubectl explain when you need the exact field path for a resource type.
JSON merge patch
JSON merge patch treats object fields as merges and replaces whole lists when you send a list in the patch:
kubectl patch deployment web -n kubectl-lab --type=merge -p '{"metadata":{"labels":{"tier":"frontend"}}}'Sample output:
deployment.apps/web patchedCheck the new label:
kubectl get deployment web -n kubectl-lab -o jsonpath='tier={.metadata.labels.tier}{"\n"}'Sample output:
tier=frontendJSON Patch
JSON Patch (RFC 6902) sends explicit operations:
kubectl patch deployment web -n kubectl-lab --type=json -p='[{"op":"replace","path":"/spec/replicas","value":3}]'Sample output:
deployment.apps/web patchedOne replace operation targets /spec/replicas with value 3. Use JSON Patch when you need precise path-based edits.
Patch using a file
Large patches belong in a file:
Save patch.yaml:
spec:
template:
metadata:
labels:
track: stableApply it:
kubectl patch deployment web -n kubectl-lab --patch-file patch.yamlSample output:
deployment.apps/web patchedVerify:
kubectl get deployment web -n kubectl-lab -o jsonpath='track={.spec.template.metadata.labels.track}{"\n"}'Sample output:
track=stableCRD limitation
Strategic merge patch is not supported for custom resources. For CRDs use --type=merge or --type=json, or update the CR manifest and apply.
Replace a Resource from a Manifest
kubectl replace submits a complete replacement object. The resource must already exist, and the manifest must include the live object's metadata.resourceVersion. Kubernetes recommends exporting the complete live object before replacing it.
Wait for the current rollout to finish, then export the live Deployment:
kubectl rollout status deployment/web -n kubectl-lab --timeout=120skubectl get deployment web -n kubectl-lab -o yaml > deployment-replace.yamlEdit deployment-replace.yaml and set:
spec:
replicas: 2You can also remove live-only tier and track labels to demonstrate that fields omitted from a complete replacement are removed.
Replace the object:
kubectl replace -f deployment-replace.yamlSample output:
deployment.apps/web replacedConfirm:
kubectl get deployment web -n kubectl-lab -o jsonpath='replicas={.spec.replicas}{"\n"}'Sample output:
replicas=2Fields omitted from the replacement manifest can be removed or reset compared to the live object. replace is a poor fit when several tools manage different fields on the same object—apply preserves fields kubectl does not own.
Force replacement
When an immutable field blocks an update, replace --force deletes and recreates the object. Keep the clean source manifest for this example:
kubectl replace --force -f deployment.yamlreplace --force deletes and recreates the Deployment with a new UID. Its ReplicaSets and Pods are consequently replaced, and application availability can be interrupted while the recreated workload becomes Ready. Use --force only when recreation is acceptable.
Compare apply, edit, patch and replace
| Requirement | Recommended command |
|---|---|
| Maintain resources from YAML | kubectl apply |
| Preview manifest changes | kubectl diff |
| Test validation without saving | --dry-run=server |
| Make a quick interactive change | kubectl edit |
| Change one or two selected fields | kubectl patch |
| Submit a complete replacement object | kubectl replace |
| Delete and recreate from a manifest | kubectl replace --force only when required |
Understand Manifest Drift
kubectl edit and kubectl patch change the live object but not your local YAML. The cluster and the file can diverge.
If you apply an older manifest after a live patch, kubectl reapplies whatever the file still defines and can overwrite the manual change. Record important edits in the declarative source file. Run kubectl diff before apply when drift is possible.
This article does not cover GitOps reconciliation; the same drift principle applies whenever the file and cluster disagree.
Common Problems
| Symptom | Likely cause | Fix |
|---|---|---|
kubectl apply overwrites an earlier manual change |
Local manifest still defines a different value | Update the YAML to match the desired state, or revert the live change before apply |
kubectl edit reports the object was modified |
Another update occurred while the editor was open | Close without saving, fetch the latest object, and edit again |
| Patch changes the wrong list item | Wrong patch type or list merge behavior | Use strategic merge for built-in types with named list keys; verify with kubectl explain |
| Strategic merge patch fails for a custom resource | CRDs do not support strategic merge | Use --type=merge or --type=json |
kubectl replace reports the resource does not exist |
Object was never created | Use kubectl apply or create the resource first |
kubectl replace fails with a resource version conflict |
Exported manifest is stale or missing metadata.resourceVersion |
Re-export the live object with kubectl get -o yaml before editing |
| An immutable field cannot be changed | Field is fixed after creation | Revert the field or recreate with replace --force when appropriate |
| Live resource changes but source YAML does not | edit or patch skipped the manifest |
Copy the change into the maintained file |
What's Next
- Kubernetes API Deprecations and Manifest Migration
- Kubernetes Liveness, Readiness and Startup Probes
- kubectl logs, Events and describe with Examples
References
- kubectl command reference — apply, edit, patch, replace, and diff
- Managing Kubernetes Objects Using Configuration Files — declarative apply workflow
- Update API Objects in Place Using kubectl patch — patch types and examples
- Server-Side Apply — field ownership and conflict handling
Summary
You prepared one web Deployment in kubectl-lab and updated it with the main kubectl change commands. kubectl apply remained the default for maintained YAML: edit the file, diff when you want a preview, dry-run when you want validation, then apply. kubectl edit and kubectl patch handled quick live edits and small field changes without opening the full manifest.
The main pitfall is manifest drift. Interactive edits and patches change the cluster immediately but not your Git copy. A later apply from stale YAML can undo them. Keep the declarative file aligned with production intent and run diff before apply when several people touch the same object.
For overlay-based layouts use Kubernetes Kustomize. For rollout status, history, and rollback after image changes, continue with Deployments and rolling updates.

