464

What I understood by the documentation is that:

  • kubectl create
    
    Creates a new k8s resource in the cluster
  • kubectl replace
    
    Updates a resource in the live cluster
  • kubectl apply
    
    If I want to do create + replace (Reference)

My questions are

  1. Why are there three operations for doing the same task in a cluster?
  2. What are the use cases for these operations?
  3. How do they differ from each other under the hood?
Mike
  • 1,080
  • 1
  • 9
  • 25
Suresh Vishnoi
  • 17,341
  • 8
  • 47
  • 55

11 Answers11

513

Those are two different approaches:

Imperative Management

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.

Declarative Management

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.

In laymans They do different things. If the resource exists, kubectl create will error out and kubectl apply will not error out.

Trevor Boyd Smith
  • 18,164
  • 32
  • 127
  • 177
Ara Pulido
  • 5,396
  • 1
  • 11
  • 7
  • 29
    Which one to be used in production then? – Yogesh Jilhawar Jan 09 '18 at 11:10
  • 14
    @YogeshJilhawar both are valid ways to work in production. – gdvalderrama Apr 04 '18 at 15:28
  • 3
    So in essence, it's like whole object modification vs a partial patch? – Ryall Sep 26 '18 at 11:05
  • so use create if you want it to throw an error instead of replacing it for you- right? thats the only benefit i see here – red888 Nov 26 '18 at 00:23
  • 21
    This answer didn't confirm whether these two operations `kubectl create` and `kubectl apply` have identical effect or not. – Nawaz Mar 05 '19 at 08:48
  • 185
    @Nawaz - They do different things. `kubectl create` will throw an error if the resource already exists. `kubectl apply` won't. The difference is that `kubectl create` specifically says "create this thing" whereas `kubectl apply` says "do whatever is necessary (create, update, etc) to make it look like this". – Mr. Llama May 21 '19 at 22:12
  • @YogeshJilhawar I always use `kubectl apply` or `kubectl create ... --save-config` and one of the prime reason for that is the "three-way diff" which is needed to apply patches or updates to your resources. if you simply create by `kubectl create` then the first time you apply an update it won't be applied! Reference: https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#kubectl-apply – garlicFrancium Jun 10 '19 at 20:16
  • 1
    So basically isn't it simpler and better to just use apply since it allows for easily applying incremental changes in future? Also if the configuration doesn't change it can detect and report that as well. Right? – FearlessHyena Jun 17 '19 at 07:28
  • 1
    In practice this isn't always the case: https://github.com/kubernetes/kubernetes/issues/67135 – Chris Stryczynski Aug 16 '19 at 11:55
99

When running in a CI script, you will have trouble with imperative commands as create raises an error if the resource already exists.

What you can do is applying (declarative pattern) the output of your imperative command, by using --dry-run=true and -o yaml options:

kubectl create whatever --dry-run=client -o yaml | kubectl apply -f -

The command above will not raise an error if the resource already exists (and will update the resource if needed).

This is very useful in some cases where you cannot use the declarative pattern (for instance when creating a docker-registry secret).

FillFeile
  • 3
  • 2
Sébastien Dan
  • 1,314
  • 9
  • 9
  • 2
    Alternatively, delete the resource before creating it, with **--ignore-not-found** flag. This will not raise _AlreadyExists_ error. For example: `kubectl delete deployment nginx --ignore-not-found; kubectl create deployment nginx --image=nginx` – Noam Manos Mar 18 '20 at 11:07
  • 3
    I'd wager many people coming in to this question are actually looking for something like the above. It's so idiomatic at this point it should be just incorporated into `kubectl`. – mcouthon Dec 17 '20 at 17:55
  • 3
    --dry-run is deprecated and can be replaced with --dry-run=client – Guillaume Berche Jun 02 '21 at 13:51
  • TBH, I came here looking to see which kubectl command did the above (since it is obviously what you need in CI scenarios). – Jeremy Morren Feb 10 '22 at 17:22
  • I'm curious to know why this command works without " is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. " error. Is this not the same as providing the manifest files directly to `kube apply -n myNamespace -f .` command? I'd appreciate anyone elaborating on this, thanks. – Alex Apr 23 '23 at 16:30
88

One of the finest ways to understand the difference between imperative and declarative patterns for beginner.


enter image description here


Ref : https://www.digitalocean.com/community/tutorials/imperative-vs-declarative-kubernetes-management-a-digitalocean-comic


EDIT

There is error is the example mentioned in image. Please refer comments for better understanding.

You can also refer below example.

