A pod is the smallest deployable and schedulable unit in Kubernetes. When you deploy an instance of a microservice, such as a web server, Kubernetes does not run the container directly. Instead, it runs the container inside a pod, which provides the execution context for that workload, including networking, storage volumes, and runtime configuration.

Each pod consists of one or more containers. While single-container pods are the most common, Kubernetes also supports multi-container pods for advanced use cases where containers must work together and share resources. This raises an important question: what is the difference between a container and a pod, and why does Kubernetes introduce this extra abstraction?

Why Kubernetes uses pods

Containers bundle application code and dependencies, making them ideal for packaging microservices. However, in a distributed system running at scale, Kubernetes must also solve problems related to networking, scheduling, scaling, and lifecycle coordination.

Pods provide a consistent abstraction that simplifies these challenges. Each pod is assigned a unique IP address accessible via Services and DNS, allowing it to communicate with other pods across the cluster without needing to know where those pods are running. This remains true even as pods are created, destroyed, or rescheduled across nodes.

For workloads that require tight coupling, such as an application container paired with a logging or proxy sidecar, Kubernetes allows multiple containers to run within the same pod. Containers in the same pod share the same network namespace, which means that they can communicate using localhost and access shared storage volumes. This design makes it easier to coordinate closely related processes without embedding that complexity into the application itself.

How do Kubernetes pods work?

Kubernetes pods can be created manually, but in most production environments they are created and managed automatically by higher-level controllers. Pods are designed to be ephemeral; they are not intended to be long-lived or manually maintained. When a pod is created, the Kubernetes scheduler assigns it to a suitable node based on resource requirements, placement rules, and cluster availability.

For scalable workloads, Kubernetes runs multiple identical pod replicas across the cluster. These replicas allow Kubernetes to distribute load, tolerate failures, and perform rolling updates without downtime.

If demand increases, Kubernetes can create additional pod replicas automatically. When demand drops, excess replicas can be removed just as seamlessly.

Kubernetes pod lifecycle

Understanding the lifecycle of a Kubernetes pod is essential to mastering Kubernetes operations. From the moment you create a pod using kubectl to the time it’s terminated, each pod goes through a predictable series of phases: Pending, Running, Succeeded, or Failed. When you first create a pod the scheduler assigns it to a node based on scheduling decisions and resource availability. The pod enters the “Pending” state while its container images are being pulled and resources are allocated. Once everything is ready, the pod transitions to “Running.”

Kubernetes continuously monitors pods. If a pod crashes or stops responding, depending on its configuration, it may be restarted, replaced, or left terminated. This built-in resiliency — managed by controllers — ensures your k8s pods behave predictably, even in complex deployments.

Whether you’re working with ephemeral or long-running pods, it’s helpful to use commands like kubectl get pods to monitor their status.

How Pods Communicate with Each Other

Each pod in Kubernetes is assigned a unique IP address, and containers within the same pod can communicate over localhost, sharing the same network namespace. This setup is perfect for multi-container pods that need to tightly coordinate tasks, such as a web server container and a logging sidecar.

For communication across different pods — even across nodes — Kubernetes services act as stable endpoints, abstracting the underlying IPs of pods in Kubernetes. Whether you’re deploying a frontend that needs to talk to a backend service, or scaling microservices across a cluster, this IP-based networking and service abstraction simplifies orchestration.

And when troubleshooting, use commands like kubectl pods or kubectl describe pod [pod-name]to inspect how your pods Kubernetes are interacting and behaving.

Single container pods vs multi-container pods

Most often, developers start with single-container pods, where one container handles a distinct microservice. This keeps deployments clean, predictable, and aligned with best practices for containerization.

However, Kubernetes also supports multi-container pods — helpful in tightly coupled scenarios where containers must share storage or memory. For example, a helper container might pull configuration files or handle metrics export, running alongside your main app in the same pod. This pattern is often referred to as the sidecar pattern, and it’s foundational for observability, logging, and security in cloud-native environments.

So when you’re deciding between containers vs pods, the key difference is: containers are the app runtimes, while pods are the deployable units that contain one or more containers and define their shared context. Kubernetes doesn't schedule containers — it schedules pods.

Managing pods with kubectl

Earlier, we said that pods are typically managed automatically, and this is true. But we do have the ability to manage pods manually using the Kubernetes command-line tool kubectl. For hands-on practice with pods, spin up a simple Kubernetes development environment and try the following commands:

