Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes

Create a Deployment from a Manifest

Learn how to create a Kubernetes deployment from a YAML manifest in this hands-on tutorial. Step-by-step walkthrough, troubleshooting, and what to study next.

Focus: create a deployment from a manifest

Sponsored

Running kubectl run for every pod works in a demo, but it’s fragile — a single node crash wipes your work, and there’s no way to update or roll back. Kubernetes Deployments solve this by providing declarative, self-healing, and update-safe workload management. In this lesson, you’ll learn to create a Deployment from a YAML manifest, the standard way to define how your application should run and stay running.

The Problem This Lesson Solves

When you launch a pod manually with kubectl run nginx --image=nginx, you get a single pod with no guarantees. If the pod dies, it stays dead. If the node fails, the pod is gone. You can’t scale it, update it without downtime, or roll back a bad change. Deployments were designed to fix exactly this: they manage a ReplicaSet that ensures the desired number of pod replicas, and they support rolling updates, rollbacks, and self-healing. Without learning how to create a Deployment from a manifest, you’re hand-cranking infrastructure — one crash away from an outage.

Core Concept / Mental Model

A Deployment is a declarative specification — you write down the desired state, and Kubernetes controllers work to match the live state. Think of it like a recipe:

  • apiVersion: Which version of the Kubernetes API you’re using (e.g., apps/v1).
  • kind: Always Deployment.
  • metadata: A name for your Deployment (must be unique in the namespace).
  • spec.replicas: How many copies (pods) you want to run.
  • spec.selector: How the Deployment finds its pods (labels).
  • spec.template: The pod template — contains the container spec, image, ports, env vars, etc.

Mental model: The Deployment YAML is a contract. You define the what (my app, 3 replicas, port 80), and Kubernetes handles the how (scheduling, health checks, updates).

How It Works Step by Step

1. Write the Manifest

You create a YAML file (typically deployment.yaml) that describes your desired state.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80

2. Apply the Manifest

Use kubectl apply to send the manifest to the Kubernetes API server. This is the standard command for creating or updating resources.

kubectl apply -f deployment.yaml

3. Verify the Deployment

Check that the Deployment was created and pods are running.

kubectl get deployments
kubectl get pods -l app=nginx

4. Under the Hood: What Happens

When you apply the manifest, the Deployment controller creates a ReplicaSet with the number of replicas you specified. The ReplicaSet then creates the individual pods using the pod template. If a pod crashes, the ReplicaSet replaces it. If you update the image later, the Deployment performs a rolling update.

Hands-On Walkthrough

Let’s create a real Deployment from scratch.

Example 1: Basic Nginx Deployment

Save the following as nginx-deployment.yaml:

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

Apply and verify:

kubectl apply -f nginx-deployment.yaml
deployment.apps/nginx-deploy created

kubectl get deployments
NAME            READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deploy    3/3     3            3           10s

kubectl get pods -l app=nginx
NAME                             READY   STATUS    RESTARTS   AGE
nginx-deploy-7d86c8b4b7-5x2fk   1/1     Running   0          10s
nginx-deploy-7d86c8b4b7-8q3gp   1/1     Running   0          10s
nginx-deploy-7d86c8b4b7-x9m4n   1/1     Running   0          10s

Example 2: Custom Image and Environment Variables

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app
        image: my-registry/my-app:v2
        env:
        - name: DATABASE_URL
          value: "postgres://user:pass@db:5432/mydb"
        ports:
        - containerPort: 8080

Example 3: Using kubectl create deployment (Quick Start)

For a quick ad-hoc Deployment, you can use the imperative command:

kubectl create deployment my-nginx --image nginx:1.25 --replicas=2

Pro tip: This generates a manifest that you can export later with kubectl get deployment my-nginx -o yaml > my-nginx.yaml. However, for repeatable infrastructure, always use the declarative YAML file approach.

Compare Options / When to Choose What

