我想在 docker 容器中執行高效能網路測試,並且不希望橋接的開銷(因此 pipelineworks 無法運作)。我想(除了正常的 docker veth 設備之外)從主機到 docker 容器分配一個物理 40GbE 網路接口,就像在 lxc“phys”模式中一樣。這會導致實體介面對主機不可見。
答案1
pipework
可將實體網路介面從預設網路命名空間移至容器網路命名空間:
$ sudo pipework --direct-phys eth1 $CONTAINERID 192.168.1.2/24
欲了解更多信息,請參閱這裡。
答案2
在我的搜尋中,我遇到了涉及將 lxc-config 參數傳遞給 docker 的舊解決方案,但較新版本的 docker 不再使用 lxc 工具,因此無法運作。
按照這裡的建議:https://groups.google.com/d/msg/docker-user/pL8wlmiuAEU/QfcoFcKI3kgJ找到了解決方案。我沒有考慮修改上面提到的管道腳本,而是直接使用所需的命令。另請參閱後續部落格文章:http://jason.digitaliertia.net/exusing-docker-containers-with-sr-iov/。
以下低階(即非 docker 特定)網路命名空間工具指令可用於將介面從主機傳送到 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
如果您的主機有很多 ethX 裝置(我的主機有 eth0 -> eth5),則需要注意介面命名。例如,假設您將 eth3 作為容器名稱空間中的 eth1 移至容器中。當您停止容器時,核心將嘗試將容器的 eth1 裝置移回主機,但請注意已經有一個 eth1 裝置。然後它會將介面重命名為任意名稱;我花了一段時間才再次找到它。基於這個原因,我編輯了/etc/udev/rules.d/70-persistent-net.rules (我認為這個檔案名稱對於大多數流行的Linux 發行版來說是常見的;我使用的是Debian) ,為所討論的介面提供一個獨特的、明確無誤的名稱,並在容器和主機上使用它。
由於我們沒有使用 docker 來進行此配置,因此無法使用標準 docker 生命週期工具(例如 docker run --restart=on-failure:10 ...)。有問題的主機運行 Debian Wheezy,因此我編寫了以下初始化腳本:
#!/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
有點 hacky,但它有效:)
答案3
我編寫了一個 docker 網路外掛程式來執行此操作。
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