Container Networking: Part Two
This is the second part of the series Container Networking. I will cover Network Namespaces and Linux Bridges in this blog post.
Linux Namespaces wiki says
Namespaces are a feature of the Linux kernel that partition kernel resources
such that one set of processes sees one set of resources, while another set
of processes sees a different set of resources.
So the process isolation is provided using namespaces and cgroups. This makes each process to see it’s personal view of system (files, process, network interfaces, hostname).
Some more expert from wiki
Since kernel version 5.6, there are 8 kinds of namespaces.
Network namespaces virtualize the network stack. On creation, a network
namespace contains only a loopback interface. Each network interface
(physical or virtual) is present in exactly 1 namespace and can be moved
between namespaces.
ip-netns utility helps to create network namespaces. Let’s see how.
Network namespaces demo
Create a network namespaces
sudo ip netns add ns1
List them
ip netns list
ns1
Only loopback interface is available in ns1
namespace.
sudo ip netns exec ns1 ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
Following diagram helps to visualize the setup
For brevity, I will not list lo
and enp0s3
interfaces in rest of
the diagrams.
Now, let’s create a veth
pair
sudo ip link add vethX type veth peer name vethY
sudo ip link set vethX up
sudo ip link set vethY up
Attach one end of the veth
pair to ns1
namespace.
sudo ip link set vethX netns ns1
This ensures processes in the default/root namespace could not see vethX
interface
ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
link/ether 02:fd:4d:34:55:76 brd ff:ff:ff:ff:ff:ff
18: vethY@if19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 5a:bc:4d:7e:76:b1 brd ff:ff:ff:ff:ff:ff link-netns ns1
And processes in ns1
namespace could not see vethY
interface.
sudo ip netns exec ns1 ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
19: vethX@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 5e:4b:13:90:7d:63 brd ff:ff:ff:ff:ff:ff link-netnsid 0
In similar fashion, we can create another namespace. Create a new veth
pair. And then attach one end of veth
pair to a namespace.
sudo ip netns add ns2
sudo ip link add vethP type veth peer name vethQ
sudo ip link set vethP up
sudo ip link set vethQ up
sudo ip link set vethP netns ns2
Now the last part is to connect these two namespaces with a Bridge.
Bridge connects two LAN segments together. We will create a new bridge and
attach vethY
and vethQ
to this bridge.
sudo ip link add name br0 type bridge
sudo ip link set dev br0 up
sudo ip link set vethY master br0
sudo ip link set vethQ master br0
As we have looked in last blog post, any packet on bridge br0
is seen on
all the veths
we have created. You can try it on yourself.
Now by this time, you might have started imagining how a container achieves the network isolation using Virtual Ethernet, Bridge and Linux Namespaces. We will take a look at docker container in next blog post.
Before you jump, let’s clean up the setup
sudo ip link del br0
sudo ip link del vethY
sudo ip link del vethQ
sudo ip netns del ns1
sudo ip netns del ns2