Pods: The Smallest Deployable Unit
A Pod is the smallest deployable unit Kubernetes manages. Before learning Deployments, Services, scaling, rollouts, or troubleshooting, you need to understand what a Pod is and what Kubernetes is actually running.
What this lesson covers
This lesson introduces Pods as the basic workload unit in Kubernetes.
By the end, you should understand:
- What a Pod is
- How a Pod relates to a container
- Why Kubernetes usually manages Pods through higher-level objects
- How to create a simple Pod
- How to inspect Pod status
- How to view Pod logs
- How to exec into a Pod
- How to expose a Pod locally for testing
- How to delete a Pod
- Why manually created Pods are not usually how production workloads are managed
The short version
A Pod is a wrapper around one or more containers.
Most beginner examples use one container per Pod, but a Pod can contain multiple containers when those containers need to be tightly coupled and share the same network and storage context.
In normal application deployments, you usually do not create standalone Pods directly. You create a higher-level object like a Deployment, and that Deployment creates and manages Pods for you.
Pod vs container
A container is the running application process created from an image.
A Pod is the Kubernetes object that holds that container.
Container: The application process and its runtime environment. Pod: The Kubernetes wrapper around one or more containers.
If Kubernetes is managing a containerized application, it is doing that through a Pod.
What a Pod provides
A Pod gives containers a shared execution environment.
Containers in the same Pod share:
- The same network namespace
- The same Pod IP address
- The ability to communicate over localhost
- Shared volumes, if configured
- The same scheduling lifecycle
That last point is important. Containers in the same Pod are scheduled together. They are meant to be tightly related.
Why most Pods have one container
Most application Pods contain one main application container.
That keeps the model simple:
- One application process
- One container image
- One set of logs
- One primary lifecycle
Multi-container Pods exist, but they are usually used for helper patterns such as sidecars, proxies, log shippers, or tightly coupled support containers.
Pods are disposable
Pods are not meant to be long-lived pets. They are meant to be replaceable.
A Pod can disappear because:
- The node failed
- The Pod was deleted
- A Deployment rolled out a new version
- A health check failed
- The scheduler moved workload elsewhere
- The cluster needed to reclaim resources
This is why Kubernetes uses higher-level controllers like Deployments to keep the desired number of Pods running.
Before you start the lab
This lab assumes:
- Docker Desktop is running
- Your kind cluster exists
- kubectl is installed
- Your current context is kind-stealth-k8s-lab
Check your context:
kubectl config current-context
You should see:
kind-stealth-k8s-lab
Check your node:
kubectl get nodes
If your cluster no longer exists, recreate it:
kind create cluster --name stealth-k8s-lab
Step 1: Create a simple Pod imperatively
The fastest way to create a simple Pod is with kubectl run.
kubectl run nginx-pod-lab --image=nginx:latest
This tells Kubernetes to create a Pod named nginx-pod-lab using the nginx:latest container image.
What this command does
- Creates a Pod object
- Uses the nginx container image
- Asks Kubernetes to schedule the Pod onto a node
- Starts the container inside the Pod
This is called an imperative command because you directly told Kubernetes to create something from the command line.
Step 2: List Pods
Run:
kubectl get pods
You should see something like:
NAME READY STATUS RESTARTS AGE nginx-pod-lab 1/1 Running 0 30s
What to look for
- READY: How many containers are ready compared to how many are expected.
- STATUS: The current Pod phase or status summary.
- RESTARTS: How many times the container restarted.
- AGE: How long the Pod has existed.
For this simple Pod, 1/1 means one container is expected and one container is ready.
Step 3: Show more detail with wide output
Run:
kubectl get pods -o wide
This gives you more information, usually including:
- Pod IP
- Node where the Pod is running
- Readiness gates, if any
In a local kind cluster, the node name will usually be something like:
stealth-k8s-lab-control-plane
Step 4: Describe the Pod
Run:
kubectl describe pod nginx-pod-lab
The describe output is one of your most useful troubleshooting views.
What to look for
- Pod name and namespace
- Node placement
- Pod IP
- Container image
- Container state
- Restart count
- Events at the bottom
The events section often tells you what Kubernetes did: scheduled the Pod, pulled the image, created the container, and started the container.
Step 5: View Pod logs
Run:
kubectl logs nginx-pod-lab
nginx may not show much until it receives traffic. That is normal.
Logs come from the container running inside the Pod. If a Pod has multiple containers, you may need to specify which container you want logs from.
Step 6: Exec into the Pod
Open a shell inside the container:
kubectl exec -it nginx-pod-lab -- /bin/sh
Inside the container, run:
hostname ps ls exit
This shows that you can inspect the running container through Kubernetes.
This is useful for learning and emergency inspection, but you should not treat containers like traditional servers that you manually repair from the inside.
Step 7: Port-forward to the Pod
Use port-forwarding to test the nginx Pod from your local browser:
kubectl port-forward pod/nginx-pod-lab 8080:80
Keep that PowerShell window open. Then open a browser and go to:
http://localhost:8080
You should see the nginx welcome page.
Press Ctrl+C in PowerShell to stop the port-forward session.
Step 8: Check logs again after traffic
After visiting the nginx page, check logs again:
kubectl logs nginx-pod-lab
You should now see nginx access log entries.
Step 9: View the Pod as YAML
Kubernetes resources are API objects. You can view the Pod in YAML:
kubectl get pod nginx-pod-lab -o yaml
The output will be long. For now, look for these major sections:
- apiVersion
- kind
- metadata
- spec
- status
What these sections mean
- apiVersion: Which Kubernetes API version this object uses.
- kind: What type of Kubernetes object this is.
- metadata: Name, namespace, labels, and system-managed information.
- spec: The desired configuration for the Pod.
- status: What is currently happening with the Pod.
Step 10: Create a Pod from YAML
Imperative commands are useful for quick testing, but Kubernetes work usually moves toward YAML files.
Create a new file named:
pod-lab.yaml
Paste this into the file:
apiVersion: v1
kind: Pod
metadata:
name: nginx-yaml-pod-lab
labels:
app: nginx-yaml-pod-lab
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Apply the file:
kubectl apply -f pod-lab.yaml
Check the Pod:
kubectl get pods
You should now see both Pods:
nginx-pod-lab nginx-yaml-pod-lab
Step 11: Compare the two Pods
Describe the YAML-created Pod:
kubectl describe pod nginx-yaml-pod-lab
Then view its YAML:
kubectl get pod nginx-yaml-pod-lab -o yaml
The important point is that both methods created a Pod object. The YAML method is more repeatable because the desired configuration is saved in a file.
Step 12: Delete the first Pod
Delete the Pod you created imperatively:
kubectl delete pod nginx-pod-lab
Check Pods:
kubectl get pods
Notice that the Pod does not come back.
Why it does not come back
You created a standalone Pod. There is no Deployment or controller watching it and saying, “Keep one copy running.”
When you delete a standalone Pod, it is gone.
Step 13: Delete the YAML-created Pod
Delete it using the YAML file:
kubectl delete -f pod-lab.yaml
Confirm it is gone:
kubectl get pods
This removes the object defined in the YAML file.
Common Pod statuses
As you work with Pods, you will see different status values. Some common ones include:
- Pending: Kubernetes accepted the Pod, but it has not started running yet.
- Running: The Pod is assigned to a node and at least one container is running.
- Succeeded: Containers completed successfully and will not restart.
- Failed: Containers terminated with failure.
- CrashLoopBackOff: A container keeps crashing and Kubernetes is backing off before restarting it again.
- ImagePullBackOff: Kubernetes cannot pull the container image.
The status alone does not always tell the full story. Use describe, logs, and events to understand what is happening.
Quick troubleshooting flow for Pods
When a Pod does not work, start with:
kubectl get pods kubectl get pods -o wide kubectl describe pod <pod-name> kubectl logs <pod-name> kubectl get events --sort-by=.metadata.creationTimestamp
This usually answers:
- Does the Pod exist?
- Is it running?
- Which node is it on?
- Did the image pull successfully?
- Did the container start?
- Is the app crashing?
- What did Kubernetes report in events?
What you just learned
In this lesson, you:
- Created a Pod with kubectl run
- Listed Pods
- Used wide output
- Described a Pod
- Viewed Pod logs
- Used exec for inspection
- Used port-forward for local testing
- Viewed a Pod as YAML
- Created a Pod from YAML
- Deleted standalone Pods
- Learned why controllers matter
Check your understanding
Use these questions to test whether the Pod concepts made sense.
- What is the smallest deployable unit Kubernetes manages?
- Does Kubernetes run containers directly by themselves, or inside Pods?
- Can a Pod contain more than one container?
- When should multiple containers be placed in the same Pod?
- Why are Pods considered disposable?
- What does READY 1/1 mean for a Pod?
- What command gives detailed troubleshooting information about a Pod?
- Where should you look in describe output when a Pod fails to start?
- What is the difference between spec and status?
- Why does a standalone Pod not come back after you delete it?
- Why is YAML useful for creating Kubernetes resources?
- What are two commands you would run when troubleshooting a broken Pod?
Answer key
- A Pod.
- Kubernetes runs containers inside Pods.
- Yes.
- When the containers are tightly coupled and need to share the same network or storage context.
- Because they can be deleted, replaced, rescheduled, or recreated as part of normal Kubernetes operation.
- One container is expected and one container is ready.
- kubectl describe pod <pod-name>.
- The events section at the bottom.
- spec is the desired configuration. status is what Kubernetes reports is currently happening.
- Because no controller is managing it and recreating it.
- YAML makes the desired configuration repeatable and reviewable.
- Examples: kubectl describe pod <pod-name>, kubectl logs <pod-name>, kubectl get events, kubectl get pods -o wide.