Your first Pod
What a Pod manifest consists of, what phases it goes through, and two ways to create one.
In the previous lessons you worked through YAML and learned what a cluster is made of. Now it's time to run something of your own in it. Everything that runs in Kubernetes ends up running inside a Pod, so that's where we start: what a Pod manifest is made of, what phases a Pod goes through, and how to create one.
Concepts
- Pod - the smallest unit that Kubernetes runs. One or more containers run inside a Pod.
- Manifest - a YAML file describing a Kubernetes object.
- Namespace - a section of the cluster that isolates objects from each
other by name. Until you specify another one, everything is created in
the
defaultnamespace. - Pod phase - a short summary state of the Pod:
Pending,Running,Succeeded,Failed, orUnknown.
What a Pod is
Containers in the same Pod share a network and an IP address and can mount shared volumes (shared folders inside the Pod).
Usually a Pod has one container. Below we break down what fields make up such a Pod.
Manifest: four required fields
Every manifest starts with the same four fields.
apiVersion: v1
kind: Pod
metadata:
name: hello
spec:
containers:
- name: hello
image: busybox:1.36.1
command: ["sleep", "3600"]
apiVersion - the API version kubectl uses to send the object to the
cluster. For base resources (Pod, Service, ConfigMap, Secret, Namespace)
the value is v1.
kind - the object type. Here it's Pod. Case matters: the cluster won't
accept pod with a lowercase letter and will respond with
no kind "pod" is registered for version "v1".
metadata - the identification block. The required field here is name,
the Pod's name. The name is unique within a namespace: you can't have two
Pods named hello in the same namespace.
spec - the description of the desired state. For a Pod, the main field
is containers, a list of containers. Each container sets at least name
and image.
The command line in the example keeps the container alive: sleep 3600
sleeps for an hour. Without it, busybox runs its default command sh,
which exits right away without a terminal, and kubelet starts restarting
the container in a loop. We cover command and args in detail in the
next lesson.
Container: image and tag
image - the address of the container image with a tag. The tag points to
a specific version, for example busybox:1.36.1.
Without a tag, Kubernetes substitutes the tag latest and pulls the image
again every time the container starts. The image under this tag changes
over time, and the Pod's contents become unpredictable. Use an exact tag
both in a learning cluster and in production.
Kubernetes doesn't check whether the image exists when it accepts the manifest. A Pod with a typo in the tag gets created without errors, and the problem only surfaces later, when kubelet on the node tries to pull the image.
Pod phases
The phase is stored in the Pod object, in the field status.phase. There
are only five values:
Pending- the cluster accepted the Pod, but its containers aren't running yet: the Pod is waiting for a node, or kubelet is pulling the image.Running- the Pod is bound to a node, and at least one container is running, starting, or restarting.Succeeded- all containers exited with code 0 and won't start again.Failed- all containers exited, and at least one with an error.Unknown- the Pod's state couldn't be obtained, usually because contact with the node was lost.
You can print the phase of a single Pod like this:
kubectl get pod hello -o jsonpath='{.status.phase}'
Running
The STATUS column in kubectl get pod doesn't always show the phase. If a
container has a waiting or termination reason, kubectl prints that instead
of the phase. For example, a Pod in phase Pending whose container
kubelet is still preparing shows ContainerCreating. A Pod being deleted
shows Terminating, even though there's no such phase at all.
kubectl get pod hello
NAME READY STATUS RESTARTS AGE
hello 1/1 Running 0 41s
Two ways to create a Pod
Pods are created imperatively or declaratively.
Imperatively, with a single command:
kubectl run hello --image=busybox:1.36.1 -- sh -c 'sleep 3600'
In kubectl run, the Pod name comes first, then the flags, then the
container's command after --. Here sleep 3600 keeps the container alive
for an hour, otherwise busybox exits right away and kubelet starts
restarting it. If Pod hello already exists, running kubectl run again
returns an AlreadyExists error.
Declaratively, from a manifest file:
kubectl apply -f pod.yaml
kubectl apply compares the file with what's already in the cluster. If
the object doesn't exist, it gets created (created). If the object
exists and the file changed, only the difference changes (configured).
If nothing changed, kubectl responds unchanged. That's why you can apply
the same file as many times as you like.
Production uses the declarative way: the manifest lives in git, and every change shows up in the history.
Many people shorten kubectl to the alias k, so the command looks like
k get pod. It's the same command. The only difference is the number of
characters you type.
The other Pod fields (command/args, restartPolicy, the lifecycle) are
covered in the next lesson. Resource limits and securityContext are in
separate lessons in the course.
Common mistakes
- An error in
apiVersionorkind. The server rejects the whole file, no Pod gets created. Read the message to the end: it names the value from your file. - Image without a tag or with a typo in the tag. Without a tag you get an
unpredictable
latest, with a typo the container won't start, and STATUS showsErrImagePullorImagePullBackOff. You can see the reason in the Events section ofkubectl describe pod <name>. - busybox without a command. The container exits right away, STATUS
bounces between
CompletedandCrashLoopBackOff. - Mistaking STATUS for the phase. These are different fields, and the phase alone doesn't always show that the app isn't working: also check READY and RESTARTS.
- You fixed the manifest but didn't send it again with
kubectl apply -f. The cluster knows nothing about the file on your disk. - Running
kubectl runagain with the same name and gettingAlreadyExists. Delete the old Pod (kubectl delete pod <name>) or pick a different name.
Homework
Practice the theory on your own cluster: 3 steps with a check. Set up the cluster with the Kubernetes locally track, the tasks live in the k8s-practice repository.
./run.sh start k8s-first-pod # set up the starting state
./run.sh verify k8s-first-pod # check the current step
In short
- A Pod is the smallest unit you run, with one or more containers sharing a network inside it.
- Every manifest starts with
apiVersion,kind,metadata,spec. - A Pod requires the list
spec.containers, and a container requiresnameandimage. - Specify the image with an exact tag.
- There are five phases:
Pending,Running,Succeeded,Failed,Unknown. They live instatus.phase, and the STATUS column also shows reasons. kubectl runcreates a Pod with a single command,kubectl apply -ffrom a file, and you can repeat it.
What you'll need for the tasks
- Docker, kind v0.31.0 or newer, kubectl v1.35 or v1.36. Each lab's
setup/up.shbrings up the cluster for it. - The commands
kubectl run,kubectl apply -f,kubectl get pods,kubectl describe pod,kubectl delete pod. - Printing a single field with
-o jsonpathand the whole object with-o yaml. - Any text editor for YAML (
nano, VS Code).
Interview-style questions
Interview questions on this topic: 1
Included with practice access, $49 one-time. Get access
Answer out loud or in writing, then reveal the answer and honestly mark whether you knew it.
Done reading?
Mark the lesson as read to move your track progress forward.
Lesson marked as done.
Go through it with an AI agent
The agent explains anything unclear in plain words, gives you 3 labs for this lesson and drills you on interview questions. $49 one-time, lifetime access.
Tell the agent: use MCP izi, give me lesson k8s-basics/first-pod
Progress saved in this browser
Clear your history or open this on your phone, and the marks will be gone. Leave your email and they'll move to your account. No password needed.
Done. moved to your account. You can see your progress on any device. My progress