Kubernetes Infrastructure Container (pause container) Concepts Explained

Concept Map - Core Keyword Connections

image.png


1. What is an Infrastructure Container (pause container)?

Definition

  • A hidden container automatically created for every Pod
  • Performs only infinite waiting via the pause() system call — no application logic
  • Acts as the owner (anchor) of the Linux Namespace shared by containers within the Pod

Why is it necessary? (Cause and Effect)

Problem: App container owns the Namespace (no pause)
    │
    ├──▶ Coupled responsibilities: one container handles both app logic + infrastructure
    │       └──▶ App instability = Infrastructure instability
    │
    ├──▶ No restart isolation: owner crashes → Namespace destroyed → other containers lose network
    │       └──▶ Cannot recover individual containers via restartPolicy
    │
    └──▶ Asymmetric structure: one app container becomes "special"
            └──▶ Violates the principle of container equality within a Pod

Solution: pause container = Separation of Concerns
    └──▶ Dedicated to infrastructure role; practically no reason to crash

2. What exactly is the pause container?

ItemDetails
Source codeWritten in C; core logic is ~20 lines
What it does① Registers SIGCHLD handler (zombie process reaping) ② pause() system call (infinite wait)
Base imagescratch (completely empty image — no shell, no libc)
Image size~700KB
CompilationStatically compiled (static linking) → no OS dependencies
OS❌ No OS. Only a single binary sitting on top of the kernel

Image Size Comparison

pause:3.9    ████ ~700KB        (scratch)
alpine       ████████████████████████████ ~7MB   (musl + busybox)
ubuntu       ████████████████████████████████████████████████████ ~78MB (full OS)
nginx        ██████████████████████████████████████████████████████████████████ ~140MB (debian)

3. Namespace Sharing Structure Inside a Pod

Shared Namespaces (owned by pause)

NamespaceEffect
NetworkAll containers share the same IP; communicate via localhost
IPCIPC communication possible via shared memory, semaphores, etc.
UTSShared hostname

Isolated Namespaces (unique per container)

NamespaceEffect
PIDEach container sees only its own processes (independent PID 1)
MountEach container has an independent filesystem view

Patterns enabled by this structure

  • Sidecar pattern: App container serves on :80 → log agent accesses it via localhost:80
  • Ambassador pattern: Proxy container handles external communication
  • Adapter pattern: Container transforms monitoring data formats

4. Container Count

kubectl vs. Reality (example: Pod with 2 app containers)

MethodVisible countActual composition
kubectl get pods (READY column)2/2Only App A + App B shown
crictl ps (directly on node)3pause + App A + App B

The pause container is an infrastructure container created internally by kubelet and is therefore not visible at the Kubernetes API level.

Verification Commands

# For containerd-based setups (RKE2, EKS, etc.)
crictl ps | grep <pod-name>

# Output: all 3 containers — pause, app-container-a, app-container-b

5. How the Container Count Changes When initContainers Are Included

initContainers terminate after execution completes → the count varies depending on the point in time

Example: 1 init container + 2 app containers

Containers running at each phase:

[Initializing]  pause + initContainer = 2
                │
                ▼ init succeeds (exit 0) → init terminates/removed
                │
[App starting]  pause + app-A + app-B = 3
                │
[Running]       pause + app-A + app-B = 3

kubectl display

# During initialization
NAME        READY   STATUS
my-pod      0/2     Init:0/1     ← shows init progress

# Running state
NAME        READY   STATUS
my-pod      2/2     Running      ← init not counted

Key Rules

  • initContainers run sequentially (one at a time if there are multiple)
  • If any one fails, app containers will never start → Init:CrashLoopBackOff
  • After all inits succeed, app containers start simultaneously

6. The Fundamental Reason pause Cannot Be Omitted

Answering: “Why not just store network info in etcd/ConfigMap?”

A Namespace is not data — it is a kernel resource.

etcd/ConfigMapNetwork Namespace
NatureData (configuration values)Kernel runtime resource
StorageDisk/in-memory DBKernel memory
Persistence conditionPersists as long as etcd is aliveMust be held by a process to persist
AnalogyPhone number written in a directoryAn actual phone that is connected

Linux Namespace Survival Condition

Reference count based:

Processes referencing it ≥ 1  →  Namespace remains
Processes referencing it = 0  →  Kernel immediately releases it (GC)

Kernel Objects That Exist Inside a Network Namespace

  • eth0 virtual interface + veth pair
  • IP address binding
  • Routing table
  • iptables/nftables rules
  • Open sockets (TCP connection state)

