| |

LFCE 138 ๐Ÿง Kubernetes โ€” Pods

โฑ๏ธ Estimated read: 11 min | |

A Pod is the smallest deployable unit in Kubernetes. It is not a container; it is a wrapper around one or more containers that share the same network namespace, the same IP address, and the same storage volumes . The containers inside a Pod are always co-located on the same node, always co-scheduled, and always share a context. When a Pod is created, Kubernetes manages the Pod as a whole, not the individual containers inside it.

This chapter covers the Pod abstraction: the single-container and multi-container models, the shared network and storage that define a Pod’s identity, the three multi-container design patterns (init containers, sidecars, and co-located peers), and the restart policy that determines what happens when a container exits.

Key point: A Pod is ephemeral. It is not designed to survive node failures or restarts. When a Pod is deleted or its node fails, the control plane creates a replacement Pod with a new name, a new IP address, and no memory of the previous instance. The Pod itself is the unit of scheduling, not the unit of persistence.


Why Pods exist

The co-location problem. Some processes are tightly coupled. A web server needs a log shipper to collect its output. An application needs a local cache to serve requests faster. A batch job needs a helper to fetch data before the main process starts. If these processes ran in separate containers on separate nodes, they would have to communicate over the network, which adds latency and complexity. A Pod places them on the same node, in the same network namespace, so they can communicate over localhost and share storage directly .

The atomic scheduling problem. Kubernetes schedules Pods, not containers. The scheduler evaluates the Pod’s total resource requests, the node’s available capacity, and the Pod’s constraints as a single decision. If the Pod has three containers, all three are scheduled together. There is no partial scheduling where one container runs on one node and another container runs on a different node. The Pod is the atomic unit of placement .

The lifecycle problem. A container has a lifecycle. It starts, runs, and exits. A Pod has a lifecycle that wraps the containers. The Pod can be Pending (waiting for scheduling), Running (at least one container is running), Succeeded (all containers exited with zero), or Failed (at least one container exited with non-zero and will not restart). The Pod’s status is the aggregate of its containers’ statuses .


a. The single-container Pod

The most common Pod has exactly one container. The Pod is a wrapper that gives the container a network identity, a set of resource limits, and a lifecycle managed by Kubernetes. The container does not know it is in a Pod; it just runs its process .

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - name: nginx
      image: nginx:1.27
      ports:
        - containerPort: 80

The Pod gets a cluster-internal IP address. The container inside the Pod binds to port 80. Other Pods can reach it at that IP and port. The Pod’s name (nginx) is its identity in the cluster, but the IP address is what other Pods use to connect.

The single-container model is the default for stateless applications. A Deployment creates a ReplicaSet, and the ReplicaSet creates Pods with one container each. The controller manages the Pods, not the containers.


b. The multi-container Pod

A Pod can contain multiple containers. These containers share the network namespace and the storage volumes. They are always scheduled on the same node. They can communicate over localhost because they share the same IP address and port space .

The Kubernetes documentation describes three patterns for multi-container Pods .

Init containers run before the main containers. They run sequentially, in the order they are listed in the initContainers field. Each init container must exit successfully before the next one starts. The main containers do not start until all init containers have completed. Init containers are used for setup tasks: waiting for a database to be ready, running a schema migration, or fetching configuration files .

spec:
  initContainers:
    - name: wait-for-db
      image: busybox
      command: ['sh', '-c', 'until nc -z db 5432; do sleep 1; done']
  containers:
    - name: app
      image: myapp:1.0

Sidecar containers run alongside the main container for the Pod’s entire lifetime. They provide supporting functionality: log collection, metrics export, request proxying, or data synchronization. In Kubernetes v1.33 and later, a sidecar is defined as an init container with restartPolicy: Always, which makes it start before the main container and remain running until the Pod terminates .

Co-located containers are multiple containers in the containers array that run concurrently. Kubernetes does not guarantee a startup order between them. This pattern is appropriate when the containers are independent peers that need to share the network or storage but do not depend on each other’s startup sequence .


c. Shared resources and the Pod’s identity

Every container in a Pod shares the same network namespace. The Pod has one IP address, and every container binds to ports on that address. Two containers in the same Pod cannot bind to the same port; they must coordinate their port usage. Containers in different Pods have different IP addresses and cannot communicate via localhost .

Every container in a Pod can mount the same volumes. A volume is defined at the Pod level and mounted into each container that needs it. This is how a sidecar can read the main container’s log files, or how an init container can write a configuration file that the main container reads .

The Pod’s hostname is the Pod’s metadata.name. Containers inside the Pod see the hostname as the Pod name. This is useful for applications that report their identity, but it is not a stable identifier across Pod recreations.


Complete Example Session

# ============================================
# PART 1: A SINGLE-CONTAINER POD
# ============================================
apiVersion: v1
kind: Pod
metadata:
  name: web
spec:
  containers:
    - name: nginx
      image: nginx:1.27
      ports:
        - containerPort: 80
