Weisen Sie dem Docker ausschließlich eine physische Schnittstelle zu

12

Ich möchte einen Hochleistungstest in einem Docker-Container durchführen und möchte nicht den Overhead der Überbrückung (damit die Rohrleitungen AFAIK nicht funktionieren). Ich möchte (zusätzlich zum normalen Docker-Veth-Gerät) eine physische 40-GbE-Netzwerkschnittstelle vom Host zu einem Docker-Container wie im lxc-Modus "phys" zuweisen. Dies sollte dazu führen, dass die physische Schnittstelle für den Host unsichtbar wird.

NeilenMarais
quelle

Antworten:

4

pipework kann eine physische Netzwerkschnittstelle vom Standard in den Containernetzwerk-Namespace verschieben:

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

Weitere Informationen finden Sie hier .

Christoph Zauner
quelle
1
Ich habe diese Antwort akzeptiert, weil sie einfach zu sein scheint, aber ich habe sie nicht selbst ausprobiert (ich habe die lange Antwort verwendet, die ich geschrieben habe, bevor
Pipeworks
7

Bei meiner Suche bin ich auf alte Lösungen gestoßen, bei denen lxc-config-Parameter an Docker übergeben wurden. Neuere Versionen von Docker verwenden die lxc-Tools jedoch nicht mehr, sodass dies nicht funktioniert.

Dem Vorschlag hier folgend: https://groups.google.com/d/msg/docker-user/pL8wlmiuAEU/QfcoFcKI3kgJ wurde eine Lösung gefunden. Ich habe nicht versucht, das Pipework-Skript wie oben erwähnt zu ändern, sondern die erforderlichen Befehle direkt zu verwenden. Siehe auch den folgenden Blog-Beitrag: http://jason.digitalinertia.net/exposing-docker-containers-with-sr-iov/ .

Die folgenden Befehle des Netzwerk-Namespace-Tools auf niedriger Ebene (dh nicht Docker-spezifisch) können verwendet werden, um eine Schnittstelle vom Host in einen Docker-Container zu übertragen:

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

Eine kleine Einschränkung bei der Benennung der Benutzeroberfläche, wenn Ihr Host viele ethX-Geräte hat (meins hatte eth0 -> eth5). Angenommen, Sie verschieben eth3 als eth1 im Containernamensraum in den Container. Wenn Sie den Container stoppen, versucht der Kernel, das eth1-Gerät des Containers zurück auf den Host zu verschieben. Beachten Sie jedoch, dass bereits ein eth1-Gerät vorhanden ist. Anschließend wird die Schnittstelle in etwas Beliebiges umbenannt. Ich habe eine Weile gebraucht, um es wieder zu finden. Aus diesem Grund habe ich /etc/udev/rules.d/70-persistent-net.rules bearbeitet (ich denke, dieser Dateiname ist in den meisten gängigen Linux-Distributionen üblich; ich verwende Debian), um der fraglichen Schnittstelle einen eindeutigen, unverwechselbaren Namen zu geben und verwenden Sie dies sowohl im Container als auch auf dem Host.

Da wir für diese Konfiguration kein Docker verwenden, können die Standard-Docker-Lebenszyklus-Tools (z. B. Docker-Ausführung --restart = on-fail: 10 ...) nicht verwendet werden. Auf dem fraglichen Host-Computer wird Debian Wheezy ausgeführt, daher habe ich das folgende Init-Skript geschrieben:

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

Etwas hackig, aber es funktioniert :)

NeilenMarais
quelle
Warum beginnen Ihre Netzwerkschnittstellennamen mit eth? Macht Debian nicht konsistente Netzwerkgerätenamen?
Michael Hampton
Für alle anderen, die sich gefragt haben, warum Symlink /var/run/netns/$PIDbenötigt wird: Sie benötigen es, damit die ip netns exec $PID ...Befehle funktionieren.
Donn Lee
2

Ich schreibe dazu ein Docker-Netzwerk-Plugin.

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
quelle