Asignar interfaz física a Docker exclusivamente

Me gustaría ejecutar una prueba de red de alto rendimiento en un contenedor docker y no quiero la sobrecarga de los puentes (por lo que pipeworks no funcionará AFAIK). Me gustaría asignar (además del dispositivo docker veth normal) una interfaz de red física de 40GbE desde el host a un contenedor docker como en el modo lxc "phys". Esto debería hacer que la interfaz física se vuelva invisible para el host.

En mi búsqueda, encontré soluciones antiguas que incluían pasar parámetros lxc-config a docker, pero las versiones más nuevas de docker ya no usan las herramientas lxc, por lo que eso no puede funcionar.

Siguiendo la sugerencia aquí: https://groups.google.com/d/msg/docker-user/pL8wlmiuAEU/QfcoFcKI3kgJ se encontró una solución.No busqué modificar el script de canalización como se mencionó anteriormente, en su lugar, utilicé los comandos requeridos directamente. Vea también la publicación de blog posterior: http://jason.digitalinertia.net/exposing-docker-containers-with-sr-iov/.

Los siguientes comandos de la herramienta de espacio de nombres de red de bajo nivel (es decir, no específicos de docker) se pueden usar para transferir una interfaz del host a un contenedor de docker:

CONTAINER=slave-play # Name of the docker containerHOST_DEV=ethHOST     # Name of the ethernet device on the hostGUEST_DEV=test10gb   # Target name for the same device in the containerADDRESS_AND_NET=10.101.0.5/24# Next three lines hooks up the docker container's network namespace # such that the ip netns commands below will workmkdir -p /var/run/netnsPID=$(docker inspect -f '{{.State.Pid}}' $CONTAINER)ln -s /proc/$PID/ns/net /var/run/netns/$PID# Move the ethernet device into the container. Leave out # the 'name $GUEST_DEV' bit to use an automatically assigned name in # the containerip link set $HOST_DEV netns $PID name $GUEST_DEV# Enter the container network namespace ('ip netns exec $PID...') # and configure the network device in the containerip netns exec $PID ip addr add $ADDRESS_AND_NET dev $GUEST_DEV# and bring it up.ip netns exec $PID ip link set $GUEST_DEV up# Delete netns link to prevent stale namespaces when the docker# container is stoppedrm /var/run/netns/$PID

>Una advertencia menor sobre el nombre de la interfaz si su host tiene muchos dispositivos ethX (el mío tenía eth0 - eth5). Por ejemplo, digamos que mueve eth3 al contenedor como eth1 en el espacio de nombres de contenedores. Cuando detenga el contenedor, el núcleo intentará mover el dispositivo eth1 del contenedor de vuelta al host, pero observe que ya hay un dispositivo eth1. Luego cambiará el nombre de la interfaz a algo arbitrario; me tomó un tiempo encontrarlo de nuevo. Por esta razón edité /etc / udev / rules.d / 70-persistente-net.reglas (creo que este nombre de archivo es común a la mayoría de las distribuciones de Linux populares; estoy usando Debian) para dar a la interfaz en cuestión un nombre único e inconfundible, y usarlo tanto en el contenedor como en el host.

Como no estamos usando docker para hacer esta configuración, las herramientas estándar del ciclo de vida de docker (por ejemplo, docker run --restart=on-failure:10 ...) no se puede utilizar. La máquina host en cuestión ejecuta Debian Wheezy, así que escribí el siguiente script de inicio:

#!/bin/sh### BEGIN INIT INFO# Provides:          slave-play# Required-Start:    $local_fs $network $named $time $syslog $docker# Required-Stop:     $local_fs $network $named $time $syslog $docker# Default-Start:     2 3 4 5# Default-Stop:      0 1 6# Description:       some slavishness### END INIT INFOCONTAINER=slave-playSCRIPT="docker start -i $CONTAINER"RUNAS=rootLOGFILE=/var/log/$CONTAINER.logLOGFILE=/var/log/$CONTAINER.logHOST_DEV=test10gbGUEST_DEV=test10gbADDRESS_AND_NET=10.101.0.5/24start() {  if [ -f /var/run/$PIDNAME ] && kill -0 $(cat /var/run/$PIDNAME); thenecho 'Service already running' >&2return 1  fi  echo 'Starting service…' >&2  local CMD="$SCRIPT &> \"$LOGFILE\" &"  su -c "$CMD" $RUNAS   sleep 0.5 # Nasty hack so that docker container is already running before we do the rest  mkdir -p /var/run/netns  PID=$(docker inspect -f '{{.State.Pid}}' $CONTAINER)  ln -s /proc/$PID/ns/net /var/run/netns/$PID  ip link set $HOST_DEV netns $PID name $GUEST_DEV  ip netns exec $PID ip addr add $ADDRESS_AND_NET dev $GUEST_DEV  ip netns exec $PID ip link set $GUEST_DEV up  rm /var/run/netns/$PID  echo 'Service started' >&2}stop() {  echo "Stopping docker container $CONTAINER" >&2  docker stop $CONTAINER  echo "docker container $CONTAINER stopped" >&2}case "$1" in  start)start;;  stop)stop;;  restart)stopstart;;  *)echo "Usage: $0 {start|stop|restart}"esac

Un poco hacky, pero funciona :)

pipework puede mover una interfaz de red física del espacio de nombres de red predeterminado al de contenedor:

    $ sudo pipework --direct-phys eth1 $CONTAINERID 192.168.1.2/24

Para obtener más información, consulte aqui.

Escribo un complemento de red docker para hacer esto.

https://github.com/yunify/docker-plugin-hostnic

docker pull qingcloud/docker-plugin-hostnicdocker run -v /run/docker/plugins:/run/docker/plugins -v /etc/docker/hostnic:/etc/docker/hostnic --network host --privileged qingcloud/docker-plugin-hostnic docker-plugin-hostnicdocker network create -d hostnic --subnet=192.168.1.0/24 --gateway 192.168.1.1 hostnicdocker run -it --ip 192.168.1.5 --mac-address 52:54:0e:e5:00:f7 --network hostnic ubuntu:14.04 bash