Can Docker Replicate Kubernetes Pods? Exploring Containers, Namespaces, and cgroups
This article investigates how containers and Kubernetes Pods differ and overlap by examining their underlying Linux namespaces, cgroup hierarchies, and runtime specifications, then demonstrates how to emulate a Pod using only Docker commands and shared resources.
Introduction
Containers could serve as lightweight VM alternatives, yet Docker/OCI standardization popularized the one‑process‑per‑container model, offering isolation, easier horizontal scaling, and reusability while sacrificing the multi‑service nature of traditional VMs.
Kubernetes advances this concept by introducing Pods—a set of co‑located containers that form the smallest deployable unit.
Personal Exploration of Pods
Initially, each Pod appears to have a unique IP and hostname, allowing containers to communicate via localhost, suggesting a micro‑server. However, each container maintains an isolated filesystem and cannot see the processes of its siblings, revealing that a Pod is primarily a group of containers sharing a network stack.
Further investigation shows that containers within a Pod can also share memory, indicating that network namespaces are not the sole shared resource.
Questions Driving the Study
How are Pods implemented at the low level?
What practical differences exist between Pods and plain containers?
How can Docker be used to create Pod‑like constructs?
1. Exploring Containers
The OCI runtime specification does not restrict containers to Linux namespaces and cgroups, though this article focuses on the traditional implementation.
Setting Up a Playground
$ 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 sshStart a simple container:
$ docker run --name foo --rm -d --memory='512MB' --cpus='0.5' nginxExploring Container Namespaces
After launching a container, the following isolation primitives are created:
mnt (mount): isolated mount table.
uts (Unix Time‑Sharing): unique hostname and domain.
ipc (inter‑process communication): processes can communicate via system‑level IPC within the container.
pid (process ID): processes see only those in the same PID namespace.
net (network): dedicated network stack.
User namespaces are not used by default, and Docker’s root user often maps to the host’s root.
Cgroup namespaces provide an isolated view of the cgroup hierarchy but are not enabled by default.
Exploring Container cgroups
cgroups limit resource usage. Example commands: $ sudo systemd-cgls The hierarchy shows a parent node for the pod and individual containers underneath, matching expectations for per‑container resource limits.
2. Exploring Pods
Pod implementations vary across CRI runtimes; some, like Kata, may run Pods as lightweight VMs. This study uses a minikube cluster with the ContainerD runtime.
Setting Up a Playground
$ curl -sLS https://get.arkade.dev | sh
$ arkade get kubectl minikube
$ minikube start --driver virtualbox --container-runtime containerdCreate a pod with two containers:
$ 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"
EOFInspecting the pod on the node reveals three containers: the two defined containers and a pause container that provides the shared network, IPC, and PID namespaces.
$ sudo ctr --namespace=k8s.io containers ls
$ sudo crictl psThe pause container’s ID matches the POD ID field in crictl output, confirming its role as a sandbox.
Exploring Pod Namespaces
Running lsns on the node shows that the pause container owns net, mnt, uts, ipc, and pid namespaces, while the app and sidecar containers reuse the net, uts, and ipc namespaces of the pause container.
# httpbin container
sudo ls -l /proc/5001/ns
# sidecar container
sudo ls -l /proc/5035/nsThus, containers in the same Pod can communicate via localhost and shared IPC mechanisms.
Setting shareProcessNamespace: true gives all containers a common PID namespace, and flags like hostIPC, hostNetwork, and hostPID allow containers to adopt the host’s namespaces.
Exploring Pod cgroups
Using systemd-cgls visualizes the pod’s cgroup hierarchy, confirming that each container can have individual resource limits while sharing a common parent cgroup.
$ sudo systemd-cgls memory3. Emulating a Pod with Docker
Install cgroup-tools and create a parent cgroup:
$ sudo apt-get install cgroup-tools
$ sudo cgcreate -g cpu,memory:/pod-fooCreate a sandbox container that will host shared namespaces:
$ docker run -d --rm \
--name foo_sandbox \
--cgroup-parent /pod-foo \
--ipc 'shareable' \
alpine sleep infinityLaunch the actual containers reusing the sandbox’s network and IPC namespaces:
# app container
$ docker run -d --rm \
--name app \
--cgroup-parent /pod-foo \
--network container:foo_sandbox \
--ipc container:foo_sandbox \
kennethreitz/httpbin
# sidecar container
$ docker run -d --rm \
--name sidecar \
--cgroup-parent /pod-foo \
--network container:foo_sandbox \
--ipc container:foo_sandbox \
curlimages/curl sleep 365dDocker cannot currently share the UTS namespace, but network and IPC sharing works, effectively reproducing most Pod behavior.
Inspecting cgroups and namespaces shows a hierarchy and namespace reuse similar to the Kubernetes pod examined earlier.
4. Summary
Containers and Pods share the same underlying Linux namespaces and cgroups, but a Pod is a higher‑level construct that groups containers on the same node, synchronizes their lifecycles, and deliberately reduces isolation to simplify inter‑container communication, making Pods resemble traditional VMs with sidecar patterns.
Related links:
https://github.com/opencontainers/runtime-spec/issues/345
https://github.com/opencontainers/runtime-spec/pull/388
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Efficient Ops
This public account is maintained by Xiaotianguo and friends, regularly publishing widely-read original technical articles. We focus on operations transformation and accompany you throughout your operations career, growing together happily.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
