Skip to content

Imperative Deployments

How do I create a Deployment using kubectl?

In Kubernetes, a Deployment is a higher-level workload API object that provides declarative updates for Pods and ReplicaSets. When you create a Deployment, you are instructing the Kubernetes control plane's Deployment Controller to change the cluster's actual state to match your specified desired state at a controlled rate.

To create a Deployment using kubectl, you must choose between two fundamentally different architectural approaches: Declarative Object Configuration (the production standard) and Imperative Commands (best for quick testing).

Method 1: Declarative Object Configuration (Best Practice)

For production environments, the recommended technique is declarative object configuration. In this model, you do not instruct Kubernetes how to perform an operation; instead, you define the complete desired state of the Deployment in a YAML or JSON manifest file, and Kubernetes figures out how to make it a reality.

1. Create the Manifest You define the Deployment specification in a YAML file (e.g., deployment.yaml). This file includes critical fields like the apiVersion, kind, metadata, and the spec which outlines the Pod template and the number of replicas.

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

2. Apply the Manifest To submit this desired state to the Kubernetes API server, use the kubectl apply command:

bash
kubectl apply -f deployment.yaml

Architectural Reasoning: Why use apply instead of create? When you use kubectl apply, Kubernetes writes the contents of your configuration file into a special annotation on the live object called kubectl.kubernetes.io/last-applied-configuration. This mechanism allows kubectl to calculate precise merge patches during future updates, enabling you to manage your infrastructure as code (stored in Git) while safely retaining changes made by other controllers (like HorizontalPodAutoscalers).

Method 2: Imperative Commands (Quick Start)

If you are learning Kubernetes, running a one-off task, or experimenting in a local development environment, you can operate directly on the cluster using imperative commands.

This method bypasses YAML files entirely and submits the intent directly via command-line flags.

bash
kubectl create deployment nginx-deployment --image nginx:1.14.2

Operational Warning: While imperative commands are fast, they have the lowest learning curve but provide no history or audit trail of previous configurations. Furthermore, Kubernetes strictly warns against mixing management techniques. If you create an object using imperative commands and later try to manage it declaratively, you will experience undefined behavior.

Verifying the Deployment Architecture

Regardless of which method you use, the creation of a Deployment triggers a specific architectural workflow in the control plane. The Deployment controller does not manage Pods directly; instead, it creates a ReplicaSet. The ReplicaSet is then responsible for creating and maintaining the actual Pod objects.

You can observe this hierarchy and verify your creation using kubectl:

  1. Check the Deployment:
    bash
    kubectl get deployments
    This displays the number of READY replicas, the UP-TO-DATE replicas matching your desired state, and the AVAILABLE replicas serving traffic.
  2. Check the underlying ReplicaSet:
    bash
    kubectl get rs
    Notice that the ReplicaSet's name is formatted as [DEPLOYMENT-NAME]-[HASH] (e.g., nginx-deployment-75675f5897), where the hash is generated from the Deployment's Pod template.
  3. Check the Pods:
    bash
    kubectl get pods --show-labels
    This shows the actual running instances of your application. You will see that the Deployment controller automatically injected a pod-template-hash label into your Pods to prevent child ReplicaSets from overlapping.

Based on Kubernetes v1.35 (Timbernetes). Changelog.