# ============================================
# PART 2: CREATE AND INSPECT
# ============================================
kubectl apply -f pod.yaml
kubectl get pod web
kubectl describe pod web
# ============================================
# PART 3: AN INIT CONTAINER
# ============================================
apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  initContainers:
    - name: init-config
      image: busybox
      command: ['sh', '-c', 'echo "config" > /work/config.txt']
      volumeMounts:
        - name: work
          mountPath: /work
  containers:
    - name: app
      image: myapp:1.0
      volumeMounts:
        - name: work
          mountPath: /work
  volumes:
    - name: work
      emptyDir: {}
# ============================================
# PART 4: A SIDECAR CONTAINER
# ============================================
spec:
  initContainers:
    - name: log-shipper
      image: fluentbit:latest
      restartPolicy: Always
      volumeMounts:
        - name: logs
          mountPath: /var/log/app
  containers:
    - name: app
      image: myapp:1.0
      volumeMounts:
        - name: logs
          mountPath: /var/log/app
  volumes:
    - name: logs
      emptyDir: {}
# ============================================
# PART 5: CO-LOCATED CONTAINERS
# ============================================
spec:
  containers:
    - name: web
      image: nginx:1.27
    - name: metrics
      image: prom-exporter:latest
      ports:
        - containerPort: 9090
# ============================================
# PART 6: CHECK POD STATUS
# ============================================
kubectl get pods
# NAME   READY   STATUS    RESTARTS   AGE
# web    1/1     Running   0          30s
# app    2/2     Running   0          1m
# ============================================
# PART 7: CHECK CONTAINER LOGS
# ============================================
kubectl logs web
kubectl logs app -c init-config
# ============================================
# PART 8: EXEC INTO A CONTAINER
# ============================================
kubectl exec -it web -- /bin/sh
# ============================================
# PART 9: THE RESTART POLICY
# ============================================
# Always: restart regardless of exit code
# OnFailure: restart only on non-zero exit
# Never: never restart
# ============================================
# PART 10: THE COMPLETE POD
# ============================================
apiVersion: v1
kind: Pod
metadata:
  name: complete
spec:
  restartPolicy: OnFailure
  initContainers:
    - name: wait
      image: busybox
      command: ['sh', '-c', 'until nc -z db 5432; do sleep 1; done']
  containers:
    - name: app
      image: myapp:1.0
      ports:
        - containerPort: 8080

The ten parts covered the single-container Pod, creation and inspection, init containers, sidecar containers, co-located containers, Pod status, container logs, exec, the restart policy, and the complete Pod.


Quick Reference

Pod models

ModelContainersUse case
Single-containerOneStateless applications
Init containersSequential, run before mainSetup, migrations, waiting
SidecarLong-running helperLogging, proxying, metrics
Co-locatedConcurrent peersShared network/storage, independent

Shared resources

ResourceShared
Network namespaceYes (one IP, shared ports)
VolumesYes (mounted per container)
HostnamePod name
IPCYes (SystemV, POSIX)

Restart policies

PolicyBehavior
AlwaysRestart regardless of exit code
OnFailureRestart only on non-zero exit
NeverNever restart

Pod lifecycle

PhaseMeaning
PendingAccepted, not scheduled or containers not started
RunningAt least one container running
SucceededAll containers exited 0
FailedAt least one container exited non-zero

Best Practices

โœ… Do This:

# Use init containers for setup that must complete first
initContainers:
  - name: wait-for-db                                   # โœ…
# Use a sidecar for log collection
initContainers:
  - name: log-shipper
    restartPolicy: Always                               # โœ…
# Set resource requests and limits
resources:
  requests: { cpu: 100m, memory: 128Mi }                # โœ…

โŒ Don’t Do This:

# Put unrelated services in the same Pod
containers:
  - name: web
  - name: database  # separate concern                    # โŒ
# Assume startup order for co-located containers
containers:
  - name: a
  - name: b  # b may start before a                      # โŒ
# Use a Pod directly for a long-running service
# Use a Deployment instead                               # โŒ

Common Pitfalls

PitfallWhy It HappensFix
Pods are not recreatedCreated directly, not via a controllerUse a Deployment or ReplicaSet
Container cannot bind portAnother container in the Pod uses itCoordinate ports or use separate Pods
Init container hangsWaiting for a service that never comes upCheck the init container’s command and logs
Sidecar does not start firstCo-located containers have no orderUse an init container with restartPolicy: Always
Data lost on Pod restartUsed emptyDir or no volumeUse a PersistentVolume

Real-World Examples

1. Single-container Pod

spec:
  containers:
    - name: nginx
      image: nginx:1.27

2. Init container

initContainers:
  - name: migrate
    image: myapp:1.0
    command: ['sh', '-c', 'npm run migrate']

3. Sidecar

initContainers:
  - name: proxy
    image: envoy:latest
    restartPolicy: Always

4. Co-located containers

containers:
  - name: app
  - name: metrics

5. Shared volume

volumes:
  - name: shared
    emptyDir: {}

6. Restart policy

restartPolicy: OnFailure

7. Check Pod status

kubectl get pods

8. Describe a Pod

kubectl describe pod web

9. Exec into a container

kubectl exec -it web -- /bin/sh

10. View logs

kubectl logs web

Visual

