Declarative & Imperative
When working with Kubernetes, there are two ways of creating objects such as Pods, you can do so declaratively or imperatively.
Note
Most Kubernetes objects can be created in both ways, but there are some exceptions. For instance, a ResourceQuota object must be created declaratively, it has no kubectl create imperative equivalent.
The declarative approach
The declarative approach involves defining the desired state of a cluster in configuration files before applying those files.
You write a YAML file that describes the end state that you want and Kubernetes determines the steps required to achieve and maintain it.
E.g.:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
namespace: sandbox
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx
Then, using kubectl, you deploy the object to the cluster:
Last applied annotation
After using kubectl apply -f commands, Kubernetes creates or updates the object and if successful, stores its configurations in JSON format, under the kubectl.kubernetes.io/last-applied-configuration annotation. (1)
- Annotations are key-value pairs that are used to attach non-identifying metadata to Kubernetes objects.
Later, when applying changes, kubectl compares the new desired configuration with both the live configuration and the previously applied configuration.
It uses this three-way comparison to determine which fields were added, changed, or removed, and then updates the resource accordingly.
The imperative approach
The imperative approach consists of directly instructing Kubernetes to perform a specific operation.
Unlike the declarative approach, instead of describing the desired end state in a configuration file, you use a command that tells Kubernetes what to create, update, or delete.
E.g.:
Comparing both
The imperative approach is convenient for quick operations and troubleshooting, however, it is difficult to reproduce and maintain because the commands used to create or modify an object will not be recorded as configuration.
The declarative approach is generally better because the configuration files can be version-controlled, reviewed, reused, and applied consistently across clusters.
| Declarative | Imperative |
|---|---|
| Describes the desired state | Specifies an action to perform |
| Uses YAML files | Uses kubectl commands |
| Configuration can be version-controlled | Local CLI history is the only record |
| Suitable for repeatable deployments | Convenient for quick or one-off changes |
| Kubernetes determines how to reach the desired state | You directly request a specific operation |
Generating YAML from imperative commands
When using imperative commands, you can perform a dry run to preview the generated resource without applying any changes to the cluster.
You can save the output to a file and use it as the starting point for a declarative configuration.
E.g.:
After reviewing or modifying the file, you can apply it to the cluster.