✦ For everyone, free.

Practical knowledge for real and everyday life

Home

Kubernetes Pods and Containers

Kubernetes Pods and Containers are fundamental building blocks for deploying and managing applications in a scalable and resilient containerized environment.

Kubernetes Pods and Containers describes the smallest deployable and manageable unit in Kubernetes, the Pod, and its relationship to the containers it wraps. A Pod is a thin, shared execution context around one or more containers that are deployed, scheduled, and scaled together as a single unit, guaranteeing that its constituent containers always run on the same node and can cooperate through shared network and storage resources.


The Pod Abstraction

Why Kubernetes Does Not Schedule Bare Containers

Kubernetes schedules Pods rather than individual containers because many real workloads consist of tightly coupled processes that must run together, such as a main application container and a logging sidecar. Wrapping these in a single schedulable unit guarantees co-location, avoids the complexity of coordinating placement across separately scheduled containers, and gives the group a single lifecycle and IP address.

Shared Execution Context

All containers within a Pod share:

  • Network namespace: Every container in a Pod shares a single IP address and port space, and can reach each other over localhost.
  • IPC namespace: Containers can communicate using standard inter-process communication mechanisms as if they were processes on the same machine.
  • Storage volumes: Volumes defined at the Pod level can be mounted into any of its containers, enabling data sharing between them.

Containers within a Pod do not share a process ID namespace or filesystem by default, preserving isolation between them even while sharing network and storage.


Container Types Within a Pod

Application Containers

The primary containers of a Pod run the main application logic. A Pod may contain a single application container, the most common case, or several that need to operate closely together.

Init Containers

Init containers run to completion, in order, before any application container in the Pod starts. They are commonly used to perform setup tasks, such as waiting for a dependency to become available or populating a shared volume, that must finish before the main application begins.

spec:
  initContainers:
    - name: wait-for-db
      image: busybox:1.36
      command: ["sh", "-c", "until nc -z db-service 5432; do sleep 2; done"]
  containers:
    - name: app
      image: codartium/app:1.0.0

Sidecar Containers

Sidecar containers run alongside the main application container for the entire lifetime of the Pod, commonly providing cross-cutting functionality such as log shipping, metrics collection, or service mesh proxying, without embedding that logic into the application image itself.


Pod Specification

apiVersion: v1
kind: Pod
metadata:
  name: codartium-analyzer
  labels:
    app: codartium-analyzer
spec:
  containers:
    - name: analyzer
      image: codartium/analyzer:3.2.0
      ports:
        - containerPort: 9090
      resources:
        requests:
          cpu: "100m"
          memory: "128Mi"
        limits:
          cpu: "300m"
          memory: "256Mi"
      volumeMounts:
        - name: cache
          mountPath: /var/cache/analyzer
  volumes:
    - name: cache
      emptyDir: {}
  restartPolicy: Always

Pod Lifecycle

Phases

A Pod progresses through a sequence of phases reported in its status.phase field: Pending, while the Pod is accepted but its containers are not yet running; Running, once at least one container is running; Succeeded or Failed, once all containers have terminated; and Unknown, if the Pod's state cannot be determined, typically due to a communication failure with its node.

Pending Running { Succeeded , Failed }

Restart Policy

The restartPolicy field, Always, OnFailure, or Never, governs whether the kubelet restarts containers within the Pod after they exit, and is a key factor distinguishing long-running service Pods from batch or run-to-completion Pods.

Pod Disposability

Pods are treated as ephemeral and disposable. They are not migrated between nodes; if a node fails or a Pod is deleted, a new Pod with a new identity and, typically, a new IP address is created in its place by the relevant controller. Applications running in Pods must therefore be designed to tolerate replacement rather than relying on any individual Pod's persistence.


Container Images and Pull Policy

Each container in a Pod specifies an image reference, typically including a registry, repository, and tag or digest. The imagePullPolicy field determines whether the kubelet always pulls the latest image, pulls only if the image is not already present locally, or never pulls, which affects both startup latency and the guarantee that a given tag always resolves to the same content.

kubectl run codartium-debug --image=busybox:1.36 --restart=Never -- sleep 3600
kubectl exec -it codartium-debug -- sh
kubectl logs codartium-analyzer -c analyzer

Multi-Container Coordination

Because containers in a Pod share network and storage but remain independently defined, patterns such as the sidecar, ambassador, and adapter emerge naturally: a sidecar extends or monitors the main container, an ambassador proxies outbound connections on its behalf, and an adapter normalizes its output for external consumption, all without modifying the main container's image.