Understanding Pods
Learn about Pods - the smallest deployable unit in Kubernetes. Create your first pod, understand its lifecycle, and view logs.
Understanding Pods
In the Previous Tutorial, we set up Minikube and got our cluster running. Now it's time to meet the most fundamental concept in Kubernetes — the Pod.
A Pod is the smallest thing you can deploy in Kubernetes. Not a container — a Pod. Every container runs inside a Pod. Get comfortable with Pods because everything else in Kubernetes builds on top of them.
What is a Pod?
Hold on, I thought we were running containers. What's a Pod?
Great question! A Pod is a wrapper around one or more containers. Think of it like a cozy little apartment for your container to live in. The apartment provides:
- Shared network: All containers in a Pod share the same IP address and port space. They can chat with each other via
localhost— like roommates yelling across the hallway. - Shared storage: Containers in a Pod can share volumes (like a shared fridge).
- Shared lifecycle: Containers in a Pod start and stop together. If the Pod goes down, all containers inside go down with it.
Why Not Just Containers?
Why does Kubernetes add this extra layer? Can't it just manage containers directly?
It could, but some applications need tightly coupled processes. Imagine a web server that needs a log shipper running alongside it, sharing the same files. Putting them in the same Pod makes total sense — they're like best friends who do everything together.
But most of the time? One container per Pod. The multi-container pattern is the exception, not the rule. So don't overthink it.
Create Your First Pod
Alright, enough theory. Let's deploy something! We'll spin up an nginx web server. First, make sure your Minikube cluster is running:
minikube status
All good? Let's go!
Method 1: Imperative Command
The quick-and-dirty way — great for testing, terrible for production:
kubectl run nginx --image=nginx:latest
Check if it's running:
kubectl get pods
Output:
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 30s
Your first Pod is alive! How cool is that?
Method 2: Declarative YAML (Recommended)
In the real world, Kubernetes uses YAML files. They're version-controlled, reviewable, and repeatable. Think of them as recipes — you write the recipe once, and anyone can follow it.
Create nginx-pod.yaml:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
That looks like a lot of boilerplate for just one container!
Yeah, YAML can be verbose. But let's break it down — it's simpler than it looks:
| Field | Description |
|---|---|
apiVersion: v1 | Pods are part of the core API |
kind: Pod | We're creating a Pod |
metadata.name | The Pod's name (must be unique in the namespace) |
metadata.labels | Key-value pairs for organizing and selecting Pods |
spec.containers | List of containers in this Pod |
containers[].name | Container name (unique within the Pod) |
containers[].image | Docker image to use |
containers[].ports | Ports the container exposes |
Apply it:
kubectl apply -f nginx-pod.yaml
Output:
pod/nginx-pod created
Inspect the Pod
Now let's put on our detective hat and see what's going on with our Pod.
Get Basic Info
kubectl get pods
Add -o wide for more details:
kubectl get pods -o wide
Output:
NAME READY STATUS RESTARTS AGE IP NODE
nginx-pod 1/1 Running 0 1m 10.244.0.5 minikube
Get Full Details
kubectl describe pod nginx-pod
This is the big one. It shows everything: events, conditions, container status, volumes, and more. When things go wrong (and they will), describe is your best friend. Treat it like the doctor's report for your Pod.
Key sections to look at:
Name: nginx-pod
Namespace: default
Status: Running
IP: 10.244.0.5
Containers:
nginx:
Image: nginx:latest
State: Running
Ready: True
Events:
Type Reason Message
---- ------ -------
Normal Scheduled Successfully assigned default/nginx-pod to minikube
Normal Pulled Container image "nginx:latest" already present
Normal Created Created container nginx
Normal Started Started container nginx
View as YAML
See the full Pod specification with current status:
kubectl get pod nginx-pod -o yaml
Pod Lifecycle
Pods go through phases, kind of like us on a Monday morning:
| Phase | Description |
|---|---|
Pending | Pod accepted but not yet running. Could be downloading the image or waiting for a node. (Still in bed.) |
Running | Pod bound to a node, all containers created, at least one running. (At work, doing stuff.) |
Succeeded | All containers terminated successfully (exit code 0). Won't restart. (Job done, going home.) |
Failed | All containers terminated, at least one failed (non-zero exit). (Something went wrong...) |
Unknown | Pod state cannot be determined. Usually a communication issue. (Lost signal. Hello? Anyone?) |
Watch a Pod's status change in real-time:
kubectl get pods --watch
View Logs
Want to see what's happening inside the container? Logs are your window:
kubectl logs nginx-pod
Want to watch logs in real-time (like tail -f)? Add the -f flag:
kubectl logs -f nginx-pod
For Pods with multiple containers, specify which one:
kubectl logs nginx-pod -c nginx
Execute Commands in a Pod
Need to debug something inside the container? You can actually get a shell inside it — like SSH-ing into a server:
kubectl exec -it nginx-pod -- /bin/bash
What does -it mean?
-i stands for interactive (keeps stdin open) and -t allocates a terminal. Together they give you a usable shell. Without them, it'd be like trying to have a conversation through a mailbox.
# Inside the container
cat /etc/nginx/nginx.conf
curl localhost
exit
Run a single command without entering the shell:
kubectl exec nginx-pod -- cat /usr/share/nginx/html/index.html
Access the Pod
Pods have internal IP addresses, but they're not accessible from outside the cluster by default.
So how do I see my app in the browser?
For quick testing, use port forwarding. It's like creating a secret tunnel from your laptop to the Pod:
kubectl port-forward nginx-pod 8080:80
Now open http://localhost:8080 in your browser. Boom — you'll see the nginx welcome page! 🎉
Press Ctrl+C to stop port forwarding.
Pod Networking
Every Pod gets its own IP address. Containers within the same Pod share that IP — they communicate via localhost on different ports.
┌────────────────────────────────────┐
│ Pod (10.244.0.5) │
│ ┌────────────┐ ┌────────────┐ │
│ │ Container A│ │ Container B│ │
│ │ :80 │ │ :8080 │ │
│ └────────────┘ └────────────┘ │
│ │ │ │
│ └──── localhost ───┘ │
└────────────────────────────────────┘
Container A can reach Container B at localhost:8080. From outside the Pod, you'd use 10.244.0.5:8080.
Delete a Pod
kubectl delete pod nginx-pod
Or delete using the YAML file:
kubectl delete -f nginx-pod.yaml
Wait, is the Pod gone forever?
Yep! Pods are like mayflies — they live, they die, they don't come back. When you delete a Pod, it's gone. Poof. That's exactly why you don't usually create Pods directly in production — you use Deployments (coming up in the next tutorial) to manage them and auto-resurrect them when they die.
Pod Restart Policies
Control what happens when a container exits:
apiVersion: v1
kind: Pod
metadata:
name: restart-demo
spec:
restartPolicy: Always # Always | OnFailure | Never
containers:
- name: busybox
image: busybox
command: ["sh", "-c", "echo Hello && sleep 10"]
| Policy | Description |
|---|---|
Always | Always restart (default). Used for long-running services. |
OnFailure | Restart only if exit code is non-zero. Good for Jobs. |
Never | Don't restart. Container runs once. |
Multi-Container Pods
Remember how I said most Pods have just one container? Well, sometimes you need containers that work together like a buddy cop duo. Here's a common pattern:
Sidecar Pattern
A helper container that enhances the main container — like a sidekick:
apiVersion: v1
kind: Pod
metadata:
name: web-with-logging
spec:
containers:
- name: web
image: nginx
volumeMounts:
- name: logs
mountPath: /var/log/nginx
- name: log-shipper
image: busybox
command: ["sh", "-c", "tail -f /logs/access.log"]
volumeMounts:
- name: logs
mountPath: /logs
volumes:
- name: logs
emptyDir: {}
Both containers share the logs volume. The web server writes logs, the sidecar ships them somewhere. Teamwork makes the dream work!
Clean Up
Delete any Pods you created:
kubectl delete pod nginx --ignore-not-found
kubectl delete pod nginx-pod --ignore-not-found
What's Next?
Pods are the building blocks of Kubernetes — but in the real world, you never create them directly. Why? Because if a Pod dies, nobody brings it back. It's like hiring an employee with no backup plan.
In the next tutorial, you'll learn about Deployments — the smart manager that keeps your Pods running, handles scaling, and performs rolling updates without downtime. Let's go!