I created a pod with kubectl create -f pod.xml
and kubectl apply -f pod.xml
using the below yaml and I don't see any difference, a pod gets created with both the commands. The K8S document, mentions imperative and declarative commands. But, still the create and apply behave the same way.
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
What's the difference? Also, how is kubectl apply
declarative and kubectl create
imperative? Both of them take one or multiple yaml files with the object details in it.
Those are two different approaches. kubectl create is what we call Imperative Management. On this approach you tell the Kubernetes API what you want to create, replace or delete, not how you want your K8s cluster world to look like.
kubectl apply is part of the Declarative Management approach, where changes that you may have applied to a live object (i.e. through scale) are maintained even if you apply other changes to the object.
You can read more about imperative and declarative management in the Kubernetes Object Management documentation.
There is a subtle difference between kubectl create
and kubectl apply
commands.
The kubectl create
command creates a new resource. So, if the command is run again it will throw an error as resource names should be unique in a namespace.
kubectl get pods
No resources found.
kubectl create -f pod.xml
pod/myapp-pod created
kubectl create -f pod.xml
Error from server (AlreadyExists): error when creating "pod.xml": pods "myapp-pod" already exists
2) The kubectl apply
command applies the configuration to a resource. If the resource is not there then it will be created. The kubectl apply
command can be run the second time as it simply applies the configuration as shown below. In this case, the configuration hasn't changed. So, the pod hasn't changed.
kubectl delete pod/myapp-pod
pod "myapp-pod" deleted
kubectl apply -f pod.xml
pod/myapp-pod created
kubectl apply -f pod.xml
pod/myapp-pod unchanged
In the kubectl create
, we specify a certain action, in this case create
and so it is imperative. In the kubectl apply
command we specify the target state of the system and don't specify a certain action and so declarative. We let the system decide what action to take. If the resource is not there it will create it, if the resource is there then it will apply the configuration to the existing resource.
From an execution perspective, there is no difference when a resource is created for the first time between kubectl create
and kubectl apply
as shown above. But, the second time the kubectl create
will throw an error.
It took me some time to get around it, but it makes sense now.
In plain terms, create
and apply
are essentially the same if you run the operation on a single file to create resources. However, apply
lets you create and patch at the same time on multiple files under a directory.
There's also an apply
to remove resources from a directory but it's in alpha as of this writing:
kubectl apply -f <directory/> --prune -l your=label)
There are more insights on this question too: Kubectl apply vs kubectl create?