What is the difference between kubectl apply and kubectl replace
I have written up a thorough explanation of the differences between apply, replace, and patch: Kubernetes Apply vs. Replace vs. Patch. It includes an explanation that the current top-ranked answer to this question is wrong.
Briefly, kubectl apply
uses the provided spec to create a resource if it does not exist and update, i.e., patch, it if it does. The spec provided to apply
need only contain the required parts of a spec, when creating a resource the API will use defaults for the rest and when updating a resource it will use its current values.
The kubectl replace
completely replaces the existing resource with the one defined by the provided spec. replace
wants a complete spec as input, including read-only properties supplied by the API like .metadata.resourceVersion
, .spec.nodeName
for pods, .spec.clusterIP
for services, and .secrets
for service accounts. kubectl
has some internal tricks to help you get that right, but typically the use case for replace
is getting a resource spec, changing a property, and then using that changed, complete spec to replace the existing resource.
The kubectl replace
command has a --force
option which actually does not use the replace, i.e., PUT
, API endpoint. It forcibly deletes (DELETE
) and then recreates, (POST
) the resource using the provided spec.
Updated Answer
My original was rather controversial and I would even say now, in hindsight, half incorrect. So here is an updated answer which I hope will be more helpful:
- commands like kubectl
patch
,replace
,delete
,create
, evenedit
are all imperative: they tell kubectl exactly what to do - the kubectl
apply
command is OTOH "declarative" in that it tells kubernetes, here is a desired state (the yaml from the file provided to the apply command), now figure out how to get there: create, patch, replace the object, etc whatever it takes... you get the idea.
So the 2 commands are hugely different.
EG with apply
you can give it just the changes you want: it will figure out what properties of the object need to be changed, and leave the other ones alone; if those properties are "immutable" (eg, the nodeName of a pod), it will complain, and if you then repeat the command with --force
, it is smart enough to know to do the equivalent of a replace --force
.
In general, you should favor apply
(with --force
when necessary), and only use the imperative commands when the declarative approach does not give the expected result (although I would love to see examples of this -- I'm guessing this would happen only when you would need several steps because of interdependencies that will have negative consequences if done with apply).