Cloud Native 20 min read

How Pods Really Work: Inside Containers, Namespaces, and cgroups

This article explores the low‑level implementation of containers and Kubernetes Pods, comparing Docker’s single‑process model with multi‑process Pods, examining Linux namespaces and cgroups, and demonstrating how to recreate Pod‑like behavior using Docker and custom cgroup hierarchies.

MaGe Linux Operations
MaGe Linux Operations
MaGe Linux Operations
How Pods Really Work: Inside Containers, Namespaces, and cgroups

Why Pods Feel Like Mini‑Servers

Containers were originally envisioned as lightweight VM replacements, but Docker/OCI standardized on a one‑process‑per‑container model, which improves isolation and scaling yet limits the ability to run multiple services in a single VM‑like environment. Kubernetes introduced Pods—cohesive groups of containers that share an IP address and hostname, making a Pod resemble a tiny server.

Key Questions Explored

How are Pods implemented under the hood?

What practical differences exist between Pods and plain containers?

How can Docker be used to create a Pod‑like construct?

Setting Up a Playground (Docker + Vagrant)

# cat > Vagrantfile <<EOF
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
  config.vm.box = "debian/buster64"
  config.vm.hostname = "docker-host"
  config.vm.define "docker-host"
  config.vagrant.plugins = ['vagrant-vbguest']
  config.vm.provider "virtualbox" do |vb|
    vb.cpus = 2
    vb.memory = "2048"
  end
  config.vm.provision "shell", inline: <<-SHELL
    apt-get update
    apt-get install -y curl vim
  SHELL
  config.vm.provision "docker"
end
EOF

$ vagrant up
$ vagrant ssh

Exploring Container Namespaces

After launching a container, the following isolation primitives are created:

# Look up the container in the process tree.
$ ps auxf
... (output showing containerd‑shim and nginx processes)
# Find the namespaces used by the nginx process.
$ sudo lsns
NS   TYPE   NPROCS PID USER COMMAND
4026532157 mnt   3      4727 root nginx: master …
4026532158 uts   3      4727 root nginx: master …
4026532159 ipc   3      4727 root nginx: master …
4026532160 pid   3      4727 root nginx: master …
4026532162 net   3      4727 root nginx: master …

The container uses the following namespaces:

mnt (mount): isolated mount table.

uts (Unix Time‑Sharing): its own hostname and domain.

ipc (inter‑process communication): processes can use system‑level IPC.

pid (process IDs): sees only processes in the same PID namespace.

net (network): its own network stack.

Note that the user namespace is not used by default, so the container’s root user is effectively the host’s root.

Exploring Container cgroups

cgroups provide hierarchical resource control. The cgroup hierarchy for the running container can be inspected via systemd‑cgls:

$ sudo systemd-cgls
Control group /:
-.slice
├─kubepods
│  ├─burstable
│  │  ├─pod4a8d5c3e-…
│  │  │  ├─f0e87a933046… /pause
│  │  │  ├─dfb1cd29ab75… /usr/bin/python3 gunicorn …
│  │  │  └─097d4fe8a7002… /bin/sleep 365d
...

Each container can have its own CPU and memory limits within the Pod’s cgroup subtree.

Exploring Pods with Minikube

We use Minikube (VirtualBox driver, containerd runtime) as the Kubernetes playground:

# Install arkade (quick installer for kubectl and minikube)
$ curl -sLS https://get.arkade.dev | sh
$ arkade get kubectl minikube
$ minikube start --driver=virtualbox --container-runtime=containerd

A simple Pod manifest with an httpbin sidecar is applied:

$ kubectl --context=minikube apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: foo
spec:
  containers:
  - name: app
    image: docker.io/kennethreitz/httpbin
    ports:
    - containerPort: 80
    resources:
      limits:
        memory: "256Mi"
  - name: sidecar
    image: curlimages/curl
    command: ["/bin/sleep", "3650d"]
    resources:
      limits:
        memory: "128Mi"
EOF

Inspecting the node shows three containers: the pause sandbox and the two user containers. The pause container provides shared network, UTS, and IPC namespaces that the app and sidecar reuse.

$ sudo lsns
NS   TYPE   NPROCS PID USER COMMAND
4026532614 net   4 4966 root /pause
4026532715 mnt   1 4966 root /pause
4026532716 uts   4 4966 root /pause
4026532717 ipc   4 4966 root /pause
4026532718 pid   1 4966 root /pause
...

Using crictl inspect confirms that the app container’s namespace list includes pid, ipc, uts, mount, and network, with ipc, uts, and network pointing to the pause container’s namespaces.

Pod cgroups

The Pod’s cgroup hierarchy mirrors the Docker hierarchy and can be visualized with systemd‑cgls:

$ sudo systemd-cgls memory
Controller memory; Control group /:
├─pod-foo
│  ├─488d76ca… /usr/bin/python3 gunicorn …
│  ├─9166a87f… /bin/sleep 365d
│  └─c7b0ec46… /sleep infinity
...

Building a Pod‑like Construct with Docker

By creating a shared cgroup parent and reusing the sandbox’s network and IPC namespaces, we can run multiple containers that behave like a Pod:

# Install cgroup tools
$ sudo apt-get install cgroup-tools
# Create a parent cgroup for the pod
$ sudo cgcreate -g cpu,memory:/pod-foo
# Start a sandbox container (shared IPC, no UTS sharing)
$ docker run -d --rm \
    --name foo_sandbox \
    --cgroup-parent /pod-foo \
    --ipc shareable \
    alpine sleep infinity
# Run the app container sharing the sandbox’s network and IPC
$ docker run -d --rm \
    --name app \
    --cgroup-parent /pod-foo \
    --network container:foo_sandbox \
    --ipc container:foo_sandbox \
    kennethreitz/httpbin
# Run a sidecar container sharing the same namespaces
$ docker run -d --rm \
    --name sidecar \
    --cgroup-parent /pod-foo \
    --network container:foo_sandbox \
    --ipc container:foo_sandbox \
    curlimages/curl sleep 365d

Docker cannot currently share the UTS namespace, so hostname/domain sharing is omitted, but network and IPC sharing works as expected.

Summary

Containers and Pods both rely on Linux namespaces and cgroups, but a Pod is a higher‑level construct that groups containers into a single, self‑contained unit with shared networking, IPC, and (optionally) other namespaces. All containers in a Pod run on the same node, have synchronized lifecycles, and can communicate via localhost, making Pods feel like lightweight VMs and enabling patterns such as sidecars and reverse proxies.

Related links:

https://github.com/opencontainers/runtime-spec/issues/345

https://github.com/opencontainers/runtime-spec/pull/388

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

cloud-nativecgroupsNamespaces
MaGe Linux Operations
Written by

MaGe Linux Operations

Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.