Declarative vs. Imperative object management
Kubernetes provides two ways to manage objects: declarative and imperative.
Imperative object management
In imperative object management, you tell Kubernetes exactly what to do. You provide the command and Kubernetes executes it.
Declarative object management
In declarative object management, you tell Kubernetes what you want to achieve. You provide a configuration file and Kubernetes makes sure that the cluster matches the desired state.
The difference
The difference between the two is subtle. Let's understand this with examples.
Imperative pod creation
Let's understand imperative object management with an example.
Run the following command to create a pod named simple-pod
:
cd bootstrapping-with-kubernetes-examples/deploy/simple-pod
kubectl create -f pod.yaml
It should give the following output:
$ kubectl create -f pod.yaml
pod/simple-pod created
In this command, you're telling Kubernetes to exactly perform the create
operation on the pod.yaml
file. This will create a pod named simple-pod
with no labels, as shown below:
$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
simple-pod 1/1 Running 0 25m <none>
Now, say you want to add a label app=simple-pod
to the pod. You can do this by running the following command:
kubectl label pod simple-pod app=simple-pod
This will add the label app=simple-pod
to the pod.
$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
simple-pod 1/1 Running 0 27m app=simple-pod
In this command, you're telling Kubernetes to exactly perform the label
operation on the simple-pod
pod.
Another way to add label would be edit the metadata
field in the pod.yaml
file and add the label there, as shown below:
metadata:
name: simple-pod
labels:
app: simple-pod
Now, if you run create
on the updated configuration again, kubectl will give the following output:
$ kubectl create -f pod.yaml
Error from server (AlreadyExists): error when creating "pod.yaml": pods "simple-pod" already exists
This happens because the create
operation is idempotent. It will only create the object if it doesn't exist. It won't update the object if it already exists. This creates issues when you are working with existing objects and want to update them using imperative object management. To perform such updates, the imperative way, you will need to keep using commands like kubectl label pod simple-pod app=simple-pod
, kubectl edit pod simple-pod
, etc.
This behavior is not ideal when you want to manage objects in a more reliable and consistent way. This is where declarative object management helps.
Before going into declarative object management, let's delete the simple-pod
pod:
kubectl delete -f pod.yaml
Declarative pod creation
Using declarative object management, you provide a configuration file that describes the desired state of the object. Kubernetes will make sure that the cluster matches the desired state.
Let's understand this with an example.
kubectl apply -f pod.yaml
This will again create a pod named simple-pod
with no labels.
$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
simple-pod 1/1 Running 0 48s <none>
Now, to add a label app=simple-pod
to the pod, you can edit the pod.yaml
file and add the label there, as shown below:
metadata:
name: simple-pod
labels:
app: simple-pod
Now, if you run apply
on the updated configuration again, kubectl will update the pod with the new label:
$ kubectl apply -f pod.yaml
pod/simple-pod configured
$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
simple-pod 1/1 Running 0 2m42s app=simple-pod
The benefit here is that you don't have to worry about the current state of the object. You just provide the desired state and Kubernetes will make sure that the cluster matches the desired state. This is more reliable and easier to manage.
Also, if you run apply
command again, without making any changes, the command will still run successfully.
Delete the simple-pod
pod:
kubectl delete -f pod.yaml
Which one to use?
Declarative object management is the recommended way to manage objects in Kubernetes. This way, you don't have to consistently keep track of the current state of the object, Kubernetes will do that for you. All you need to do is to specify the desired state.