Imperative :

  • take a pan.
  • turn on stove.
  • add water, sugar, coffee power, milk in pan
  • wait till the preparation of coffee
  • serve coffee in cup.

Declarative :

  • Tell the waiter you need a cup of coffee. He servers you coffee.

From K8s perspective:

Imperative : You have to manage different resources like pods, service, replica sets, etc by your own.

Declarative : K8 will take care of all the resources, all you need have to specify what is your actual requirement.

Asterisk
  • 27
  • 7
dahiya_boy
  • 9,298
  • 1
  • 30
  • 51
  • 12
    On the declarative side it should be "boiling water" or "boiling water in a kettle". As depicted it still reads as imperative management (fill kettle with water + heat the water in the kettle). – golem Jan 02 '21 at 05:34
  • 3
    Agree with @golem - On the declarative side it should be: 1. A kettle filled with 1L water, 2. Kettle plugged in and water boiling at 100 degrees C. – rkrishnan Feb 25 '21 at 10:39
  • 10
    I'm slightly amazed that someone put in all that effort to create that comic then got the content completely wrong?! Both of the boiling water examples are imperative. Also, why use a kettle in one and a pot in the other? A better example: Imperative: - Get pot - Fill with 1L of water - Heat to 100 degrees. Declarative: - A pot with 1L of water at 100 degrees – Matt Jun 17 '21 at 23:46
  • 1
    @Matt Check updated answer. pls feel free to edit the asnwer if you found something wrong or you can edit it in more descriptive manner. – dahiya_boy Jun 18 '21 at 09:56
  • tea or coffee example would be better - boiling water in most cases is just an inter-step – Sławomir Lenart Sep 21 '22 at 11:53
  • Imperative is centered on verbs and adverbs, declarative is centered on nouns and adjectives. So the declarative of "**fill** a kettle **boil** the water" is "**hot** water". – Philip Couling Jul 26 '23 at 05:01
53

Just to give a more straight forward answer, from my understanding:

apply - makes incremental changes to an existing object
create - creates a whole new object (previously non-existing / deleted)


Taking this from a DigitalOcean article which was linked by Kubernetes website:

We use apply instead of create here so that in the future we can incrementally apply changes to the Ingress Controller objects instead of completely overwriting them.

mirekphd
  • 4,799
  • 3
  • 38
  • 59
User9123
  • 734
  • 5
  • 7
  • Is it? like when we use docker-compose: + use `apply` like `docker-compose up -d` + use `create` like `docker-compose up -d --build`? – Whoiskp May 28 '20 at 14:14
  • 6
    I think it's important to clarify that `apply` will still create the object if it doesn't exist. – grt3kl Sep 30 '20 at 12:30
  • 2
    Thank you for this. I just wanted to know the practical difference and wasn't interested in a lecture on declarative vs. imperative. – Gi0rgi0s Nov 27 '21 at 01:41
  • 2
    @Gi0rgi0s ikr? blah blah blah imperative, blah blah blah declarative. Please just tell me what the commands do ... – timgeb Feb 09 '22 at 09:05
41
┌─────────┬───────────────────────┬────────────────────────┐
│ command │ object does not exist │ object already exists  │
├─────────┼───────────────────────┼────────────────────────┤
│ create  │ create new object     │          ERROR         │ 
│         │                       │                        │
│ apply   │ create new object     │ configure object       │
│         │ (needs complete spec) │ (accepts partial spec) │
│         │                       │                        │
│ replace │         ERROR         │ delete object          │
│         │                       │ create new object      │
└─────────┴───────────────────────┴────────────────────────┘
timgeb
  • 76,762
  • 20
  • 123
  • 145
20

These are imperative commands :

kubectl run = kubectl create deployment

Advantages:

  • Simple, easy to learn and easy to remember.
  • Require only a single step to make changes to the cluster.

Disadvantages:

  • Do not integrate with change review processes.
  • Do not provide an audit trail associated with changes.
  • Do not provide a source of records except for what is live.
  • Do not provide a template for creating new objects.

These are imperative object config:

kubectl create -f your-object-config.yaml

kubectl delete -f your-object-config.yaml

kubectl replace -f your-object-config.yaml

Advantages compared to imperative commands:

  • Can be stored in a source control system such as Git.
  • Can integrate with processes such as reviewing changes before push and audit trails.
  • Provides a template for creating new objects.

Disadvantages compared to imperative commands:

  • Requires basic understanding of the object schema.
  • Requires the additional step of writing a YAML file.

Advantages compared to declarative object config:

  • Simpler and easier to understand.
  • More mature after Kubernetes version 1.5.

