Atribuir interface física ao docker exclusivamente

11

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 os pipeworks não funcionem AFAIK). Gostaria de atribuir (além do dispositivo docker veth normal) uma interface de rede física de 40 GbE do host a um contêiner docker, como no modo lxc "phys". Isso deve fazer com que a interface física fique invisível para o host.

    
por NeilenMarais 04.05.2015 / 17:33

3 respostas

4

pipework pode mover uma interface de rede física do padrão para o namespace da rede de contêineres:

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

Para mais informações, consulte aqui .

    
por 02.09.2016 / 11:03
6

Na minha pesquisa, encontrei soluções antigas que envolviam a passagem de parâmetros lxc-config para o docker, mas as versões mais recentes do docker não usam mais as ferramentas lxc, portanto isso não funciona.

Seguindo a sugestão aqui: link foi encontrada uma solução. Eu não olhei para modificar o script de tubulação como mencionado acima, em vez disso, usando os comandos necessários diretamente. Veja também a postagem subsequente do blog: link .

Os seguintes comandos da ferramenta de espaço para nome da rede de baixo nível (ou seja, não específicos) podem ser usados para transferir uma interface do host para um contêiner 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

Uma pequena ressalva na nomeação 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 de contêineres. 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; Levei um tempo para encontrá-lo novamente. Por esta razão eu editei /etc/udev/rules.d/70-persistent-net.rules (eu acho que este nome de arquivo é comum para distribuições Linux mais populares; estou usando o Debian) para dar à interface em questão um nome único e inconfundível e use isso no contêiner e no host.

Como não estamos usando a janela de encaixe para fazer essa configuração, as ferramentas do ciclo de vida do docker padrão (por exemplo, execução do docker --restart = on-failure: 10 ...) não podem ser usadas. A máquina host em questão roda o Debian Wheezy, então eu escrevi o seguinte script de inicialização:

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

Ligeiramente hacky, mas funciona:)

    
por 01.06.2015 / 12:23
2

Eu escrevo um plugin de rede docker para fazer isso.

link

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
    
por 05.12.2016 / 07:06