kubectl create deploy and kubectl run are imperative: a command with flags, run once, nothing saved. A manifest file applied with kubectl apply -f is declarative: the file states the desired object, and you can apply it again at any time.
Generate instead of typing
kubectl writes manifests for you. Add --dry-run=client -o yaml to any create command and nothing is sent to the server; the manifest is printed instead:
kubectl create deploy web --image=nginx:1.27 --dry-run=client -o yamlRedirect it into a file:
mkdir -p ~/manifests
kubectl create deploy web --image=nginx:1.27 --dry-run=client -o yaml > ~/manifests/web.yamlThe same works for Pods (kubectl run), Services (kubectl create svc clusterip), ConfigMaps and Secrets.
Edit, then apply
Open the file, change what the generator could not know (replicas, ports, labels), and apply it:
vim ~/manifests/web.yaml
kubectl apply -f ~/manifests/web.yaml -n shopThe first apply prints created. Later applies print configured when something changed and unchanged when nothing did.
The loop
generate ──▶ edit file ──▶ kubectl apply -f ──▶ cluster
▲ │
└──────── kubectl get -o yaml (compare) ◀─────┘The file is the record. If the live object drifts (someone scales it by hand), applying the file puts it back. If you need to remove everything the file describes:
kubectl delete -f ~/manifests/web.yaml -n shopExporting a live object
-o yaml on a live object includes server-set fields (uid, resourceVersion, status). They are harmless to apply, but a clean manifest leaves them out. Removing status: and the three server fields under metadata is enough.