Tetapkan antarmuka fisik ke buruh pelabuhan secara eksklusif

12

Saya ingin menjalankan tes jaringan kinerja tinggi dalam wadah buruh pelabuhan, dan tidak ingin overhead menjembatani (sehingga pipa tidak akan bekerja AFAIK). Saya ingin menetapkan (selain perangkat docker veth normal) antarmuka jaringan fisik 40GbE dari host ke wadah buruh pelabuhan seperti dalam mode "Phys" lxc. Ini harus menyebabkan antarmuka fisik menjadi tidak terlihat oleh tuan rumah.

NeilenMarais
sumber

Jawaban:

4

pipework dapat memindahkan antarmuka jaringan fisik dari default ke namespace jaringan wadah:

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

Untuk informasi lebih lanjut lihat di sini .

Christoph Zauner
sumber
1
Saya menerima jawaban ini karena tampaknya sederhana, tetapi saya belum mencobanya sendiri (saya menggunakan jawaban panjang yang saya tulis sebelum pipeworks mengembangkan fungsi ini)
NeilenMarais
7

Dalam pencarian saya, saya menemukan solusi lama yang invovled melewati parameter lxc-config ke buruh pelabuhan, tetapi versi buruh pelabuhan yang lebih baru tidak menggunakan alat lxc lagi, sehingga tidak bisa berfungsi.

Mengikuti saran di sini: https://groups.google.com/d/msg/docker-user/pL8wlmiuAEU/QfcoFcKI3kgJ sebuah solusi ditemukan. Saya tidak melihat ke dalam memodifikasi skrip pipework seperti yang disebutkan di atas, melainkan menggunakan perintah yang diperlukan secara langsung. Juga lihat posting blog berikutnya: http://jason.digitalinertia.net/exposing-docker-containers-with-sr-iov/ .

Perintah alat namespace jaringan level rendah (yaitu tidak khusus docker) ini dapat digunakan untuk mentransfer antarmuka dari host ke wadah buruh pelabuhan:

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

Peringatan kecil pada penamaan antarmuka jika host Anda memiliki banyak perangkat ethX (milik saya memiliki eth0 -> eth5). Misalnya, Anda memindahkan eth3 ke wadah sebagai eth1 di namespace wadah. Ketika Anda menghentikan wadah, kernel akan mencoba untuk memindahkan perangkat eth1 penampung kembali ke host, tetapi perhatikan bahwa sudah ada perangkat eth1. Kemudian akan mengubah nama antarmuka menjadi sesuatu yang sewenang-wenang; Butuh beberapa saat untuk menemukannya lagi. Untuk alasan ini saya mengedit /etc/udev/rules.d/70-persistent-net.rules (saya pikir nama file ini umum untuk distro Linux yang paling populer; saya menggunakan Debian) untuk memberikan antarmuka pertanyaan yang unik, nama yang tidak salah lagi. , dan gunakan itu di wadah dan di host.

Karena kita tidak menggunakan buruh pelabuhan untuk melakukan konfigurasi ini, alat siklus hidup buruh pelabuhan standar (misalnya buruh pelabuhan --restart = on-failure: 10 ...) tidak dapat digunakan. Mesin host tersebut menjalankan Debian Wheezy, jadi saya menulis skrip init berikut:

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

Sedikit hacky, tapi berhasil :)

NeilenMarais
sumber
Mengapa nama antarmuka jaringan Anda mulai dengan eth? Bukankah Debian melakukan nama perangkat jaringan yang konsisten?
Michael Hampton
Untuk siapa pun yang bertanya-tanya mengapa symlink /var/run/netns/$PIDdiperlukan: Anda memerlukannya agar ip netns exec $PID ...perintah berfungsi.
Donn Lee
2

Saya menulis plugin jaringan buruh pelabuhan untuk melakukan ini.

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
sumber