Building a Multi-Host Virtual Network
Throughout this book, we have explored the building blocks of Linux networking:
- Network namespaces
- Virtual Ethernet devices
- Linux bridges
- Routing
- GRE tunnels
- VXLAN overlays
- Policy routing
- VRFs
Individually, these technologies are useful. However, modern platforms rarely use them in isolation.
Kubernetes, OpenStack, VMware, cloud providers, and SDN platforms combine these primitives to create virtual networks that span multiple physical hosts while appearing as a single network to applications.
In this chapter, we will bring everything together and build a simple multi-host virtual network using Linux networking primitives.
The goal is not to build a production-ready solution.
The goal is to understand the architecture that many modern networking systems are built upon.
By the end of this chapter, you will understand how workloads running on different servers can communicate as if they are connected to the same Ethernet switch.
The Problem
Suppose we have two Linux servers:
+---------+ +---------+
| Host A | | Host B |
+---------+ +---------+
| |
| |
+----------- Network -----------+
Each host runs workloads.
These workloads might be:
- Virtual machines
- Containers
- Kubernetes Pods
- Application namespaces
Example:
Host A: App A
Host B: App B
We want:
App A <-> App B
to communicate directly on the same virtual Layer 2 network.
However, the physical network between hosts is routed.
The workloads cannot simply share a Linux bridge.
We need an overlay network.
Final Topology
By the end of this chapter, we will build:
Underlay Network
192.168.100.1 192.168.100.2
Host A Host B
| |
+--------+--------+
|
Physical Network
------------------------------------------------
Overlay Network
ns-a ns-b
10.10.10.1 10.10.10.2
| |
veth veth
| |
br0 br0
| |
vxlan100 ================= vxlan100
From the perspective of the namespaces:
10.10.10.1 and 10.10.10.2
appear to be on the same Ethernet network
even though they are running on different hosts.
What We Will Build
Each host contains:
Namespace
|
veth
|
Linux Bridge
|
VXLAN Interface
The bridge performs Layer 2 switching.
The VXLAN interface transports Ethernet frames between hosts.
This architecture closely resembles the design used by:
- OpenStack
- Flannel VXLAN
- VMware NSX
- Many cloud networking systems
Step 1: Create a Namespace
On Host A:
sudo ip netns add ns-a
On Host B:
sudo ip netns add ns-b
Verify:
ip netns
Example:
ns-a
or:
ns-b
Step 2: Create a veth Pair
Host A:
sudo ip link add veth-a type veth peer name eth0 netns ns-a
Host B:
sudo ip link add veth-b type veth peer name eth0 netns ns-b
This creates a virtual cable between:
Host Network Namespace
and
Application Namespace
Step 3: Create a Linux Bridge
Host A:
sudo ip link add br0 type bridge
sudo ip link set br0 up
Host B:
sudo ip link add br0 type bridge
sudo ip link set br0 up
Verify:
bridge link show
The bridge currently has no ports.
Step 4: Attach veth Interfaces
Host A:
sudo ip link set veth-a master br0
sudo ip link set veth-a up
Host B:
sudo ip link set veth-b master br0
sudo ip link set veth-b up
The topology now looks like:
Namespace
|
veth
|
br0
on each host.
Step 5: Configure Namespace Interfaces
Host A:
sudo ip netns exec ns-a \
ip addr add 10.10.10.1/24 dev eth0
sudo ip netns exec ns-a \
ip link set lo up
sudo ip netns exec ns-a \
ip link set eth0 up
Host B:
sudo ip netns exec ns-b \
ip addr add 10.10.10.2/24 dev eth0
sudo ip netns exec ns-b \
ip link set lo up
sudo ip netns exec ns-b \
ip link set eth0 up
At this point the namespaces are configured but cannot yet communicate.
The bridges are isolated from one another.
Step 6: Create the VXLAN Overlay
Host A:
sudo ip link add vxlan100 \
type vxlan \
id 100 \
local 192.168.100.1 \
remote 192.168.100.2 \
dstport 4789
Host B:
sudo ip link add vxlan100 \
type vxlan \
id 100 \
local 192.168.100.2 \
remote 192.168.100.1 \
dstport 4789
Bring the interfaces up:
sudo ip link set vxlan100 up
on both hosts.
Step 7: Connect VXLAN to the Bridge
Host A:
sudo ip link set vxlan100 master br0
Host B:
sudo ip link set vxlan100 master br0
Now each bridge has:
Bridge
├── Local veth
└── VXLAN tunnel
The bridge can switch traffic between local workloads and remote hosts.
Verifying the Topology
Inspect bridge ports:
bridge link show
Expected output:
veth-a master br0
vxlan100 master br0
or:
veth-b master br0
vxlan100 master br0
depending on the host.
Testing Layer 2 Connectivity
From Host A:
sudo ip netns exec ns-a ping 10.10.10.2
Expected:
64 bytes from 10.10.10.2
The packet path is:
ns-a
|
veth-a
|
br0
|
vxlan100
|
Physical Network
|
vxlan100
|
br0
|
veth-b
|
ns-b
This is effectively a virtual Ethernet switch spanning multiple hosts.
Observing ARP
Start a capture:
sudo tcpdump -ni any arp
Run:
sudo ip netns exec ns-a ping 10.10.10.2
Observe:
ARP Request
Who has 10.10.10.2?
The ARP frame crosses the VXLAN tunnel.
This demonstrates that VXLAN transports complete Ethernet frames, not just IP packets.
Observing VXLAN Traffic
Capture VXLAN traffic:
sudo tcpdump -ni any udp port 4789
Generate traffic:
sudo ip netns exec ns-a ping 10.10.10.2
Example:
192.168.100.1.4789 >
192.168.100.2.4789
Notice:
The underlay sees UDP packets.
The overlay sees Ethernet frames.
This is the essence of overlay networking.
Inspecting the Bridge Forwarding Database
Linux bridges maintain a MAC address table.
View it:
bridge fdb show
Example:
52:54:00:aa:bb:cc dev veth-a
52:54:00:dd:ee:ff dev vxlan100
The bridge learns:
MAC Address -> Port
just like a physical switch.
Unknown Traffic and Flooding
When the bridge does not know a destination MAC:
Unknown Unicast
it floods the frame.
The frame is sent:
veth
vxlan
and potentially every VXLAN peer.
This is acceptable in small environments but becomes inefficient at scale.
Large deployments solve this using:
- EVPN
- BGP
- SDN controllers
- Open vSwitch control planes
Scaling Beyond Two Hosts
Our lab contains:
Host A
Host B
Real environments may contain:
100 Hosts
1000 Hosts
The architecture remains similar:
Namespace / VM
|
Bridge
|
VXLAN
|
Routed Network
The control plane becomes more sophisticated, but the underlying concepts remain the same.
How Kubernetes Uses Similar Concepts
Many Kubernetes networking solutions use a similar architecture.
A Pod:
Pod
|
veth
|
Host Namespace
|
Overlay Network
Depending on the CNI implementation:
- VXLAN
- Geneve
- IP-in-IP
- Native routing
may be used to transport traffic between nodes.
Although the implementation details differ, the networking primitives are largely the same ones we have used throughout this book.
Troubleshooting Checklist
When a multi-host virtual network is not working, verify:
VXLAN Interface
ip link show vxlan100
Bridge Configuration
bridge link show
Forwarding Database
bridge fdb show
Underlay Connectivity
ping <remote-host-ip>
VXLAN Traffic
tcpdump -ni any udp port 4789
Namespace Configuration
ip netns exec ns-a ip addr
ARP Resolution
ip netns exec ns-a ip neigh
These commands solve most overlay-network troubleshooting problems.
What We Built
Let's review what we created:
Application Namespace
|
veth
|
Bridge
|
VXLAN
|
Physical Network
|
VXLAN
|
Bridge
|
veth
|
Application Namespace
This architecture combines nearly every major networking concept introduced throughout this book.
You have effectively built a simplified version of the networking layer used by many cloud and virtualization platforms.
Key Takeaways
- Multi-host virtual networks are built by combining Linux networking primitives.
- Network namespaces provide workload isolation.
- veth pairs connect workloads to the host network.
- Linux bridges provide Layer 2 switching.
- VXLAN transports Ethernet frames across routed networks.
- The physical network acts as the underlay network.
- The virtual network acts as the overlay network.
- ARP, broadcasts, and Ethernet frames can traverse VXLAN tunnels.
- Linux bridges learn MAC addresses just like physical switches.
- Modern cloud networking systems are built on the same fundamental concepts demonstrated in this chapter.