In the command line, you can use kubectl to create a pod from the specifications in a YAML file. To do so, you’ll use the -f flag on the create command, including the filepath for your YAML file.

For this example, let’s use the following YAML file. Using the filename example-pod.yml, place this in your working directory:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
  labels:
    role: example-role
spec:
  containers:
    - name: web
      image: nginx
      ports:
        - name: web
          containerPort: 80
          protocol: TCP

Now, in the command line, use the following command to create your pod:

kubectl create -f example-pod.yml

Now your pod should be created. To confirm, you can check for information on the pods in your current namespace:

kubectl get pods

This should return a readout with information on the readiness, status, restarts, and age for all running pods:

NAME          READY   STATUS    RESTARTS   AGE
example-pod   1/1     Running   0          7m49s

Now let’s delete our example pod. We can do this in two principal ways: by pointing to the YAML manifest that created the pod…

kubectl delete -f example-pod.yml

Or you can simply refer to the pod by name, so long as it is in your default namespace:

kubectl delete example-pod

It’s important to note that, by default, deleted pods will continue running for a grace period that is usually 30 seconds. You can specify a grace period with the --grace-period flag. For pods in other namespaces, you can simply use the --namespace flag. And if you need to force delete a Kubernetes pod, you can use --force.

Let’s imagine, then, that example-pod is running in a namespace called dev and you want to force-delete it immediately. In this situation, you could use:

kubectl delete example-pod --grace-period=0 --force --namespace dev

Keeping Kubernetes pods healthy

Keeping Kubernetes pods healthy is critical for maintaining uptime and ensuring smooth operation of your containerized workloads. Kubernetes uses readiness and liveness probes to monitor the health of pods. A liveness probe checks if a container inside a pod is still running, while a readiness probe checks if it's ready to accept traffic. If a container fails a liveness probe, Kubernetes can automatically restart the the container to recover it — no human intervention required.

For manual inspection, you can use kubectl get pods or kubectl describe pod [pod-name] to see detailed health information. If you're trying to figure out what's going wrong, kubectl logs [pod-name] is your best friend.

And if a pod enters a crash loop or becomes unresponsive, sometimes the fastest path to resolution is to kubectl delete a pod and let the controller spin up a replacement. Kubernetes makes sure that healthy replicas replace failed pods seamlessly, helping you stay resilient even in dynamic, large-scale environments.

Whether you're operating a development cluster or managing pods in Kubernetes at scale, maintaining pod health ensures your microservices keep running smoothly — and that your team spends more time building, less time firefighting.

Kubernetes pods for continuous deployment

Although pods can be created manually, Kubernetes is designed for automated lifecycle management. In practice, pods are created and managed by controllers that maintain the desired state of the system.

This automation enables Kubernetes to support:

  • Fault tolerance through automatic replacement

  • Elastic scaling based on demand

  • Rolling updates with no service interruption

When a node or process fails, Kubernetes replaces affected pods automatically. When an application version changes, traffic can be shifted gradually to new pods running the updated version, all without downtime.

Simplify Kubernetes Pods with Mirantis

Kubernetes pods are the foundation of how applications are scheduled, scaled, and managed across a cluster. But running Kubernetes reliably in production requires more than understanding its abstractions — it requires a distribution designed for simplicity, security, and operational consistency.

k0s is a lightweight Kubernetes distribution that simplifies cluster operations without sacrificing enterprise-grade capabilities.

Key features include:

  • Single-Binary Kubernetes Distribution: Core Kubernetes control plane components are packaged into a single binary, reducing installation complexity and operational overhead

  • Flexible Deployment Model: A wide range of environments are supported, from centralized data centers to edge locations

  • Fully Conformant Kubernetes: Upstream Kubernetes delivered without vendor lock-in, ensuring compatibility with standard tooling and workloads

  • Designed for Operational Simplicity: Moving parts and configuration sprawl are minimized, making it easier for platform teams to deploy, upgrade, and maintain clusters at scale

If you’re looking to reduce operational complexity while maintaining full control over your Kubernetes platform, k0s provides a streamlined foundation for running pods at scale.

Start exploring k0s today!

FREE EBOOK

Learn Kubernetes 5 Minutes at a Time

A hands-on introduction to Kubernetes for developers

DOWNLOAD NOW