Attach Container to a NIC

Sometimes you may need to attach some container's virtual network interface to the NIC of the machine hosting it, for example, to run some data plane traffic through the container.

Although CORD doesn't fully support this natively, there are some (hackish) ways to do this manually.

Create a bridge and a veth

The easiest way to do this is to skip Kubernetes and directly attach the Docker container link it to the host network interface through a Virtual Ethernet Interface Pair (veth pair).

Let's see how.

Let's assume you're running a three node Kubernetes deployment, and that you're trying to attach a container already deployed called vcore-5b4c5478f-lxrpb to a physical interface eth1 (already existing on one of the three hosts, running your container). The virtual interface inside the container will be called eth2.

You get the name of the container by running:

$ kubectl get pods [-n NAMESPACE]
NAME                      READY     STATUS    RESTARTS   AGE
vcore-5b4c5478f-lxrpb     1/1       Running   1          7d

To find out on which of the three nodes the container has been deployed on, type:

$ kubectl describe pod  vcore-5b4c5478f-lxrpb | grep Node
Node:           node3/10.90.0.103
Node-Selectors:  <none>

As you can see from the first line, the container has been deployed by Kubernetes on the Docker daemon running on node 3 (this is just an example), in this case, with IP 10.90.0.103.

Next, SSH into the node and look for the specific Docker container ID:

$ container_id=$(sudo docker ps | grep vcore-5b4c5478f-lxrpb | head -n 1 | awk '{print $1}')
85fed7deea7b

The interface on the hosting machine should be turned off first

sudo ip link set eth1 down

Create a veth called veth0 and add to it the new virtual interface eth2:

sudo ip link add veth0 type veth peer name eth2

Now add the virtual network interface eth2 to the container namespace:

sudo ip link set eth2 netns ${container_id}

Bring up the virtual interface:

sudo ip netns exec ${container_id} ip link set eth2 up

Bring up veth0:

sudo ip link set veth0 up

Create a bridge named br1, and add veth0 to it and the host interface eth1:

sudo ip link add br1 type bridge
sudo ip link set veth0 master br1
sudo ip link set eth1 master br1

Bring up again the host interface and the bridge:

sudo ip link set eth1 up
sudo ip link set br1 up

At this point, you should see an additional interface eth2 inside the container:

$ kubectl exec -it vcore-5b4c5478f-lxrpb /bin/bash
$ ip link show
$ node3:~$ ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
    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 mq state UP mode DEFAULT group default qlen 1000
    link/ether c4:54:44:8f:b7:74 brd ff:ff:ff:ff:ff:ff
3: eth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether d6:84:33:2f:8c:92 brd ff:ff:ff:ff:ff:ff

Cleanup (remove bridge and veth)

To delete the connection and bring the system back to the original state, execute the following:

ip link set veth0 down
ip link delete veth0
ip netns exec ${container_id} ip link set eth2 down
ip netns exec ${container_id} ip link delete eth2
ip link set eth1 down
ip link set br1 down
brctl delbr br1
ip link set eth1 up