Disadvantages compared to declarative object configuration:

  • Works best on files, not directories.
  • Updates to live objects must be reflected in configuration files, or they will be lost during the next replacement.

These are declarative object config

kubectl diff -f configs/

kubectl apply -f configs/

Advantages compared to imperative object config:

  • Changes made directly to live objects are retained, even if they are not merged back into the configuration files.
  • Better support for operating on directories and automatically detecting operation types (create, patch, delete) per-object.

Disadvantages compared to imperative object configuration:

  • Harder to debug and understand results when they are unexpected.
  • Partial updates using diffs create complex merge and patch operations.
Community
  • 1
  • 1
Zoe The Paranoid
  • 472
  • 5
  • 11
5

This can be concluded with simple examples:-

Lets create a simple yaml for deploying a pod having image of nginx in it.

pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
    type: front-end
spec:
  containers:
    - name: nginx-container
      image: nginx

now we create a pod using kubectl command -

kubectl create -f pod.yaml

Now a pod named nginx is created , you can get info about pods running by -

kubectl get pods -o wide

and detailed view about the pod by

kubectl describe pod nginx

Now if i want to make some changes in my pod.yaml file like this -

pod.yaml

apiVersion: v1 
kind: Pod 
metadata:
  name: nginx
  labels:
    app: nginx
    tier: frontend
    title: frontend
spec:
  containers:
    - name: nginx
      image: nginx

now try the command

kubectl create -f pod.yaml

to apply the changes in pod.yaml.

it will have a ouput -

Error from server (AlreadyExists): error when creating "pod.yaml": pods "nginx" already exists

but with the command -

kubectl apply -f pod.yaml

output is -

pod/nginx configured

As in first comment it is very detailed explained that create like imperative commands are focused on their assigned tasks, you can not assign them further tasks to tweak the world of clusters but apply like declarative commands are designed to make it work to tweak the world of clusters.

TeraByte
  • 71
  • 1
  • 6
3

The explanation below from the official documentation helped me understand kubectl apply.

This command will compare the version of the configuration that you’re pushing with the previous version and apply the changes you’ve made, without overwriting any automated changes to properties you haven’t specified.

kubectl create on the other hand will create (should be non-existing) resources.

f01
  • 1,738
  • 1
  • 18
  • 21
2

kubectl create can work with one object configuration file at a time. This is also known as imperative management

kubectl create -f filename|url

kubectl apply works with directories and its sub directories containing object configuration yaml files. This is also known as declarative management. Multiple object configuration files from directories can be picked up. kubectl apply -f directory/

Details :
https://kubernetes.io/docs/tasks/manage-kubernetes-objects/declarative-config/ https://kubernetes.io/docs/tasks/manage-kubernetes-objects/imperative-config/

Noman Khan
  • 920
  • 5
  • 12
0

This question is very deep and a good one,Next is my thinking on this problem:

K8s has three resource management methods

  • Command Based Object Management: directly use commands to operate kubernetes resources. eg:

    kubectl run nginx-pod --image=nginx:1.17.1 --port=80

  • Command Type Object Configuration: operate Kubernetes resources through command configuration and configuration files. eg:

    kubectl create/patch -f nginx-pod.yaml

  • Declarative Object Configuration: operate kubernetes resources through the apply command and configuration file. eg:

    kubectl apply -f nginx-pod.yaml

Type Operate Object Suitable for environment Advantage disadvantage
Command Based Object Management Object test env Simple Only active objects can be operated, but not audited or tracked
Command Type Object Configuration File develop evn Can be audited and tracked When the project is large, there are many configuration files and the operation is troublesome
Declarative Object Configuration Directory develop evn Support directory operations It is difficult to debug under unexpected circumstances
qingmu
  • 402
  • 2
  • 12
-4

We love Kubernetes is because once we give them what we want it goes on to figure out how to achieve it without our any involvement.

"create" is like playing GOD by taking things into our own hands. It is good for local debugging when you only want to work with the POD and not care abt Deployment/Replication Controller.

"apply" is playing by the rules. "apply" is like a master tool that helps you create and modify and requires nothing from you to manage the pods.

Ankur Kothari
  • 822
  • 9
  • 11
  • This answer isn’t all that helpful. It also implies that create command can only be used to create a Pod. The command can create any resource like ReplicaSet, Deployment, Namespace, and more. Plus I think it’s more common to use “kubectl run” when imperatively creating a Pod. Another point, Pods can’t be updated with apply. They 1st must be deleted. – brianNotBob Jul 31 '21 at 18:47