Your First Pod
A Pod is the smallest deployable unit in Kubernetes. Not a container, a Pod. You do not tell Kubernetes to run a container directly. You tell it to run a Pod, and the Pod runs one or more containers together on the same node, sharing the same network and the same lifecycle.
Think of a Pod as a logical host. Just as a process on a Linux machine can communicate with other processes on the same machine through localhost, containers in the same Pod share a network namespace and can reach each other on 127.0.0.1. They also share mounted volumes. From the containers’ perspective, they are co-located, even though they are processes in a shared kernel.
Writing the Manifest
Pod manifests are built from four required top-level fields. Start with the most basic structure:
# illustrative onlyapiVersion: v1kind: PodapiVersion: v1 means this resource type exists in the core Kubernetes API. kind: Pod is the resource type.
Add metadata with a name:
# illustrative onlyapiVersion: v1kind: Podmetadata: name: my-podAdd spec.containers with one container:
# illustrative onlyapiVersion: v1kind: Podmetadata: name: my-podspec: containers: - name: web image: nginx:1.28Every container needs a name (used for logging and exec targeting) and an image. Here the image is nginx:1.28, a stable web server you can always rely on for practice.
Here is the complete manifest. Create the file:
nano my-pod.yamlapiVersion: v1kind: Podmetadata: name: my-pod labels: app: webspec: containers: - name: web image: nginx:1.28 ports: - containerPort: 80Apply it:
kubectl apply -f my-pod.yamlObserving the Lifecycle
Pods move through a sequence of phases as they start up. List your Pod and watch the phase change:
kubectl get pod my-pod --watchPress Ctrl+C once it reaches Running. The phases you might see are:
Pending means the Pod has been accepted by the API server but its containers have not started yet. The scheduler is assigning a node and the kubelet is pulling the image.
Running means at least one container is running. The container processes are alive.
Succeeded and Failed appear when all containers have exited, with zero or non-zero exit codes respectively.
Unknown means the node the Pod was on stopped reporting to the control plane.
A Pod is in Pending state for 3 minutes. Its image is nginx:1.28. What are the two most likely causes?
Try it: kubectl describe pod my-pod
Reveal answer
Look at the Events section. The most common causes are: no node has enough CPU or memory to schedule the Pod (you will see a scheduler message), or the image cannot be pulled (you will see an ErrImagePull or ImagePullBackOff event). Both are readable from describe.
Inspecting the Running Pod
The same Pod object in the API can be viewed at different levels of detail:
Get a summary of the Pod’s current state:
kubectl get pod my-pod -o wideThe -o wide flag adds the node name and Pod IP. Note the IP address, it is unique within the cluster network and routable from other Pods.
Get the full Pod object as YAML, including all the fields Kubernetes populated at runtime:
kubectl get pod my-pod -o yamlNotice the status field in the output. Kubernetes fills this in as the Pod progresses. It contains the phase, conditions, container states, and the Pod IP.
Describe the Pod to see its event history:
kubectl describe pod my-podExecuting Commands Inside a Pod
Once the Pod is running, you can open a shell inside the container:
kubectl exec -it my-pod -- /bin/shThe -it flags allocate an interactive terminal. The -- separates kubectl flags from the command you are running inside the container. From inside, you can explore the filesystem, check the network, or run diagnostics.
Exit the shell:
exitIf a Pod has multiple containers, specify which one with -c:
kubectl exec -it my-pod -c web -- /bin/shkubectl exec is a diagnostic tool, not a way to make changes to a running application. Any file you write inside a container's filesystem is lost when the container restarts. Configuration changes made via exec are invisible to Kubernetes and will be overwritten on the next deploy. Use exec to look, not to change.
Reading Logs
Fetch the container’s stdout and stderr:
kubectl logs my-podFollow logs in real time with -f:
kubectl logs my-pod -fPress Ctrl+C to stop following. For Pods with multiple containers, use -c to specify which container’s logs you want:
kubectl logs my-pod -c webDeleting the Pod
kubectl delete pod my-podThe Pod is gone. There is no controller watching it, so nothing recreates it. This is the fundamental limitation of bare Pods: they are not self-healing. If the node fails or the Pod is accidentally deleted, it stays deleted.
In production, you almost never create bare Pods. You create Deployments, which manage Pods for you. But every Deployment’s Pod follows the exact same lifecycle you just observed: the same manifest fields, the same phases, the same exec and logs commands. Understanding a bare Pod means understanding every workload on top of it.
You have now created, inspected, exec’d into, read logs from, and deleted a Pod. These five operations cover the majority of day-to-day diagnostic work on a running cluster. The Foundations module ends here. In the Workloads module, you will build on this base and create Deployments that manage Pods automatically.