Container Networking - Veth
I’ve been playing a lot with Kubernetes lately. After migrating some projects to it, and using it for a while, I’ve decided to investigate a bit of it’s building blocks.
Kubernetes has a lot of exciting topics to study, but at the base of it, there are the containers technologies (e.g., docker, rkt, cri-o), and if you go a level down on those technologies you see that containers don’t exists, but that they are a mix of primitives in the Linux kernel used together.
One of this primitives is namespaces, a basic view of it is that they restrict what a process can see, so the process thinks it has the sole system for itself. There are a few namespaces available, but the little experiment I’m going to do in this post is using the network namespace.
Network namespace provides isolation of the resources associated with networking. A new namespace will have its own interfaces, routing table, firewall rules, etc.
The question I was asking myself was “How does ‘containers’ communicate with each other?” as with everything in computers multiple solutions can be used to address the same problem.
A good mental model to what we want to do connecting two containers: You have two computers and want to wire them with an ethernet cable to be able to communicate back and forth.
I’m running ubuntu xenial64 with vagrant+virtualbox
To start, we now need two containers, I mean network namespaces.
Let’s first check if we have any existing namespace; we can use the ip tools for it:
Now we create two new namespaces:
If we list again, we now see the two namespaces:
We can verify that those namespaces are isolated, and have their own view of network resources. Running ip addr
on my ubuntu VM will list all addresses on a device. On my VM I can see three addresses.
If you run the same command on the new namespaces, it will only return the address for the loopback interface, because it has an isolated view of the system, not seen what the existing root namespace have configured.
Now that we can simulate the two computers - namespaces, we can move to the next step, wiring them for communication, and to do this we need a cable.
Linux has support for a virtual network device veth. We can think that veth is the cable we will use to wire the two computers.
Veth always comes in pairs, and whatever is sent to one side of it will pass to the other side.
To create a veth we also use the aid of the ip tools:
With this command we have created a veth, one side of it is named ‘v1’ and the peer side is named ‘v2’.
Listing the interfaces, we can see the new veth just created:
Continuing on our metaphor, next we need to plug our cable in both our computers. Each side of the veth goes on one network namespace, to simulate our wiring.
Now our my local VM won’t display the veth if I list the interfaces. But we can see them listing the interfaces of each namespace.
The last part to have our two computers - namespaces communicate is to configure the network, each one will have an ip address, and their interfaces must be up.
We can now ping one namespace from the other.
But a better example is to start a bash process inside each namespace, and create a simple chat using netcat.
Start a bash process inside the namespace ns1:
And start a netcat server on the port 8080:
In a different terminal window, start a bash process in the second namespace:
And connect to the other side using netcat:
And that’s it we did create two network namespace and connected them with a virtual network device (veth).
To clean up, deleted the namespaces:
Quite simple huh? On a next article, I’m going to connect containers using a bridge. :)