Method Command / Manifest Best For
Declarative (YAML file) kubectl apply -f deployment.yaml GitOps, CI/CD, repeatable Deployments
Imperative (kubectl create) kubectl create deployment ... Ad-hoc testing, one-off Deployments
kubectl run (pod) kubectl run nginx --image=nginx Single-pod debugging, no scaling needed
  • Choose YAML when you care about version control, audit history, and team collaboration.
  • Choose kubectl create for quick experiments or learning.
  • Avoid kubectl run for production — use Deployments even for single pods if you want self-healing.

Troubleshooting & Edge Cases

Common Mistake: Wrong apiVersion

kubectl apply -f old-deployment.yaml
error: unable to recognize "old-deployment.yaml": no matches for kind "Deployment" in version "extensions/v1beta1"

Fix: Always use apps/v1 for Deployments. The old extensions/v1beta1 is no longer supported in modern clusters (1.16+).

Common Mistake: Missing selector.matchLabels

If you omit the selector or its labels don’t match the template labels, the Deployment fails to create the ReplicaSet.

# ❌ Wrong: selector missing
spec:
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx

Fix: Add selector.matchLabels that exactly matches the template labels.

Edge Case: Image Pull Secrets

If your image is in a private registry, you must specify imagePullSecrets in the pod template spec, not in the Deployment spec.

spec:
  template:
    spec:
      imagePullSecrets:
      - name: registry-credential

Troubleshooting Pods Not Starting

kubectl describe deployment nginx-deploy
# Look for Conditions and Events
kubectl logs nginx-deploy-7d86c8b4b7-5x2fk
# Check container logs

If pods are stuck in Pending or CrashLoopBackOff, check resource limits, image name typos, or missing registry credentials.

What You Learned & What's Next

You now understand how to create a Deployment from a manifest — the declarative foundation for running applications on Kubernetes. You can:

  • Write a YAML manifest with apiVersion, kind, metadata, spec.replicas, selector, and template.
  • Apply the manifest with kubectl apply -f <file>.
  • Verify the Deployment, ReplicaSet, and pods.
  • Choose between YAML and imperative commands based on use case.
  • Troubleshoot common mistakes like wrong apiVersion or missing selector.

Next up: You’ll learn to inspect and debug a Deployment using kubectl describe, logs, and exec — essential diagnostics for production workloads.

Practice recap

Create a new Deployment from a YAML manifest that runs two replicas of nginx:1.25. Use kubectl apply -f to deploy it. Then, check the pods with kubectl get pods. As a stretch, change replicas from 2 to 3 and re-apply — watch the third pod appear automatically.

Common mistakes

  • Forgetting to include selector.matchLabels or mismatching labels between selector and template.metadata.labels — the Deployment won’t create pods.
  • Using extensions/v1beta1 apiVersion instead of apps/v1 — modern Kubernetes (1.16+) rejects the old version.
  • Typing kubectl delete deployment too early before pods are fully terminated — use kubectl delete -f deployment.yaml for clean removal.
  • Omitting containerPort or using wrong port numbers — the pod still runs but may not be reachable by services.

Variations

  1. Use kubectl create deployment with --dry-run=client -o yaml to generate a manifest without creating anything.
  2. Use kubectl apply -f <file> instead of kubectl create -f <file>apply is idempotent and works for both create and update.
  3. For private images, add imagePullSecrets to the pod template spec, not the Deployment spec level.

Real-world use cases

  • Deploy a web application (e.g., Flask or Express) with 3 replicas behind a Service for load balancing.
  • Run a batch worker as a Deployment with a single replica — the pod auto-restarts on failure, so no job is lost.
  • Set up a canary deployment by applying a second Deployment with a newer image version and a matching Service selector.

Key takeaways

  • A Deployment is a declarative, self-healing workload resource that manages ReplicaSets and pods.
  • Always use apps/v1 apiVersion and include selector.matchLabels that match the pod template labels.
  • Use kubectl apply -f deployment.yaml for idempotent creation and updates (preferred over kubectl create).
  • The replicas field determines the desired number of pods — Kubernetes ensures availability by creating or killing pods as needed.
  • For production, always version-control your YAML manifests (e.g., in a Git repo).
  • Use kubectl describe deployment and kubectl logs to troubleshoot non-running pods.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.