Linux network namespaces

Namespaces are one of the fundamental building blocks for containers. According to Wikipedia a namespace is:

::

a feature of the Linux kernel that partitions kernel resources such that one set of processes sees one set of resources while another set of processes sees a different set of resources.

Namespaces

There are 8 types of namespaces in the Linux kernel (a new time namespace was recently added to the kernel source. So not all versions of the kernel will have this). You can use lsns command to list all the namespaces in the system. In this post I will share my understanding and the use-case of network namespace.

Network Namespace

I will be creating a virtual netowork as below. I will be explaining the details along the way. Please remember that all this happens with in a single system.

+----------------+                                +----------------+
|                |                                |                |
|                |                       +--------+                |
|                |   +-------------------+VETH1   |                |
|               ++-------+               |10.1.1.1|                |
|               |        |               |        |                |
|   DEFAULT     | VETH0  |               +--------+    BLUE        |
|   NAMESPACE   | 10.1.1.2                        |    NAMESPACE   |
|               ++---+---+               +--------+                |
|                |   |                   |VETH3   |                |
|                |   +-------------------+10.1.1.3|                |
|                |                       |        |                |
|                |                       +--------+                |
+----------------+                                +----------------+

A new linux system has no other namespaces except for the default one. All the physical interfaces of the system belong to this. The ip command is only one I will need to play with the network namespaces. ip link list and ip netns list will list the interfaces and network namespaces respectively.

# ip link list
  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: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode    DEFAULT group default qlen 1000
    link/ether 9a:8d:09:82:8f:ba brd ff:ff:ff:ff:ff:ff

# ip netns list
#

The second command output shows nothing because there are no namespaces. Let me create one.

# ip netns add blue
# ip netns list
blue (id: 0)

I will create a veth pair with the below command. The veth interfaces come in pairs. Each of which can be attached to different namespaces to connect them (I will show what it means in the next steps).

# ip link add veth0 type veth peer name veth1
# ip link list
  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: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 9a:8d:09:82:8f:ba brd ff:ff:ff:ff:ff:ff
  8: veth1@veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether f2:cf:0e:6f:d9:5b brd ff:ff:ff:ff:ff:ff
  9: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether b2:1d:21:8d:da:26 brd ff:ff:ff:ff:ff:ff

By default any new virtual interfaces created are added to the default namespace unless explicitly specified. I will move one of the veth interface pair to the blue namespace I created.

# ip link set veth1 netns blue
# ip link list
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: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 9a:8d:09:82:8f:ba brd ff:ff:ff:ff:ff:ff
9: veth0@if8: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether b2:1d:21:8d:da:26 brd ff:ff:ff:ff:ff:ff link-netnsid 0

Now when I ran the ip link list command, the veth1 is no longer in the default namespace and so the output only shows veth0 along with the lo and eth0 interfaces.

To run any commands inside a namespace, I have to run exec inside that namespace like below.

# ip netns exec blue ip link list
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
8: veth1@if9: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT groudefault qlen 1000
    link/ether f2:cf:0e:6f:d9:5b brd ff:ff:ff:ff:ff:ff link-netnsid 0

The output only shows the interfaces in the blue namespace and not the ones from the default one. Let me assign an ipaddress to the interface in the blue namespace and bring it UP. Like before to see the ip a details inside the namespace I have to exec into it.

# ip netns exec blue ip addr add 10.1.1.1/24 dev veth1
# ip netns exec blue ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
8: veth1@if9: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether f2:cf:0e:6f:d9:5b brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.1.1.1/24 scope global veth1
    valid_lft forever preferred_lft forever
# ip netns exec blue ip link set dev veth1 up

I will create another veth pair and add one of the interface into the blue namespace and this interface will have the ip 10.1.1.3. Also I will assign the IP 10.1.1.2 to the veth0 interface in the default namespace but will not bring it UP.

# ip link add veth2 type veth peer name veth3
# ip link set veth3 netns blue
# ip netns exec blue ip addr add 10.1.1.3/24 dev veth3
# ip netns exec blue ip link set dev veth3 up
# ip addr add 10.1.1.2/24 dev veth0

Now the interfaces veth1 and veth3 are in the same namespace. Also they are in the same network subnet and so should be reachable.

# ip netns exec blue ping 10.1.1.3
PING 10.1.1.3 (10.1.1.3) 56(84) bytes of data.
64 bytes from 10.1.1.3: icmp_seq=1 ttl=64 time=0.020 ms

# ip netns exec blue ping 10.1.1.1
PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data.
64 bytes from 10.1.1.1: icmp_seq=1 ttl=64 time=0.020 ms

# ping 10.1.1.1
PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data.
^C
--- 10.1.1.1 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3068ms

This is as good as having 2 systems in the same subnet. If these interfaces are assigned to any VM or a container, they will be able talk to each other. But when I ping the IP 10.1.1.1 from the default namespace, it is not reachable as there is no connection or route between these two networks.

In the next step I will bring UP the veth0 interface. This basically connects the default and the blue namesapces. Once the link is UP, we can reach the veth1 IP from the default namespace and veth0 from the blue namespace.

# ip link set dev veth0 up
# ping 10.1.1.1
PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data.
64 bytes from 10.1.1.1: icmp_seq=1 ttl=64 time=0.025 ms

# ip netns exec blue ping 10.1.1.2
PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data.
64 bytes from 10.1.1.2: icmp_seq=1 ttl=64 time=0.023 ms

# ip netns exec blue ip route
10.1.1.0/24 dev veth1 proto kernel scope link src 10.1.1.1
# ip route
default via 134.209.144.1 dev eth0 proto static
10.1.1.0/24 dev veth0 proto kernel scope link src 10.1.1.2

Usecase

Great so far! But what is the use case of this? Let’s see that in a TLDR fashion.

When only the interfaces inside the blue namespace are up they were able to talk to each other but not to the outside world. This is how a completely private network can be created. Once the interface in the default namespace came up, we were able to reach the host network and this can be used to create host only networks i.e, systems that can only work inside that host as the networks and the interfaces are confined to a single host.

Hope that gave some insights into the network namespace. In my future posts I will be exploring other kind of namesapces and see how all of these collectively make container’s what they are and how the isolation of resources work.