Na minha pesquisa, me deparei com soluções antigas que invocavam 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, 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 tubagem conforme mencionado acima, em vez de usar diretamente os comandos necessários. Consulte também a postagem subsequente do blog: http://jason.digitalinertia.net/exposing-docker-containers-with-sr-iov/ .
Os seguintes comandos da ferramenta de espaço para nome de rede de baixo nível (isto é, não específico do docker) podem ser usados para transferir uma interface do host para um contêiner do 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 interface, que indica se o seu host possui muitos dispositivos ethX (o meu tinha eth0 -> eth5). Por exemplo, digamos que você mova eth3 para o contêiner como eth1 no espaço para nome dos contêineres. Quando você para o contêiner, o kernel tenta mover o dispositivo eth1 do contêiner de volta para o host, mas observe que já existe um dispositivo eth1. Ele irá renomear a interface para algo arbitrário; Levei um tempo para encontrá-lo novamente. Por esse motivo, editei o /etc/udev/rules.d/70-persistent-net.rules (acho que esse nome de arquivo é comum às 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 o docker para fazer essa configuração, as ferramentas padrão do ciclo de vida do docker (por exemplo, docker run --restart = on-fail: 10 ...) não podem ser usadas. A máquina host em questão executa o 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 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 :)