All of these are kernel objects — they cannot be stored as key-value pairs.
Even if etcd records “IP is 10.244.1.5”, without a Namespace in the kernel, packets cannot be received.

The Essence of the pause Container

  • Its purpose is not “interaction” — it is existence itself
  • Infinite wait via pause() system call → uses almost no CPU/memory
  • Maintains a reference to the kernel: “I’m still using this Namespace”

7. What Happens If the pause Container Dies?

pause dies
    │
    ▼
Network/IPC Namespace owned by pause is destroyed
    │
    ▼
All app containers in the Pod lose network connectivity
    │
    ▼
kubelet detects this
    │
    ▼
Entire Pod terminated → new Pod recreated (new pause + new app containers)
    │
    ▼
⚠️ New Pod receives a new IP → why Services are necessary

App container crash → only that container can be restarted via restartPolicy
pause container crash → Namespace itself is destroyed; partial recovery impossible → entire Pod recreated


Practical Troubleshooting Tips

1. Checking the pause container when a Pod keeps restarting

# After accessing the node
crictl ps -a | grep <pod-name>
# Check pause container status — if Exited, it's an infrastructure-level issue

crictl logs <pause-container-id>
# Usually no logs (normal); errors indicate a node-level issue

2. pause image missing in air-gapped environments

# Default RKE2 pause image path
# registry.k8s.io/pause:3.9 → needs to be mirrored to Harbor

# For RKE2, configure mirror in /etc/rancher/rke2/registries.yaml
mirrors:
  "registry.k8s.io":
    endpoint:
      - "https://harbor.internal.company.com"

# Or change sandbox_image in containerd config
# /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri"]
  sandbox_image = "harbor.internal.company.com/pause:3.9"

3. Pod won’t start due to initContainer failure

# Check init status
kubectl describe pod <pod-name> | grep -A 20 "Init Containers"

# Check init container logs
kubectl logs <pod-name> -c <init-container-name>

# Common causes
# - Air-gapped env: init images must also be pushed to Harbor
# - DB migration failure: DB connectivity issue
# - Missing ConfigMap/Secret mount

4. Directly inspecting the Namespace when Pod networking is abnormal

# Check the Pod's network namespace
POD_ID=$(crictl pods --name <pod-name> -q)
PID=$(crictl inspectp $POD_ID | jq '.info.pid')

# Check network interfaces in that namespace
nsenter -t $PID -n ip addr
nsenter -t $PID -n ip route
nsenter -t $PID -n ss -tlnp

Expected Interview Questions

Q1. What is the role of the pause container in Kubernetes?

Key answer points:

  • Owner of the Linux Namespaces (Network, IPC, UTS) shared by containers within a Pod
  • Separation of concerns: decouples the infrastructure role from app containers
  • Based on the scratch image, ~700KB, infinitely waits via the pause() system call
  • Not visible in kubectl, but can be confirmed with crictl

Q2. How do containers within a Pod communicate with each other?

Key answer points:

  • Share the same Network Namespace → same IP, communicate via localhost
  • pause container owns the Namespace; app containers join it
  • PID and Mount Namespaces are isolated → processes and filesystems are separated
  • This structure is the foundation of the sidecar pattern

Q3. What happens if the pause container dies?

Key answer points:

  • Namespace is destroyed → all app containers lose network connectivity
  • kubelet recreates the entire Pod (partial recovery is impossible)
  • New Pod receives a new IP → connects to the need for Service abstraction

Q4. Why is storing network information in etcd alone insufficient?

Key answer points:

  • A Namespace is not data — it is a kernel runtime resource
  • Reference count based: it only exists as long as a process holds a reference
  • etcd = desired state (control plane), Namespace = actual state (data plane)
  • The pause container is the anchor of actual state

Q5. What is the difference between an initContainer and a regular container?

Key answer points:

  • init runs sequentially then terminates; app containers start simultaneously and remain running
  • App containers do not start if an init container fails
  • init containers are not included in the kubectl READY count
  • Use cases: DB migrations, config file downloads, waiting for dependent services

One-Line Summary

The pause container is the most important “process that does nothing” — it does nothing, yet makes the Pod’s network exist.


  • CNI (Container Network Interface) → the process of plugging a veth pair into the Namespace created by pause
  • Service / kube-proxy → abstraction that ensures stable access even when Pod IPs change
  • CRI (Container Runtime Interface) → the interface through which kubelet creates the pause container
  • Linux cgroup → the other pillar of container isolation, alongside Namespace
  • Sidecar Container (K8s 1.28+) → init container with restartPolicy: Always