Attribuer une interface physique à Docker exclusivement

12

Je voudrais exécuter un test de réseau haute performance dans un conteneur Docker et je ne veux pas les frais généraux de pontage (donc les canalisations ne fonctionneront pas AFAIK). Je voudrais affecter (en plus du périphérique Docker Veth normal) une interface réseau physique 40 GbE de l'hôte à un conteneur Docker comme dans le mode lxc "phys". Cela devrait rendre l'interface physique invisible pour l'hôte.

NeilenMarais
la source

Réponses:

4

pipework peut déplacer une interface réseau physique de la valeur par défaut vers l'espace de noms du réseau de conteneurs:

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

Pour plus d'informations, voir ici .

Christoph Zauner
la source
1
J'ai accepté cette réponse parce qu'elle semble simple, mais je ne l'ai pas essayée moi-même (j'ai utilisé la longue réponse que j'ai écrite avant que les tuyauteries ne développent cette fonctionnalité)
NeilenMarais
7

Dans ma recherche, je suis tombé sur d'anciennes solutions qui impliquaient de passer des paramètres lxc-config à docker, mais les nouvelles versions de docker n'utilisent plus les outils lxc, donc cela ne peut pas fonctionner.

En suivant la suggestion ici: https://groups.google.com/d/msg/docker-user/pL8wlmiuAEU/QfcoFcKI3kgJ une solution a été trouvée. Je n'ai pas cherché à modifier le script de tuyauterie comme mentionné ci-dessus, à la place en utilisant directement les commandes requises. Voir également le billet de blog suivant: http://jason.digitalinertia.net/exposing-docker-containers-with-sr-iov/ .

Les commandes d'outil d'espace de noms de réseau de bas niveau (c'est-à-dire non spécifiques aux dockers) suivantes peuvent être utilisées pour transférer une interface de l'hôte vers un conteneur de docker:

CONTAINER=slave-play # Name of the docker container
HOST_DEV=ethHOST     # Name of the ethernet device on the host
GUEST_DEV=test10gb   # Target name for the same device in the container
ADDRESS_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 work
mkdir -p /var/run/netns
PID=$(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 container
ip 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 container
ip 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 stopped
rm /var/run/netns/$PID

Une mise en garde mineure sur le nom de l'interface si votre hôte a beaucoup de périphériques ethX (le mien avait eth0 -> eth5). Par exemple, disons que vous déplacez eth3 dans le conteneur en tant que eth1 dans l'espace de noms des conteneurs. Lorsque vous arrêtez le conteneur, le noyau essaiera de déplacer le périphérique eth1 du conteneur vers l'hôte, mais notez qu'il existe déjà un périphérique eth1. Il renommera alors l'interface en quelque chose d'arbitraire; m'a pris un certain temps pour le retrouver. Pour cette raison, j'ai édité /etc/udev/rules.d/70-persistent-net.rules (je pense que ce nom de fichier est commun à la plupart des distributions Linux populaires; j'utilise Debian) pour donner à l'interface en question un nom unique et unique. et utilisez-le à la fois dans le conteneur et sur l'hôte.

Étant donné que nous n'utilisons pas docker pour effectuer cette configuration, les outils de cycle de vie de docker standard (par exemple, docker run --restart = on-failure: 10 ...) ne peuvent pas être utilisés. La machine hôte en question exécute Debian Wheezy, j'ai donc écrit le script init suivant:

#!/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 INFO

CONTAINER=slave-play
SCRIPT="docker start -i $CONTAINER"
RUNAS=root

LOGFILE=/var/log/$CONTAINER.log
LOGFILE=/var/log/$CONTAINER.log

HOST_DEV=test10gb
GUEST_DEV=test10gb
ADDRESS_AND_NET=10.101.0.5/24


start() {
  if [ -f /var/run/$PIDNAME ] && kill -0 $(cat /var/run/$PIDNAME); then
echo 'Service already running' >&2
return 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)
stop
start
;;
  *)
echo "Usage: $0 {start|stop|restart}"
esac

Légèrement hacky, mais ça marche :)

NeilenMarais
la source
Pourquoi les noms de vos interfaces réseau commencent-ils eth? Debian ne fait-il pas de noms de périphériques réseau cohérents?
Michael Hampton
Pour tous ceux qui se demandent pourquoi le lien symbolique /var/run/netns/$PIDest nécessaire: vous en avez besoin pour que les ip netns exec $PID ...commandes fonctionnent.
Donn Lee
2

J'écris un plugin réseau docker pour ce faire.

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

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