Unlocking Container Networking: How Linux Namespaces and Bridges Work
This article explains the fundamentals of Linux network namespaces and bridge devices, showing how they isolate resources, form hierarchical PID trees, and enable inter‑namespace communication for container platforms like Docker and Kubernetes.
Preface
Container networking is a major challenge; both Docker and Kubernetes rely on computer networking. This article introduces Linux network namespaces and bridges to help understand container network principles.
1. Namespace analysis
Linux supports six types of namespaces: mount, UTS, IPC, PID, network, and user. The kernel uses struct nsproxy to associate a process with its namespaces.
struct task_struct {
...
struct nsproxy *nsproxy;
...
}
struct nsproxy {
atomic_t count;
struct uts_namespace *uts_ns;
struct ipc_namespace *ipc_ns;
struct mnt_namespace *mnt_ns;
struct pid_namespace *pid_ns;
struct user_namespace *user_ns;
struct net *net_ns;
};Example focusing on pid_namespace:
struct pid_namespace {
struct kref kref;
struct pidmap pidmap[PIDMAP_ENTRIES];
int last_pid;
struct task_struct *child_reaper;
struct kmem_cache *pid_cachep;
unsigned int level;
struct pid_namespace *parent;
#ifdef CONFIG_PROC_FS
struct vfsmount *proc_mnt;
#endif
};PID namespaces are hierarchical, forming a tree of namespaces where each node records its parent.
Member records the parent PID namespace.
PID assignment in task_struct:
p->pid = pid_nr(pid); // global PID
...
init_task_pid(p, PIDTYPE_PID, pid); // store struct pid pointerThe clone() system call with CLONE_NEWPID creates a new PID namespace. The following program demonstrates that the child sees PID 1 while the parent sees a different PID.
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdlib.h>
#include <errno.h>
char child_stack[5000];
int child(void* arg) {
printf("Child - %d
", getpid());
return 1;
}
int main() {
printf("Parent - fork child
");
int pid = clone(child, child_stack+5000, CLONE_NEWPID, NULL);
if (pid == -1) {
perror("clone:");
exit(1);
}
waitpid(pid, NULL, 0);
printf("Parent - child(%d) exit
", pid);
return 0;
}Running the program produces output similar to:
Parent - fork child
Parent - child(9054) exit
Child - 1From the result, the child’s PID namespace shows PID 1, while the parent sees a different global PID.
2. Bridge
Namespaces isolate kernel resources, preventing processes from seeing each other. To enable communication between namespaces, a veth pair and a bridge are used. Docker also employs namespaces and a bridge network mode.
2.1 Practical use of a bridge
Bridges can be assigned IP addresses to allow the host and bridged interfaces (including virtual interfaces) to communicate, typically within the same subnet. Screenshots illustrate bridge IP configuration and connectivity issues when subnets differ.
2.2 Bridge operation principle
A bridge works in promiscuous (promisc) mode, maintaining a MAC‑address filtering database. It forwards frames based on the destination MAC, using flooding for unknown unicast, broadcast, and multicast traffic.
After receiving a frame, the bridge selects the appropriate port based on the destination MAC. Cases: known unicast – forward to the specific port; unknown unicast – flood all ports except the source; broadcast/multicast – flood.
Command‑line examples to create and view a bridge:
# brctl addbr br0
# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.000000000000 no
docker0 8000.000000000000 noKernel source for creating a bridge:
int br_add_bridge(char *name) {
struct net_bridge *br;
if ((br = new_nb(name)) == NULL)
return -ENOMEM;
if (__dev_get_by_name(name) != NULL) {
kfree(br);
return -EEXIST;
}
br->next = bridge_list;
bridge_list = br;
...
register_netdev(&br->dev);
return 0;
}Key data structures:
struct net_bridge {
struct net_bridge *next;
rwlock_t lock;
struct net_bridge_port *port_list;
struct net_device dev;
struct net_device_stats statistics;
rwlock_t hash_lock;
struct net_bridge_fdb_entry *hash[BR_HASH_SIZE];
struct timer_list tick;
...
};
struct net_bridge_port {
struct net_bridge_port *next;
struct net_bridge *br;
struct net_device *dev;
int port_no;
...
};
struct net_bridge_fdb_entry {
struct net_bridge_fdb_entry *next_hash;
struct net_bridge_fdb_entry **pprev_hash;
atomic_t use_count;
mac_addr addr;
struct net_bridge_port *dst;
...
};These structures link network interfaces to a bridge.
Conclusion
Both namespaces and bridges are fundamental to container networking; understanding them simplifies learning Docker and Kubernetes networking.
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.
Open Source Linux
Focused on sharing Linux/Unix content, covering fundamentals, system development, network programming, automation/operations, cloud computing, and related professional knowledge.
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.
