Linux Network Namespaces, veth Pairs & Software Bridges: Virtualization Primitives
Created: 2026-11-08 · Last updated: 2026-11-08 · Nejat Hakan
Executive Summary: How do container runtimes like Podman, Docker, and Kubernetes allocate every container its own dedicated
eth0interface, private IP address, independent routing table, and isolated firewall rules without booting a virtual machine? By combining three native Linux kernel virtualization primitives: Network Namespaces (ip netns), Virtual Ethernet Pairs (veth), and Layer-2 Linux Kernel Bridges (type bridge).
-
Network Namespaces (
ip netns)
Isolate entire kernel networking stacks: instantiate independent socket queues, routing tables, loopback devices, and Netfilter rulesets in RAM.
-
Virtual Ethernet (
veth) Pairs
Construct bidirectional kernel patch cables: packets pushed into one end immediately emerge from the peer end across namespace boundaries.
-
Linux Kernel Bridges
Deploy software-defined Layer-2 learning switches inside kernel memory, complete with MAC Forwarding Databases (FDB) and STP support.
-
Container Fabric from Scratch
Build a complete multi-tenant container network using raw
iproute2CLI commands—demystifying Docker and CNI bridge plugins forever.
1. The Three Primitives of Linux Network Virtualization
Rather than relying on proprietary software layers, container networking is assembled from standard kernel building blocks:
%%{init: {'flowchart': {'wrappingWidth': 600, 'subGraphTitleMargin': {'top': 15, 'bottom': 15}}}}%%
flowchart TB
subgraph RootNS["🖥️ Root Host Network Namespace"]
BR["🔀 Linux Bridge: br-app0<br/>Gateway: 10.88.0.1/24"]
VH1["veth-app1-br<br/>(Bridge Slave Port)"]
VH2["veth-app2-br<br/>(Bridge Slave Port)"]
BR --- VH1
BR --- VH2
end
subgraph NS1["📦 NetNS: ns-app1 (Container 1)"]
VC1["eth0 (veth peer)<br/>IP: 10.88.0.11/24"]
end
subgraph NS2["📦 NetNS: ns-app2 (Container 2)"]
VC2["eth0 (veth peer)<br/>IP: 10.88.0.12/24"]
end
VH1 <==>|"veth Virtual Patch Cable"| VC1
VH2 <==>|"veth Virtual Patch Cable"| VC2
- Network Namespace (
ip netns): A logical copy of the entire network stack. Processes assigned to a namespace cannot see, sniff, or bind to ports in other namespaces or the host. - Virtual Ethernet Pair (
veth): Acts like a physical Ethernet patch cable with two ends. Created as a linked pair; moving one end into a namespace bridges that namespace to the host. - Linux Bridge (
type bridge): Operates as an IEEE 802.1D software learning switch. It learns MAC addresses on its ports, populates its Forwarding Database (FDB), and switches frames between connectedvethandtapinterfaces.
2. Managing Network Namespaces (ip netns)
Network namespaces are managed directly via iproute2:
# 1. Create two isolated network namespaces
sudo ip netns add ns-web
sudo ip netns add ns-db
# 2. List all active network namespaces
ip netns list
# 3. Namespaces are represented as bind mounts in the filesystem
ls -la /var/run/netns/
Executing Commands Inside a Namespace
To run commands inside an isolated namespace, use ip netns exec (or the compact shortcut ip -n <name>):
# Check interfaces inside ns-web (only unconfigured 'lo' exists initially)
sudo ip -n ns-web link show
# Bring up the loopback interface inside the namespace (MANDATORY)
sudo ip -n ns-web link set lo up
# Execute arbitrary user-space binaries inside the isolated namespace
sudo ip netns exec ns-web ss -tulpn
3. The veth Virtual Patch Cable Mechanics
A veth interface cannot exist alone; it is always allocated as an interconnected pair:
# Create a veth pair: 'veth-host' and 'veth-guest'
sudo ip link add veth-host type veth peer name veth-guest
# Move 'veth-guest' into the 'ns-web' namespace
sudo ip link set veth-guest netns ns-web
# Rename 'veth-guest' to standard 'eth0' inside the namespace
sudo ip -n ns-web link set dev veth-guest name eth0
# Assign IP address and bring both ends up
sudo ip addr add 10.88.0.1/24 dev veth-host
sudo ip link set veth-host up
sudo ip -n ns-web addr add 10.88.0.2/24 dev eth0
sudo ip -n ns-web link set eth0 up
Now, pinging 10.88.0.2 from the host traverses the veth virtual wire directly into ns-web.
4. The Linux Bridge: Software Layer-2 Switching
When connecting three or more namespaces together, point-to-point veth cables are insufficient. We attach the host ends of all veth cables into a Linux Bridge:
# 1. Create the virtual bridge
sudo ip link add name br-app0 type bridge
# 2. Assign the bridge an IP (acts as the default gateway for all attached namespaces)
sudo ip addr add 10.88.0.1/24 dev br-app0
sudo ip link set dev br-app0 up
# 3. Enslave a veth host-end to the bridge
sudo ip link set veth-host master br-app0
# 4. Inspect bridge member ports and Forwarding Database (FDB)
bridge link show
bridge fdb show dev br-app0
5. Hands-On Lab: Building a Container Network Fabric from Scratch
Execute this complete automation script to construct a bridged, multi-tenant virtual network with full internet access using pure Linux kernel tools:
#!/usr/bin/env bash
# File: /opt/net-ops/build_container_fabric.sh
set -euo pipefail
echo "=== 1. Creating Linux Bridge Gateway (br-app0) ==="
sudo ip link add name br-app0 type bridge
sudo ip addr add 10.88.0.1/24 dev br-app0
sudo ip link set dev br-app0 up
echo "=== 2. Creating Two Isolated Namespaces ==="
sudo ip netns add ns-app1
sudo ip netns add ns-app2
echo "=== 3. Creating and Connecting veth Virtual Patch Cables ==="
# App 1 Cable
sudo ip link add veth-app1-br type veth peer name eth0 netns ns-app1
sudo ip link set veth-app1-br master br-app0 up
# App 2 Cable
sudo ip link add veth-app2-br type veth peer name eth0 netns ns-app2
sudo ip link set veth-app2-br master br-app0 up
echo "=== 4. Configuring Networking Inside Namespaces ==="
# Configure ns-app1
sudo ip -n ns-app1 link set lo up
sudo ip -n ns-app1 addr add 10.88.0.11/24 dev eth0
sudo ip -n ns-app1 link set eth0 up
sudo ip -n ns-app1 route add default via 10.88.0.1
# Configure ns-app2
sudo ip -n ns-app2 link set lo up
sudo ip -n ns-app2 addr add 10.88.0.12/24 dev eth0
sudo ip -n ns-app2 link set eth0 up
sudo ip -n ns-app2 route add default via 10.88.0.1
echo "=== 5. Enabling Internet Access via Host NAT Masquerading ==="
sudo sysctl -w net.ipv4.ip_forward=1 > /dev/null
sudo nft add table ip container_nat
sudo nft add chain ip container_nat post { type nat hook postrouting priority 100 \; }
sudo nft add rule ip container_nat post oifname "eth0" ip saddr 10.88.0.0/24 masquerade
echo "=== 6. Verification: Inter-Namespace & WAN Reachability ==="
# Test App 1 pinging App 2 across the bridge
sudo ip netns exec ns-app1 ping -c 2 10.88.0.12
# Test App 1 pinging Google DNS across the host NAT
sudo ip netns exec ns-app1 ping -c 2 8.8.8.8
echo "=== Container Network Fabric Successfully Built! ==="
6. High-Speed TCP Congestion Tuning: Google BBR & FQ
Virtualization and container hosts handling thousands of concurrent connections should replace legacy packet-loss-based TCP congestion control (cubic) with Google BBR (Bottleneck Bandwidth and RTT):
%%{init: {'flowchart': {'wrappingWidth': 600}}}%%
flowchart TB
CUBIC["Legacy TCP CUBIC<br/>Increases sending rate until packet loss occurs.<br/>Causes bufferbloat and latency spikes on long pipes."]
BBR["Modern Google BBR + FQ Scheduler<br/>Measures actual bottleneck bandwidth and minimum RTT.<br/>Paces packet transmission at max link speed without bloating buffers."]
Applying BBR & Fair Queueing in Debian
Create /etc/sysctl.d/99-tcp-bbr.conf:
# File: /etc/sysctl.d/99-tcp-bbr.conf
# 1. Set Fair Queue (FQ) as default queuing discipline
net.core.default_qdisc = fq
# 2. Enable Google BBR TCP Congestion Control
net.ipv4.tcp_congestion_control = bbr
# 3. Expand Socket Buffer Limits for High-Bandwidth Container Links (16MB max)
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
# 4. Enable TCP Fast Open (TFO)
net.ipv4.tcp_fastopen = 3
Apply immediately:
7. Next Steps
Now that you understand the raw kernel virtualization primitives (ip netns, veth, and bridges), examine how modern container runtimes and Kubernetes orchestrate them automatically:
-
Container Networking & CNI Architecture
Explore Docker bridges, rootless Podman (
pasta/slirp4netns), the CNI plugin specification, and Kubernetes overlay networks (Flannel vs. Cilium eBPF).