Verifying VETH pairs

Of all the Linux network constructs we've reviewed in this book, VETH pairs are likely the most essential. Being namespace aware they allow you to connect a container in a unique namespace to any other namespace including the default. And while Docker handles all of this for you, it is useful to be able to determine where the ends of a VETH pair live and correlate them to determine what purpose a VETH pair is serving. In this recipe, we'll review in depth how to find and correlate the ends of a VETH pair.

Getting ready

In this recipe, we'll be using a single Docker host. It is assumed that Docker is installed and in its default configuration. You'll also need root-level access in order to inspect and change the hosts networking and firewall configuration.

How to do it…

The main use case for VETH pairs in Docker is to connect a containers network namespace back to the default network namespace. It does this by placing one of the VETH pair on the docker0 bridge and the other end in the container. The container side of the VETH pair gets an IP address assigned to it and then renamed to eth0.

When looking to match up ends of a VETH pair for a container, there are two scenarios. The first is when you start with the end in the default namespace, and the second is when you start the end in the container namespace. Let's walk through each case and how to correlate them together.

Let's first start with knowing the host end of the interface. For instance, let's say we're looking for the container end of this interface:

user@docker1:~$ ip -d link show
…<Additional output removed for brevity>… 
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default
    link/ether 02:42:ab:27:0e:3e brd ff:ff:ff:ff:ff:ff promiscuity 0
    bridge
6: vetha431055@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default
    link/ether 82:69:cb:b6:9a:db brd ff:ff:ff:ff:ff:ff promiscuity 1
    veth
user@docker1:~$

There are a couple things to point out here. First, passing the -d parameter to the ip link subcommand displays extra detail about the interface. In this case, it confirms that the interface is a VETH pair. Second, VETH pair naming generally follows the <end1>@<end2> naming convention. In this case, we can see that the end vetha431055 is the local interface and the if5 is the other end. if5 stands for interface 5 or the index ID of the 5th interface on the host. Since VETH interfaces are always created in pairs, it's fair to assume that the end of this VETH pair with index 6 is very likely index 5 or 7. In this case, the naming is indicating that it's 5, but we can confirm that using the ethtool command:

user@docker1:~$ sudo ethtool -S vetha431055
NIC statistics:
     peer_ifindex: 5
user@docker1:~$

As you can see, the other end of this VETH pair has an interface index of 5 as the name indicated. Now finding which container has 5 is the hard part. To do this, we need to inspect each container for a specific interface number. If you're running a lot of containers, this can be a challenge. Instead of inspecting each container manually, you can loop through them using Linux xargs. For instance, look at this command:

docker ps -q | xargs --verb -I {} docker exec {} ip link | grep ^5:

What we're doing here is returning a list of the container IDs for all running containers and then passing that list to xargs. In turn, xargs is using those container IDs to run a command inside the container with docker exec. That command happens to be the ip link command, which will return a list of all interfaces and their associated index numbers. If any of that information returned starts with a 5:, indicating an interface index of 5, we'll print it to the screen. In order to see which container has the interface in question, we have to run the xargs command in verbose mode (--verb), which will show us each command as it runs. The output will look like this:

user@docker1:~$ docker ps -q | xargs --verb -I {} docker exec {} ip link | grep ^5:
docker exec 4b521df22184 ip link
docker exec 772e12b15c92 ip link
docker exec d8f3e7936690 ip link
docker exec a2e3201278e2 ip link
docker exec f9216233ba56 ip link
docker exec ea32565ece0c ip link
5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
user@docker1:~$

As you can see, there were six containers running on this host. We didn't find the interface ID we were looking for until the last container. Given the container ID, we can tell which container has the other end of the VETH interface.

Note

You could confirm this by running the docker exec -it ea32565ece0c ip link command.

Now, let's try another example of starting with the container end of the VETH pair. This is slightly easier since the naming of the interface tells us the index of the host-side matching interface:

user@docker1:~$ docker exec web1 ip -d link show dev eth0
5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    veth
user@docker1:~$

We can then validate that the interface on the host with index 6 is a match to the interface with an index 5 in the container by once again using the ethtool:

user@docker1:~$ ip -d link show | grep ^6:
6: vetha431055@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default
user@docker1:~$ sudo ethtool -S vetha431055
[sudo] password for user:
NIC statistics:
     peer_ifindex: 5
user@docker1:~$
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset