在使用Docker的過程中,有時候我們會有将Docker容器配置到和主機同一網段的需求。要實作這個需求,我們隻要将Docker容器和主機的網卡橋接起來,再給Docker容器配上IP就可以了。pipework工具來實作這一需求
1.安裝pipework
2.主控端配置橋接網絡(可以省略)
3.給容器添加橋接位址
實驗環境:
主控端:10.207.0.99/24 網關:10.207.0.0.1
容器test:10.207.0.236/24
[root@localhost ~] cp pipework/pipework /usr/local/bin/
主控端實體網卡em1配置:
[root@localhost ~]# cat /etc/sysconfig/network-scripts/ifcfg-em1
TYPE=Ethernet
BOOTPROTO=none
DEVICE=em1
ONBOOT=yes
BRIDGE=br0
主控端橋接網卡br0配置:
[root@localhost ~]# cat /etc/sysconfig/network-scripts/ifcfg-br0
TYPE=Bridge
DEVICE=br0
IPADDR=10.207.0.99
NETMASK=255.255.255.0
GATEWAY=10.207.0.1
3.1 首先建立一個容器
[root@localhost ~] docker run -itd --name test ubuntu /bin/bash
此時,檢視容器的IP位址資訊,其中隻有一個eth0,IP位址是172.17.0.2 是Docker預設配置設定的位址,如下:
root@c64b5871157f:/# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
10: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 scope global eth0
inet6 fe80::42:acff:fe11:2/64 scope link
3.2 在主控端配置容器test的網絡,并連接配接到網橋br0上,其中@後面是網關位址
[root@localhost ~] pipework br0 test 10.207.0.236/[email protected]
注意:這一步中,pipework首先會檢查主機是否存在br0網橋,若不存在,就自己建立一個。這裡以"br"開頭,是以建立的是Linux bridge。如果以"ovs"開頭,就會建立OpenVswitch網橋。
另外,如果主機環境中有DHCP服務,也可以通過DHCP的方式擷取IP
[root@localhost ~] pipework br0 test dhcp
此時檢視容器的IP位址資訊,發現新增加了一個網卡eth1,配置設定的IP位址是10.207.0.236/24,如下:
12: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether e2:e3:56:c0:9d:ca brd ff:ff:ff:ff:ff:ff
inet 10.207.0.236/24 brd 10.207.0.255 scope global eth1
inet6 fe80::e0e3:56ff:fec0:9dca/64 scope link
現在,可以通過ping 10.207.0.236來測試容器網絡。或者從其它實體主機上ping這個容器位址。
擴充部分:
pipework工作原理分析
#建立br0網橋
#若ovs開頭,則建立OVS網橋 ovs-vsctl add-br ovs*
brctl addbr $IFNAME
#建立veth pair,用于連接配接容器和br0
ip link add name $LOCAL_IFNAME mtu $MTU type veth peer name $GUEST_IFNAME mtu $MTU
#找到Docker容器test1在主機上的PID,建立容器網絡命名空間的軟連接配接
DOCKERPID=$(docker inspect --format='` `.`State`.`Pid `' $GUESTNAME)
ln -s /proc/$NSPID/ns/net /var/run/netns/$NSPID
#将veth pair一端放入Docker容器中,并設定正确的名字eth1
ip link set $GUEST_IFNAME netns $NSPID
ip netns exec $NSPID ip link set $GUEST_IFNAME name $CONTAINER_IFNAME
#将veth pair另一端加入網橋
#若為OVS網橋則為 ovs-vsctl add-port $IFNAME $LOCAL_IFNAME ${VLAN:+"tag=$VLAN"}
brctl addif $IFNAME $LOCAL_IFNAME
#為新增加的容器配置IP和路由
ip netns exec $NSPID ip addr add $IPADDR dev $CONTAINER_IFNAME
ip netns exec $NSPID ip link set $CONTAINER_IFNAME up
ip netns exec $NSPID ip route delete default
ip netns exec $NSPID ip route add $GATEWAY/32 dev $CONTAINER_IFNAME
1.首先pipework檢查是否存在br0網橋,若不存在,就自己建立。若以"ovs"開頭,就會建立OpenVswitch網橋,以"br"開頭,建立Linux bridge。
2.建立veth pair裝置,用于為容器提供網卡并連接配接到br0網橋。
3.使用docker inspect找到容器在主機中的PID,然後通過PID将容器的網絡命名空間連結到/var/run/netns/目錄下。這麼做的目的是,友善在主機上使用ip netns指令配置容器的網絡。因為,在Docker容器中,我們沒有權限配置網絡環境。
4.将之前建立的veth pair裝置分别加入容器和網橋中。在容器中的名稱預設為eth1,可以通過pipework的-i參數修改該名稱。
5.然後就是配置新網卡的IP。若在IP位址的後面加上網關位址,那麼pipework會重新配置預設路由。這樣容器通往外網的流量會經由新配置的eth1出去,而不是通過eth0和docker0。(若想完全抛棄自帶的網絡設定,在啟動容器的時候可以指定--net=none)
以上就是pipework配置Docker網絡的過程,這和Docker的bridge模式有着相似的步驟。事實上,Docker在實作上也采用了相同的底層機制。
通過源代碼,可以看出,pipework通過封裝Linux上的ip、brctl等指令,簡化了在複雜場景下對容器連接配接的操作指令,為我們配置複雜的網絡拓撲提供了一個強有力的工具。當然,如果想了解底層的操作,我們也可以直接使用這些Linux指令來完成工作,甚至可以根據自己的需求,添加額外的功能。
本文轉自 sjfbjs 51CTO部落格,原文連結:http://blog.51cto.com/11886896/1981901