KubernetesVI · kubectl for Administratorskubectl for administrators
kubectl edit, label, annotate, set — in-place modification
What you'll learn
- Use kubectl edit to modify a live object through your $EDITOR
- Use kubectl label and kubectl annotate to manage object metadata
- Use kubectl set to change images, resources, and env on Deployments and other workloads
- Recognise when in-place edits bypass GitOps and what to do about it
Prerequisites
Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16
Read commands answer questions. Write commands change state.
This lesson covers the four in-place write commands every
operator reaches for: edit, label, annotate, set. They
are fast, ergonomic, and the source of most cluster drift.
kubectl edit — open the object in your editor
kubectl edit reads the object from the API server, opens it in
your $EDITOR ($KUBE_EDITOR overrides), and applies the
edited YAML on save. Under the hood it does a GET then a
PUT (not a PATCH) — the entire object is replaced.
kubectl edit deployment web -n team-a-prod
kubectl edit svc web -o yaml
KUBE_EDITOR='vim' kubectl edit pod web-7c8
The behaviour:
- kubectl reads the object (or subresource with
-o yaml). - kubectl writes it to a temp file and runs
$KUBE_EDITOR(or$EDITOR) on it. - On save, kubectl PUTs the edited YAML back to the API server.
- The API server validates the YAML; if it parses, the object is replaced.
Important properties:
- The edit is a PUT, not a PATCH. If you delete a field by accident, the PUT replaces the whole object and the field is gone.
- The edit runs against whatever the API server returns.
Server-defaulted fields (e.g.,
status, default labels) appear in the file and are sent back unchanged. editis interactive. Non-interactive edits require different commands.
# Non-interactive edit via stdin
kubectl get deployment web -o yaml | sed 's/replicas: 3/replicas: 5/' | kubectl apply -f -
# Or use kubectl scale (cleaner for single-field changes)
kubectl scale deployment web --replicas=5
kubectl label — manage labels
Labels are how Kubernetes objects get selected. Setting them right is what makes selectors, services, and replication controllers work.
kubectl label pods web-7c8 app=web # set
kubectl label pods web-7c8 app=web --overwrite # set if exists
kubectl label pods web-7c8 app- # remove (key-)
kubectl label pods -l app=web env=prod # all matching
kubectl label --all pods env=prod # all in ns
kubectl label node node-3 team=web # on a Node
kubectl label ns team-a-prod pod-security.kubernetes.io/enforce=restricted
The trailing - syntax removes a label. app- deletes the
label with key app. This is unique to kubectl; the API
server itself does not understand app-.
--overwrite is required to change an existing label. Without
it, kubectl returns “already has that value” or refuses to
overwrite (depending on the version).
Production patterns
The labels that matter most:
# Recommended labels (see Kubernetes recommended labels)
kubectl label ... app.kubernetes.io/name=web
kubectl label ... app.kubernetes.io/instance=web-7c8
kubectl label ... app.kubernetes.io/version=1.2.3
kubectl label ... app.kubernetes.io/component=frontend
kubectl label ... app.kubernetes.io/part-of=checkout
kubectl label ... app.kubernetes.io/managed-by=helm
# Node labels for scheduling
kubectl label node node-3 workload=high-memory
kubectl label node node-3 workload=high-memory- # remove
A node label with a - suffix removes that label. The kubelet
will not delete labels applied through its own Node API;
labels on Nodes are operator-managed.
kubectl annotate — manage annotations
Annotations are non-identifying metadata. They are used for tooling, documentation, and arbitrary key-value storage.
kubectl annotate pods web-7c8 description="production web tier"
kubectl annotate pods -l app=web contact=team-a@example.com
kubectl annotate pods web-7c8 description- # remove
kubectl annotate pods web-7c8 description="updated text" --overwrite
Common production uses:
kubernetes.io/ingress.class(legacy) — class for Ingressservice.beta.kubernetes.io/aws-load-balancer-type— cloud LB integrationprometheus.io/scrape=true— Prometheus scrape annotationssidecar.istio.io/inject=false— service mesh overridesconfig.kubernetes.io/local-config— kubectl config hint
Annotations are strings; they cannot be selected by label selector. Use them for tooling, not for identification.
kubectl set — modify workload specs
kubectl set is a family of subcommands that wrap PATCH
operations on workload specs:
# Set image on Deployment (rolls out a new ReplicaSet)
kubectl set image deployment/web web=nginx:1.27.2
kubectl set image deployment/web web=nginx:1.27.2 --record
# Set environment variables
kubectl set env deployment/web DB_HOST=db.example.com
kubectl set env deployment/web DB_HOST- # remove var
kubectl set env deployment/web --from=configmap/web # from ConfigMap
kubectl set env deployment/web --from=secret/db # from Secret
# Set resource requests/limits
kubectl set resources deployment/web -c web \
--requests=cpu=200m,memory=256Mi --limits=cpu=500m,memory=512Mi
# Set service account
kubectl set serviceaccount deployment/web app-sa
# Set pull policy / image pull secrets
kubectl set image deployment/web web=nginx:1.27.2
kubectl set image-registries ... # in newer versions
kubectl set is the right tool for one-off changes that
should propagate through the workload’s rollout machinery. The
Deployment controller detects the spec change and rolls out a
new ReplicaSet.
When in-place editing breaks GitOps
The fundamental tension: a Kubernetes cluster’s live state and
the manifests in source control can diverge. apply makes them
converge toward the manifest. edit, label, annotate,
set make the live state diverge from the manifest.
flowchart LR
A[Manifest in Git] -->|apply| B[Live state]
B -->|edit / set / label| A
A -.->|next apply| B
Production discipline:
- Triage edits are temporary. A
kubectl editto fix a typo or update an image tag during an incident is fine. Fix Git immediately afterwards. - Sustained changes go through Git. Anything that should
persist for hours, days, or weeks must be in a manifest
that
applywill reapply. - Audit live vs Git regularly.
kubectl diff -f manifest.yamlshows the divergence. Use it in CI: if the diff is non-empty, fail the build. - Use
--server-sideapply (Part VII) for fields that multiple tools need to manage without overwriting each other.
How to safely do a one-off edit
If you must edit (or set) in production:
# 1. Capture the current state
kubectl get deployment web -o yaml > /tmp/web-before.yaml
# 2. Make the edit
kubectl edit deployment web
# 3. Verify the change took
kubectl get deployment web -o yaml | diff - /tmp/web-before.yaml
# 4. Reflect the change in Git
# (commit the change to the manifest repo)
# 5. If something went wrong, restore from the backup
kubectl apply -f /tmp/web-before.yaml
The backup before the edit is the difference between a clean
recovery and a manual reconstruction. Production operators
keep /tmp/<object>-before.yaml snapshots for every edit
session.
Cross-course references
- The Terraform course part
XVII-Terraform-Driftcovers drift detection in Terraform state; the same discipline applies to live Kubernetes state vs manifests in Git. - The Ansible course part
XXXVI-Ansible-Driftcovers configuration drift;kubectl editis the live equivalent of running an ad-hoc shell command. - The Linux course part
LXXIV-Linux-Driftcovers configuration management drift at the OS level.
Quiz
Knowledge check · 4 questions
Q1. Which HTTP verb does `kubectl edit` use when it saves the edited object?
Q2. `kubectl label pods web-7c8 app-` removes the label with key `app` from the Pod.
Q3. An incident requires immediately rolling the web Deployment from `nginx:1.27.1` to `nginx:1.27.2` to pick up a security patch. The on-call engineer uses `kubectl set image`. What happens to GitOps, what is the blast radius, and how do you reconcile afterwards?
Cluster has 30+ workloads, all managed by ArgoCD from a Git repository. The web Deployment is in repo `infra-manifests`. The current image is `nginx:1.27.1`. The new image is `nginx:1.27.2`. The Deployment has 5 replicas. ArgoCD is configured with `prune: false` and is the source of truth.
Q4. Explain why `kubectl set image` creates drift and how to reconcile after a triage edit.
Passing score: 75%. Answers are checked in this browser.
Production discipline
- Prefer
apply -fovereditfor sustained changes.applyis manifest-driven and reproducible;editis interactive and creates drift. - Reserve
editfor triage. A 2am fix to a typo or an emergency image bump is fine. Anything that should persist longer than the incident must be reflected in Git. - Capture the object before every edit.
kubectl get -o yaml > /tmp/before.yamlis the difference between a clean recovery and a manual reconstruction. - Use
kubectl diff -f manifest.yamlin CI. If a manifest has drifted from the live state, fail the build. - Audit
pods/exec,pods/eviction, and other write verbs. In a GitOps cluster, only the controller should write. Any manual write is an exception that needs review.