Skip to content

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:

kubectl apply -f <file-name>.yaml

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)

  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.
Last-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.:

kubectl create pod nginx-pod --image=nginx -n sandbox

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.:

kubectl create pod --image=nginx --dry-run=client > pod.yaml

After reviewing or modifying the file, you can apply it to the cluster.