The Pod abstraction

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  POD                                                         โ”‚
โ”‚                                                              โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚
โ”‚  โ”‚  Network namespace: 10.0.0.5                            โ”‚โ”‚
โ”‚  โ”‚                                                         โ”‚โ”‚
โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                     โ”‚โ”‚
โ”‚  โ”‚  โ”‚ Container A  โ”‚  โ”‚ Container B  โ”‚                     โ”‚โ”‚
โ”‚  โ”‚  โ”‚ port 8080    โ”‚  โ”‚ port 9090    โ”‚                     โ”‚โ”‚
โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                     โ”‚โ”‚
โ”‚  โ”‚         โ”‚                 โ”‚                             โ”‚โ”‚
โ”‚  โ”‚         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                             โ”‚โ”‚
โ”‚  โ”‚                  โ–ผ                                      โ”‚โ”‚
โ”‚  โ”‚         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                             โ”‚โ”‚
โ”‚  โ”‚         โ”‚  Shared volume  โ”‚                             โ”‚โ”‚
โ”‚  โ”‚         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                             โ”‚โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Multi-container patterns

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  INIT CONTAINERS                                             โ”‚
โ”‚    init1 โ”€โ”€โ–บ init2 โ”€โ”€โ–บ main container                       โ”‚
โ”‚    Sequential, must complete before main starts             โ”‚
โ”‚                                                              โ”‚
โ”‚  SIDECAR                                                     โ”‚
โ”‚    sidecar โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บ (runs for Pod lifetime)          โ”‚
โ”‚    main โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บ (runs for Pod lifetime)          โ”‚
โ”‚    Concurrent, sidecar may start first with restartPolicy   โ”‚
โ”‚                                                              โ”‚
โ”‚  CO-LOCATED                                                  โ”‚
โ”‚    container A โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บ                                   โ”‚
โ”‚    container B โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บ                                   โ”‚
โ”‚    Concurrent, no startup order guaranteed                  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The Pod lifecycle

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  PENDING โ”€โ”€โ–บ RUNNING โ”€โ”€โ–บ SUCCEEDED                          โ”‚
โ”‚     โ”‚            โ”‚                                           โ”‚
โ”‚     โ”‚            โ””โ”€โ”€โ–บ FAILED                                 โ”‚
โ”‚     โ”‚                                                        โ”‚
โ”‚     โ–ผ                                                        โ”‚
โ”‚  Scheduled to a node                                         โ”‚
โ”‚  Containers starting                                         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Shared network

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  POD: 10.0.0.5                                               โ”‚
โ”‚                                                              โ”‚
โ”‚  Container A binds 8080                                      โ”‚
โ”‚  Container B binds 9090                                      โ”‚
โ”‚                                                              โ”‚
โ”‚  Container A โ†’ localhost:9090 โ†’ Container B                  โ”‚
โ”‚                                                              โ”‚
โ”‚  External โ†’ 10.0.0.5:8080 โ†’ Container A                      โ”‚
โ”‚  External โ†’ 10.0.0.5:9090 โ†’ Container B                      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
DefinitionSmallest deployable unit, one or more containers
Shared resourcesNetwork namespace, IP, volumes, IPC
Single-containerMost common, wrapper around one container
Init containersSequential, run before main containers
SidecarLong-running helper, restartPolicy: Always in initContainers
Co-locatedConcurrent containers, no startup order
Restart policyAlways, OnFailure, Never
Lifecycle phasesPending, Running, Succeeded, Failed
Pod IPUnique per Pod, shared by all containers

Key takeaways:

  • A Pod is not a container. It is a wrapper around one or more containers that share a network namespace, an IP address, and storage volumes. Kubernetes manages Pods, not containers .
  • The single-container model is the default. A Pod with one container is the standard unit for stateless applications. The Pod gives the container a network identity and a lifecycle managed by Kubernetes .
  • Multi-container Pods exist for tightly coupled processes. Init containers run sequentially before the main containers. Sidecars run alongside the main container for the Pod’s lifetime. Co-located containers run concurrently with no guaranteed startup order .
  • The shared network namespace is the defining feature. All containers in a Pod share the same IP address and port space. They can communicate over localhost, but they cannot bind to the same port .
  • The restart policy determines what happens when a container exits. Always restarts regardless of exit code, OnFailure restarts only on non-zero, and Never never restarts. The policy is set at the Pod level and applies to all containers .
  • Pods are ephemeral. A Pod is tied to the node where it was scheduled and remains there until termination or deletion. When a node fails, the control plane creates replacement Pods on other nodes. A Pod is not a persistent entity; it is a disposable unit of execution .

Remember: A Pod is the atomic unit of Kubernetes scheduling and the smallest deployable object. It wraps one or more containers that share a network namespace and storage volumes. The single-container Pod is the default. The multi-container Pod is for tightly coupled processes: init containers for setup, sidecars for supporting services, and co-located containers for independent peers. The Pod has an IP address, a hostname, and a lifecycle, but it does not have persistence. When a Pod dies, it is replaced. The controller that manages the replacement is the Deployment, the StatefulSet, or the DaemonSet, not the Pod itself.

Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!