Sign in
← Kubernetes: basics
6 min · easy · Lesson 4 of 11

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

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

Pending image still pulling start Running container running exit 0 error Succeeded all exited with code 0 Failed and didn't recover
The Pod's main path: from Pending to Running, and from there to Succeeded or Failed.

The phase is stored in the Pod object, in the field status.phase. There are only five values:

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

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

What you'll need for the tasks

Done reading?

Mark the lesson as read to move your track progress forward.

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.

Get access for $49

Tell the agent: use MCP izi, give me lesson k8s-basics/first-pod