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
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: AlwaysDeployment.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, andtemplate. - 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.matchLabelsor mismatching labels betweenselectorandtemplate.metadata.labels— the Deployment won’t create pods. - Using
extensions/v1beta1apiVersion instead ofapps/v1— modern Kubernetes (1.16+) rejects the old version. - Typing
kubectl delete deploymenttoo early before pods are fully terminated — usekubectl delete -f deployment.yamlfor clean removal. - Omitting
containerPortor using wrong port numbers — the pod still runs but may not be reachable by services.
Variations
- Use
kubectl create deploymentwith--dry-run=client -o yamlto generate a manifest without creating anything. - Use
kubectl apply -f <file>instead ofkubectl create -f <file>—applyis idempotent and works for both create and update. - For private images, add
imagePullSecretsto 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/v1apiVersion and includeselector.matchLabelsthat match the pod template labels. - Use
kubectl apply -f deployment.yamlfor idempotent creation and updates (preferred overkubectl create). - The
replicasfield 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 deploymentandkubectl logsto troubleshoot non-running pods.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.