Kubernetes provides several commands that appear to do the same thing, and two of the most commonly confused are kubectl apply and kubectl create.

Both commands can create Kubernetes resources. However, there is an important difference:

  • kubectl create creates a resource that does not already exist.
  • kubectl apply declares the desired configuration of a resource and can create it or apply changes to an existing resource.

If you run kubectl create for a resource that already exists, Kubernetes normally returns an AlreadyExists error. Run kubectl apply against an existing resource, and Kubernetes instead attempts to reconcile the resource with the configuration you supplied.

That's why kubectl apply is commonly used when Kubernetes manifests are stored in source control and repeatedly applied as the application's configuration changes.

Is kubectl create imperative or declarative?

One reason the difference between kubectl apply and kubectl create can be confusing is that create supports more than one style of resource creation.

You can create a resource imperatively by describing it directly on the command line:

kubectl create deployment mydeployment --image=nginx

You can also tell kubectl create to create resources described in a manifest:

kubectl create -f mydeployment.yaml

The important characteristic of create is that it is a creation operation. The resource is expected not to exist yet.

By comparison, kubectl apply is designed around declarative configuration. You describe the desired resource in a manifest and apply that configuration to the cluster:

kubectl apply -f mydeployment.yaml

If the resource doesn't exist, apply can create it. If it does exist, apply can update it.

Kubectl apply example

Consider the following Kubernetes Deployment manifest. It describes an Nginx Deployment with three replicas:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mydeployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80

Save the manifest as mydeployment.yaml and apply it with the following command:

kubectl apply -f mydeployment.yaml

If the Deployment does not already exist, the output will look similar to this:

deployment.apps/mydeployment created

Now inspect the Deployment:

kubectl get deployment mydeployment

After the Pods become ready, the output will look similar to this:

NAME           READY   UP-TO-DATE   AVAILABLE   AGE
mydeployment   3/3     3            3           1m

The important point isn't the exact output or age of the Deployment. It's that kubectl apply created the resource because it didn't already exist.

Kubectl create example

Now suppose we attempt to create another Deployment named mydeployment:

kubectl create deployment mydeployment --image=nginx

Kubernetes rejects the request because a Deployment with that name already exists:

Error from server (AlreadyExists): deployments.apps "mydeployment" already exists

This behavior illustrates one of the fundamental differences between kubectl create and kubectl apply.

The create command expects to create a new resource. It isn't intended to reconcile changes with the existing mydeployment Deployment.

However, if we create a Deployment with a new name, the command succeeds:

kubectl create deployment yourdeployment --image=nginx

The result is:

deployment.apps/yourdeployment created

That's a perfectly reasonable use of kubectl create. For quick, one-off resource creation from the command line, the imperative command is convenient and easy to understand.

Update a resource with kubectl apply

Now let's demonstrate where kubectl apply becomes particularly useful.

Our original mydeployment.yaml manifest requested three replicas. Suppose the application needs another replica.

Change replicas from 3 to 4:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mydeployment
  labels:
    app: nginx
spec:
  replicas: 4
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80

Then apply the manifest again:

kubectl apply -f mydeployment.yaml

This time, the Deployment already exists. Instead of returning an AlreadyExists error, kubectl apply applies the changed configuration:

deployment.apps/mydeployment configured

Check the Deployment again:

kubectl get deployment mydeployment

Once the additional Pod becomes available, the output will look similar to this:

NAME           READY   UP-TO-DATE   AVAILABLE   AGE
mydeployment   4/4     4            4           10m

The same manifest that originally created the Deployment has now been used to change its desired state from three replicas to four.

Kubectl create with a YAML file

It's worth emphasizing that YAML manifests aren't exclusive to kubectl apply.

You can also run:

kubectl create -f mydeployment.yaml

If mydeployment does not exist, Kubernetes creates it.

Run the same command again, however, and the operation fails because create expects a new resource.

That's different from:

kubectl apply -f mydeployment.yaml

which is designed to apply the manifest's desired configuration repeatedly as that configuration evolves.

Kubectl apply vs. create comparison

Behavior kubectl create kubectl apply
Create a new resource Yes Yes
Use a YAML manifest Yes Yes
Create directly from command-line arguments Yes Not its primary usage
Resource can already exist No Yes
Apply changes to an existing resource No Yes
Best suited to repeatedly managed manifests No Yes

When should you use kubectl create?

Use kubectl create when the operation you're performing is fundamentally about creating a new Kubernetes resource.

It's especially convenient for quick command-line operations such as:

kubectl create deployment nginx-demo --image=nginx

It can also be useful when you deliberately want creation to fail if a resource with the same name already exists.

When should you use kubectl apply?

Use kubectl apply when a manifest represents the desired configuration of a resource and you expect to manage that resource over time.

The workflow becomes straightforward:

  1. Define the Kubernetes resource in YAML.
  2. Store the manifest with your application's configuration.
  3. Run kubectl apply to create the resource.
  4. Edit the manifest when the desired configuration changes.
  5. Run kubectl apply again to apply those changes.

That repeatability is the main reason kubectl apply is so closely associated with declarative Kubernetes resource management.

Kubectl apply vs. create explained

The difference between kubectl create and kubectl apply ultimately comes down to intent.

kubectl create says: Create this resource.

kubectl apply says: Make the resource's configuration match this declared state.

Both commands can create Kubernetes resources, and both can work with manifest files. But if you expect to maintain a resource declaratively and apply configuration changes to it over time, kubectl apply is the command designed for that workflow.