Eu gostaria de executar um teste de rede de alto desempenho em um contêiner docker e não quero a sobrecarga de ponte (para que o pipeworks não funcione AFAIK). Eu gostaria de atribuir (além do dispositivo Docker veth normal) uma interface de rede 40GbE física do host para um contêiner docker como no modo "phys" lxc. Isso deve fazer com que a interface física se torne invisível para o host.
Na minha pesquisa, encontrei soluções antigas que invovled passando parâmetros lxc-config para docker, mas as versões mais recentes do docker não usam mais as ferramentas lxc, de modo que não podem funcionar.
Seguindo a sugestão aqui: https://groups.google.com/d/msg/docker-user/pL8wlmiuAEU/QfcoFcKI3kgJ uma solução foi encontrada.Eu não procurei modificar o script de pipework como mencionado acima, em vez disso, usando os comandos necessários diretamente. Veja também a postagem subsequente do blog: http://jason.digitalinertia.net/exposing-docker-containers-with-sr-iov/.
Os seguintes comandos de Ferramenta de namespace de rede de baixo nível (ou seja, não específicos do docker) podem ser usados para transferir uma interface do host para um contêiner do 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
>Uma pequena ressalva na nomenclatura da interface se o seu host tiver muitos dispositivos ethX (o meu tinha eth0 - eth5). Por exemplo, digamos que você mova eth3 para o contêiner como eth1 no namespace containers. Quando você parar o contêiner, o kernel tentará mover o dispositivo eth1 do contêiner de volta para o host, mas observe que já existe um dispositivo eth1. Ele então renomeará a interface para algo arbitrário; demorei um pouco para encontrá-la novamente. Por esse motivo, editei /etc / udev / rules.d / 70-persistente-net.regras (acho que esse nome de arquivo é comum às distros Linux mais populares; estou usando Debian) para dar à interface em questão um nome único e inconfundível e usá-lo tanto no contêiner quanto no host.
Como não estamos usando o docker para fazer essa configuração, as ferramentas padrão do ciclo de vida do docker (por exemplo, docker run --restart=on-failure:10 ...) não pode ser usado . A máquina host em questão executa Debian Wheezy, então escrevi o seguinte script init:
#!/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
Um pouco hacky, mas funciona :)
pipework
pode mover uma interface de rede física do padrão para o namespace de rede de contêiner:
$ sudo pipework --direct-phys eth1 $CONTAINERID 192.168.1.2/24
Para mais informações, consulte aqui.
Eu escrevo um plugin de rede docker para fazer isso.
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