基礎概念
首先來回顧一下網絡的基礎概念, 網橋和網關
網橋
網橋(Bridge)是一個區域網路與另一個區域網路之間建立連接配接的橋梁. 是一種二層網絡裝置,
網關
網關實質上是一個網絡通向其他網絡的IP位址。
比如有網絡A和網絡B,網絡A的IP位址範圍為“192.168.1.1~192. 168.1.254”,子網路遮罩為255.255.255.0;網絡B的IP位址範圍為“192.168.2.1~192.168.2.254”,子網路遮罩為255.255.255.0。
在沒有路由器的情況下,兩個網絡之間是不能進行TCP/IP通信的,即使是兩個網絡連接配接在同一台交換機(或集線器)上,TCP/IP協定也會根據子網路遮罩(255.255.255.0)判定兩個網絡中的主機處在不同的網絡裡。
而要實作這兩個網絡之間的通信,則必須通過網關。如果網絡A中的主機發現資料包的目的主機不在本地網絡中,就把資料包轉發給它自己的網關,再由網關轉發給網絡B的網關,網絡B的網關再轉發給網絡B的某個主機
macvlan
macvlan 是linux核心在3.9版本以上提供較新的一種特性,
允許在同一個實體網卡上配置多個 MAC 位址,即多個 interface,每個 interface 可以配置自己的 IP。
macvlan 本質上是一種網卡虛拟化技術,Docker 用 macvlan 實作容器網絡就不奇怪了。
macvlan 的最大優點是性能極好,相比其他實作,macvlan 不需要建立 Linux bridge,而是直接通過以太 interface 連接配接到實體網絡
簡單macvlan環境配置
環境是兩台VM, 172.16.104.145/172.16.104.146
需要在兩台VM上都打開網卡混雜模式和建立docker的macvlan網絡
這種模式下的容器, 和主控端不能互通, 和其他主機以及上面的容器都可以通信
網卡混雜模式設定
[root@centos1 ~]# ip link set ens33 promisc on
[root@centos1 ~]# ifconfig
ens33: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST> mtu 1500
inet 172.16.104.145 netmask 255.255.255.0 broadcast 172.16.104.255
inet6 fe80::9abe:3a2e:cbd9:3192 prefixlen 64 scopeid 0x20<link>
ifconfig
可以看到有
PROMISC
字樣表示混雜模式打開
建立macvlan網絡
docker network create -d macvlan --subnet=172.16.104.0/24 --gateway=172.16.104.1 -o parent=ens33 mynet
參數說明: -d macvlan
: 建立macvlan網絡,使用macvlan網絡驅動
--subnet
: 指定主控端所在網段
--gateway
: 指定主控端所在網段網關, 必須是真實存在的網關,否則容器無法路由
-o parent
: 繼承指定網段的網卡
注意:
- 1、macvlan是一種本地網絡, docker不會為它建立網關,
- 2、使用者也需要自己管理 IP subnet, 而且不提供DNS服務
- 3、macvlan是一種獨占網絡, 即一個網卡隻能建立一個 macvlan 網絡, 如果要支援多個macvlan網絡, 必須使用 sub-interface , 具體方法略.
建立容器
兩台VM上分别建立容器(IP為10/11)之後
docker run --net=mynet --ip=172.16.104.10 -itd --name=test1 docker.io/centos bash
docker run --net=mynet --ip=172.16.104.11 -itd --name=test2 docker.io/centos bash
進入容器, 能互相ping通
[root@634408c6c399 /]# ping 172.16.104.10
PING 172.16.104.10 (172.16.104.10) 56(84) bytes of data.
64 bytes from 172.16.104.10: icmp_seq=1 ttl=64 time=0.595 ms
使用macVLAN模式的容器,無法ping通主控端,主控端也無法ping通該容器,對其他同網段的伺服器和容器都可以聯通
# 容器ping主控端IP
[root@634408c6c399 /]# ping 172.16.104.146
PING 172.16.104.146 (172.16.104.146) 56(84) bytes of data.
^C
--- 172.16.104.146 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2001ms
# 主機ping另外主機的容器
[root@centos2 ~]# ping 172.16.104.10
PING 172.16.104.10 (172.16.104.10) 56(84) bytes of data.
64 bytes from 172.16.104.10: icmp_seq=1 ttl=64 time=0.762 ms
# 容器内ping另外的主機
[root@634408c6c399 /]# ping 172.16.104.145
PING 172.16.104.145 (172.16.104.145) 56(84) bytes of data.
64 bytes from 172.16.104.145: icmp_seq=1 ttl=64 time=0.513 ms
pipework
pipework是一個400多行的shell程式,封裝Linux上的ip、brctl等指令, 簡化了在複雜場景下對容器連接配接的操作指令,為我們配置複雜的網絡拓撲提供了一個強有力的工具.
使用pipework指令為容器設定固定IP
格式為:
pipework <網卡> <容器> <IP/掩碼>@<網關>
方法一
這種方法直接綁定到網卡上, 和上面方法類似, 容器内ping不同主控端ip, 其他可以
docker run --net=none -itd --name=test1 -h test1 busybox /bin/sh
pipework ens33 test1 172.16.104.10/[email protected]
pipework ens33 test2 172.16.104.11/[email protected]
執行過程大概包括:
檢視主機是否包含ens33,如果不存在就建立,向容器執行個體test1添加一塊網卡,并配置固定IP:172.16.104.10,若test1已經有預設的路由,則删除掉,将@後面的172.16.104.1設定為預設路由的網關,将test1容器執行個體連接配接到建立的ens33上。
[root@centos1 network-scripts]# docker exec test1 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
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
valid_lft forever preferred_lft forever
18: eth1@if2: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue qlen 1000
link/ether f6:c5:fe:92:08:c0 brd ff:ff:ff:ff:ff:ff
inet 172.16.104.10/24 brd 172.16.104.255 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::f4c5:feff:fe92:8c0/64 scope link
valid_lft forever preferred_lft forever
容器可以ping通另外的主機了
[root@centos1 network-scripts]# docker exec test1 ping 172.16.104.147
PING 172.16.104.147 (172.16.104.147): 56 data bytes
64 bytes from 172.16.104.147: seq=0 ttl=64 time=1.343 ms
64 bytes from 172.16.104.147: seq=1 ttl=64 time=0.553 ms
方法二
該方法效果較好, 容器和主控端互通, 但是配置的時候需要通過VNC或者序列槽連接配接(單網卡), 要斷網
啟動容器, pipework綁定過程和方法一相同, 這裡省略
$ ip addr add 172.16.104.148/24 dev br0
$ ip addr del 172.16.104.148/24 dev ens33
$ brctl addif br0 ens33
$ ip route del default
$ ip route add default via 172.16.104.1 dev br0
過程中會斷網, 可以寫到一條指令中, 但實測過程中并不好用 (因為可能中間哪條抛錯下面的就執行不了, 實測中第一次執行時候第四條抛錯)
ip addr add 172.16.104.148/24 dev br0;\
ip addr del 172.16.104.148/24 dev ens33;\
brctl addif br0 ens33;\
ip route del default;\
ip route add default via 172.16.104.1 dev br0;\