kubectl create/replace vs. kubectl apply – which one to use?

Both are valid methods of managing Kubernetes objects, but there is a difference in the way they behave when objects are modified by multiple writers. It is the desired behavior, in such scenarios, that should drive the choice between the two.

There are three different ways to manage objects in Kubernetes. The diagram below describes these three methods briefly.

Now let us see how the Imperative and the Declarative object configuration methods work in reality, through a simple example.

In this example, we will create two Deployment objects (one using the Imperative method and the other using the Declarative method) and compare their live object configs at different stages.

“last-applied-configuration” section (shown with the blue arrow above) is not there in the live object config for the Deployment created by the Imperative method. “last-applied-configuration” section has a record of all the key/values which were explicitly defined in the YAML config file. It is important to note that the fields which are not explicitly defined in the YAML config files, will have default values set in the object live config.  For example: the “replicas” field value is set to 1 (default value) since the config files have no mention of “replicas” .

Now we will run the imperative command : kubctl scale -–replicas=3 ……”   on both the Deployment objects created in the previous step and note the changes to the object live configs.

The object live configs reflect the change  in the number of replicas to 3 for both the Deployment objects. “last-applied-configuration” section for the declarative Deployment object records no change due to “kubectl scale” command execution.

Now we will run the “kubectl replace …” and the “kubectl apply…” commands on the imperative object and the declarative object respectively. We will use a new version of the config files for this purpose. Let us take a closer look at the config files.

Merging changes to the object live config (key/value) based on rules in the scenarios like above, where another writer (“kubectl scale..” in this case) is involved, is a unique characteristic of the Declarative object management method. Imperative object management method does not use merging/patching techniques.

Rules for merging changes to complex field types e.g. map/list are far more complex. Please refer to https://kubernetes.io/docs/home/ for more information on Imperative and Declarative object management.

It is important to note that the use of Imperative and Declarative methods together to manage a set of Kubernetes objects may result in unpredictable object config (including errors) in some cases and it should be avoided as much as possible.

YAML fundamentals for Kubernetes

YAML is a human friendly data serialization standard for all programming languages. It is a simple, text/human-readable annotation format that can be used to store/represent data.

We don’t really need to know the entire set of complex YAML syntax in order to work with the K8S YAML object definition files.

Once we grasp the below concepts, we are good to go:

Key-Value pairs/Maps:

Represented by key: value (mind the space after the colon).

Any one such pair is nothing but a dictionary at its simplest form (single element dictionary). More than one such pairs will form a multi-element dictionary.

YAML

Fruits: Banana 
Vegetables: Carrot

Interpretation
{‘Fruits’: ‘Banana’, ‘Vegetables’: ‘Carrot’}
It is a Dictionary with two key: value pairs.

Arrays/Lists:


Every individual element of a list/array starts with a – (dash) followed by a space. Arrays can be used as values within a dictionary.

YAML

- Banana
- Carrot

Interpretation
[‘Banana’, ‘Carrot’]

YAML

Fruits:
 - Banana
 - Orange
 - Apple

Interpretation

{‘Fruits’: [‘Banana’, ‘Orange’, ‘Apple’]}

It is a dictionary with a single key: value pair. The value being an array with 3 elements.

It is possible to have a complex combination of one or more Lists and/or Maps in order to form:

I. maps of maps
II. maps of lists
III. lists of lists
IV. lists of maps

Multiple levels of nesting can be represented by appropriate indentation.

YAML

Identity:
    Name: John Doe
    Age: 42
    Sex: M
    Skill:
       - Java
       - C++

Interpretation
{‘Identity’: {‘Age’: 42,’Name’: ‘John Doe’, ‘Sex’: ‘M’,
‘Skill’: [‘Java’, ‘C++’]}}

It is a nested dictionary. The top level dictionary has one element having a key named “Identity” . Its value being another dictionary inside with four key: value pairs. The value of the 4th key named “Skill” (inside the nested dictionary) is an array/list.

Note: YAML does not allow the use of tabs while creating YAML files; spaces are allowed instead.

Useful Links:

https://yaml.org/
https://en.wikipedia.org/wiki/YAML
http://yaml-online-parser.appspot.com/