您好,登錄后才能下訂單哦!
博文大綱:
一、前言
二、Docker的原生網絡
三、自定義bridge網絡
四、Overlay網絡
五、Macvlan網絡
六、使外網可以訪問容器的方法
由于docker技術的火爆,導致現在越來越多的企業都在使用docker這種虛擬化技術。企業中使用docker這種虛擬化技術,其目的就是為了讓docker中的容器對外提供服務。因此,我們必須深入了解一下docker的網絡知識,以滿足更高的網絡需求。
當你安裝Docker時,它會自動創建三個網絡。如下:
[root@localhost ~]# docker network ls
//查看docker的默認網絡
NETWORK ID NAME DRIVER SCOPE
a38bd52b4cec bridge bridge local
624b3ba70637 host host local
62f80646f707 none null local
Docker內置這三個網絡,運行容器時,你可以使用該“--network”選項來指定容器應連接到哪些網絡。如果沒有指定則默認使用bridge模式。
比如:
host模式:使用 --net=host 指定;
none模式:使用 --net=none 指定;
bridge模式:使用 --net=bridge 指定(默認設置);
下面詳細介紹一下這幾種網絡模式:
雖然docker模式提供三種網絡模式,但其實是有四種網絡模式的!
如果啟動容器時使用host模式,那么這個容器將不會獲得一個獨立的Network Namespace,而是和宿主機共用一個Network Namespace。容器將不會虛擬出自己的網卡,配置自己的IP等,而是使用宿主機的IP和端口。
使用場景:
由于網絡配置與docker宿主機完全一樣,性能較好,但是不便之處就是靈活性不高,容易和宿主機出現端口沖突的問題。最好是單個容器時使用,一般情況下不建議使用。
創建使用host網絡模式的容器示例:
[root@localhost ~]# docker run -it --name host --network host busybox:latest
//使用busybox鏡像創建一個名為host的容器,網絡采用host模式
/ # ip a
//進入容器后可以看出容器中的網絡與docker主機的網絡一模一樣
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
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:0c:29:66:72:13 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.1/24 brd 192.168.1.255 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::9f3:b94e:5f5d:8070/64 scope link
valid_lft forever preferred_lft forever
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue qlen 1000
link/ether 52:54:00:e1:82:15 brd ff:ff:ff:ff:ff:ff
inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
valid_lft forever preferred_lft forever
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 qlen 1000
link/ether 52:54:00:e1:82:15 brd ff:ff:ff:ff:ff:ff
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue
link/ether 02:42:3c:06:f8:1d brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
在none模式下,Docker容器擁有自己的Network Namespace,但是,并不為Docker容器進行任何網絡配置。也就是說,這個Docker容器只有一個回環地址,不能與外界通信,稱為被隔離的網絡。
使用場景:
none模式被稱為隔離的網絡,隔離便意味著安全,不能與外部通信,同樣外部也不可以訪問到使用none模式的容器,使用這種網絡模式的容器可以運行于關于安全方面的驗證碼、校驗碼等服務。一般用于對安全性要求較高的場景中!
創建使用none網絡模式的容器示例:
[root@localhost ~]# docker run -it --name none --network none busybox:latest
//使用busybox鏡像創建一個名為none的容器,網絡采用none模式
/ # ip a //可以看到容器中只有一個lo網卡
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
bridge模式是Docker默認的網絡設置,此模式會為每一個容器分配Network Namespace、設置IP等,并將一個主機上的Docker容器連接到一個虛擬網卡上。當Docker server啟動時,會在主機上創建一個名為docker0的虛擬網橋,此主機上啟動的Docker容器會連接到這個虛擬網橋上。虛擬網橋的工作方式和物理交換機類似,這樣主機上的所有容器就通過交換機連在了一個二層網絡中。接下來就要為容器分配IP了,Docker會從RFC1918所定義的私有IP網段中,選擇一個和宿主機不同的IP地址和子網分配給docker0,連接到docker0的容器就從這個子網中選擇一個未占用的IP使用。如一般Docker會使用172.17.0.0/16這個網段,并將172.17.0.1/16分配給docker0網橋。
[root@localhost ~]# ifconfig docker0
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:3c:06:f8:1d txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@localhost ~]# brctl show //查看橋接網絡
bridge name bridge id STP enabled interfaces
docker0 8000.02423c06f81d no
//如果沒有創建橋接模式的容器,默認是空的。
創建使用bridge網絡模式的容器示例:
[root@localhost ~]# docker run -itd --name bridge busybox:latest /bin/sh
//創建一個名為bridge的容器,如果沒有指定網絡模式,默認便是bridge模式
[root@localhost ~]# docker exec -it bridge /bin/sh
//進入bridge容器中
/ # ip a
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
6: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
//可以看出eth0@if9這塊虛擬網卡上的地址與docker宿主機的docker0網絡屬于同一網段
[root@localhost ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02423c06f81d no veth811d20c
//可以看到橋接模式的接口下出現了一個新的接口,當創建一個容器便會出現一個接口
//這個接口便是容器在docker宿主機創建一個虛擬網卡,用于容器與docker通信
[root@localhost ~]# ifconfig veth811d20c //查看這個虛擬網卡是否存在
veth811d20c: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::c035:95ff:febf:978b prefixlen 64 scopeid 0x20<link>
ether c2:35:95:bf:97:8b txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 8 bytes 648 (648.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
當使用bridge網絡模式,docker的工作步驟大致為:
(1)在主機上創建一對虛擬網卡veth pair設備。veth設備總是成對出現的,它們組成了一個數據的通道,數據從一個設備進入,就會從另一個設備出來。因此,veth設備常用來連接兩個網絡設備;
(2)Docker將veth pair設備的一端放在新創建的容器中,并命名為eth0。另一端放在主機中,以veth811d20c這樣類似的名字命名,并將這個網絡設備加入到docker0網橋中,可以通過brctl show命令查看(上述實例已經驗證);
(3)從docker0子網中分配一個IP給容器使用,并設置docker0的IP地址為容器的默認網關;
這個模式指定新創建的容器和已經存在的一個容器共享一個Network Namespace,而不是和宿主機共享。新創建的容器不會創建自己的網卡,配置自己的IP,而是和一個指定的容器共享IP、端口范圍等。同樣,兩個容器除了網絡方面,其他的如文件系統、進程列表等還是隔離的。兩個容器的進程可以通過lo網卡設備通信。
創建使用container網絡模式的容器示例:
[root@localhost ~]# docker run -it --name container --network container:a172b832b531 busybox:latest
//a172b832b531是bridge容器的ID號
/ # ip a
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
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
//可以看出container容器的IP地址與bridge容器的IP地址一模一樣
關于這四種網絡模式推薦使用默認的bridge網絡模式!
細心一點可以發現,創建的容器默認情況IP地址為172.17.0.0/16網段,那么我們可不可以自定義一個網段供容器使用呢?答案肯定是可以的,方法如下:
[root@localhost ~]# docker network create -d bridge my_net
//創建一個橋接網絡,名稱為my_net,如果沒有指定網段,默認是172.18.0.0/16,按docker0的網段自動遞增
[root@localhost ~]# docker network ls //查看docker支持的網絡類型
NETWORK ID NAME DRIVER SCOPE
9fba9dc3d2b6 bridge bridge local
624b3ba70637 host host local
74544573aa67 my_net bridge local
62f80646f707 none null local
//可以看出,剛才創建的my_net已經出現在列表中
[root@localhost ~]# docker run -itd --name test1 --network my_net busybox:latest /bin/sh
[root@localhost ~]# docker run -itd --name test2 --network my_net busybox:latest /bin/sh
//使用剛才創建的網絡模式創建兩個容器
[root@localhost ~]# docker exec -it test1 /bin/sh
//進入test1
/ # ip a
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
11: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
valid_lft forever preferred_lft forever
//查看其IP地址,發現確實是172.18.0.0/16網段的
/ # ping test2 //測試通過容器名稱ping test2容器
PING test2 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.079 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.175 ms
[root@localhost ~]# ifconfig br-74544573aa67
//這張虛擬網卡就是我們創建my_net網絡時產生的
br-74544573aa67: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.18.0.1 netmask 255.255.0.0 broadcast 172.18.255.255
inet6 fe80::42:50ff:fec2:7657 prefixlen 64 scopeid 0x20<link>
ether 02:42:50:c2:76:57 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
//通過IP地址網段就可看出
自定義網絡的優點:
- 可以通過容器的名稱進行通信;
- 自定了ContainerDNSserver功能;
以上方法按照默認的方式創建一個橋接模式的網絡,可以發現網段地址并不是我們自定義的。
接下來我們通過指定具體網段的方式創建網卡。方法如下:
[root@localhost ~]# docker network create -d bridge --subnet 200.0.0.0/24 --gateway 200.0.0.1 my_net2
//自定義網絡模式的地址時,必須要明確指定其IP網段及網關信息
[root@localhost ~]# ifconfig br-0ca6770b4a10
//這張虛擬網卡便是我們創建my_net2網絡時產生的
br-0ca6770b4a10: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 200.0.0.1 netmask 255.255.255.0 broadcast 200.0.0.255
ether 02:42:05:ba:8b:fc txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
//可以看出其IP地址就是我們指定的IP地址
[root@localhost ~]# docker run -itd --name test3 --network my_net2 --ip 200.0.0.100 busybox:latest
[root@localhost ~]# docker run -itd --name test4 --network my_net2 --ip 200.0.0.200 busybox:latest
//基于剛才創建的網絡創建出兩個容器并指定其固定的IP地址
[root@localhost ~]# docker exec -it test3 /bin/sh
//進入test3容器
/ # ip a
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
16: eth0@if17: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:c8:00:00:64 brd ff:ff:ff:ff:ff:ff
inet 200.0.0.100/24 brd 200.0.0.255 scope global eth0
valid_lft forever preferred_lft forever
//發現其IP地址確實我們剛才指定的IP地址
/ # ping test4 //測試發現確實是可以和test4通信的
PING test4 (200.0.0.200): 56 data bytes
64 bytes from 200.0.0.200: seq=0 ttl=64 time=0.156 ms
64 bytes from 200.0.0.200: seq=1 ttl=64 time=0.178 ms
/ # ping test1
ping: bad address 'test1'
//發現無法與第一次創建的網絡進行通信
使用相同的網絡創建的容器是可以相互通信的,但是發現無法與其他容器進行通信,這主要是因為iptables規則的原因,創建docker網絡時,iptables規則就會隨著自動添加的。
舉例說:嘗試把iptables規則清空,是可以實現我們想要的效果的。但是這種命令的作用不亞于“rm -rf /*”,顯然在現實環境中是不可以使用的!
那么就需要使用下面的方法來實現了,方法如下:
[root@localhost ~]# docker network connect my_net2 test1
//這條命令就是在test1容器中添加一塊虛擬網卡(my_net2分配的)
[root@localhost ~]# docker exec -it test1 /bin/sh
/ # ip a
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
11: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
valid_lft forever preferred_lft forever
20: eth2@if21: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:c8:00:00:02 brd ff:ff:ff:ff:ff:ff
inet 200.0.0.2/24 brd 200.0.0.255 scope global eth2
valid_lft forever preferred_lft forever
//可以查詢到確實多了一塊虛擬網卡,網段確實和my_net2屬于同一網段
/ # ping test3
PING test3 (200.0.0.100): 56 data bytes
64 bytes from 200.0.0.100: seq=0 ttl=64 time=0.171 ms
64 bytes from 200.0.0.100: seq=1 ttl=64 time=0.237 ms
^C
--- test3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.171/0.204/0.237 ms
/ # ping test4
PING test4 (200.0.0.200): 56 data bytes
64 bytes from 200.0.0.200: seq=0 ttl=64 time=0.097 ms
^C
--- test4 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.097/0.097/0.097 ms
//測試與test3、test4通信,通信正常
注意:此時test2容器并不可以與test3、test4進行通信!如果需要其通信,還需給test2添加虛擬my_net2網卡地址(使用案例中的命令即可)!
注意:
- 容器之間可以使用容器名進行通信,但前提必須是使用自定義網絡,比如案例中創建的my_net、my_net2;
- 如果在創建自定義網絡時,指定了該網絡的網段,那么使用此時的容器也可以指定容器的IP地址,若沒有指定該網絡的網段,則不可指定容器的IP地址;
使用overlay網絡需事先部署好consul服務!
consul:是一個服務網格(微服務間的 TCP/IP,負責服務之間的網絡調用、限流、熔斷和監控)解決方案,它是一個一個分布式的,高度可用的系統,而且開發使用都很簡便。它提供了一個功能齊全的控制平面,主要特點是:服務發現、健康檢查、鍵值存儲、安全服務通信、多數據中心。
通過一個小案例來驗證consul服務的特性!
(1)關閉防火墻與SELinux(實驗環境);
(2)更改主機名,避免發生沖突;
(1)Docker1
[root@Docker1 ~]# docker pull progrium/consul
//下載consul鏡像
[root@Docker1 ~]# docker run -d -p 8500:8500 -h consul --name consul --restart=always progrium/consul -server -bootstrap
//-d:后臺運行;
//-p:將容器中的8500端口映射到宿主機的8500端口;
//-h:表示consul容器的主機名;
//--name:表示運行的容器名;
//--restart=always:隨docker服務的啟動而啟動;
//-server -bootstrap:添加這兩個選項,則表示在群集環境中可以使其以master的身份出現;
[root@Docker1 ~]# netstat -anpt | grep 8500
tcp6 0 0 :::8500 :::* LISTEN 2442/docker-proxy
//確定其8500端口正在監聽
(2)Docker2
[root@Docker2 ~]# vim /usr/lib/systemd/system/docker.service
//編寫Docker的主配置文件
13 ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376 --cluster-store=consul://192.168.1.1:8500 --cluster-advertise=ens33:2376
//在第13行上原本的基礎添加以上內容,各個配置項含義如下:
# /var/run/docker.sock:Docker的一個套接字;
# “ -H tcp://0.0.0.0:2376 ” :使用本機的tcp2376端口;
# “ --cluster-store=consul://192.168.1.1:8500”:指定運行著consul服務的docker服務器IP及端口;
# “ --cluster-advertise=ens33:2376”:從本機的ens33網卡通過2376端口搜集網絡信息,存儲在consul上
[root@Docker2 ~]# systemctl daemon-reload
[root@Docker2 ~]# systemctl restart docker //重新啟動docker服務
(3)Docker3
Docker3與Docker2的操作就是一模一樣的,所以這里就不多做解釋了!
[root@Docker3 ~]# vim /usr/lib/systemd/system/docker.service
13 ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376 --cluster-store=consul://192.168.1.1:8500 --cluster-advertise=ens33:2376
[root@Docker3 ~]# systemctl daemon-reload
[root@Docker3 ~]# systemctl restart docker
(4)使用瀏覽器訪問consul服務的web頁面
如圖:
(5)將Docker1服務器也加入到consul群集
[root@Docker1 ~]# vim /usr/lib/systemd/system/docker.service
13 ExecStart=/usr/bin/dockerd -H unix:////var/run/docker.sock -H tcp://0.0.0.0:2376 --cluster-store=consul://192.168.1.1:8500 --cluster-advertise=ens33:2376
[root@Docker1 ~]# systemctl daemon-reload
[root@Docker1 ~]# systemctl restart docker
//解釋上面都已經解釋的很清楚,這里就不做解釋了
再次訪問consul的web頁面,如圖:
如果在此過程中,訪問web頁面如果出現“500”的錯誤頁面,將運行consul服務的容器刪除重新創新即可!
(6)創建一個 overlay網絡
[root@Docker1 ~]# docker network create -d overlay my_olay
//創建一個名為my_olay的voerlay網絡
//以上操作不管在那臺docker主機上操作都可以
[root@Docker1 ~]# docker network create -d overlay --subnet 200.0.0.0/24 --gateway 200.0.0.1 lv_olay
//也可以在創建overlay網卡時,指定其IP網段及網關
[root@Docker1 ~]# docker network ls //查看docker所支持的網絡
而且在另外兩臺docker服務器上也可看到,自行驗證!
在docker 1上創建的網絡,可以看到其SPOCE(范圍)定義的是global(全局),那么這就意味著加入consul這個服務群集的其他docker服務器也可以看到這張網卡!
如果在創建網卡時,沒有指定其網段,則默認是10.0.0.0網段,由于是自定義網絡,所以滿足自定義網絡的特征(比如支持容器之間的通信)!
(7)在不同的docker服務器各自創建一個容器,驗證是否可以通信!
[root@Docker1 ~]# docker run -itd --name t1 --network lv_olay --ip 200.0.0.10 busybox:latest
//在docker1服務器上創建一個名為t1的容器并指定其IP地址
[root@Docker2 ~]# docker run -itd --name t2 --network lv_olay --ip 200.0.0.20 busybox:latest
//在docker2上創建一個容器并指定IP地址
[root@Docker3 ~]# docker run -itd --name t3 --network lv_olay --ip 200.0.0.30 busybox:latest
//在docker3上創建一個容器并指定IP地址
[root@Docker1 ~]# docker exec -it t1 /bin/sh
//隨便在一臺docker服務器上進入其創建的容器中,進行測試
如圖:
Macvlan是linux kernel比較新的特性,可以通過以下方法判斷當前系統是否支持:
[root@localhost ~]# modprobe macvlan
[root@localhost ~]# lsmod | grep macvlan
macvlan 19239 0
如果是第一個命令報錯,或者第二個命令沒有返回信息,則說明當前系統不支持macvlan,需要升級內核。
[root@docker01 ~]# modprobe 8021q //加載內核模塊
[root@docker01 ~]# modinfo 8021q //如果有信息返回則表示開啟8021q模塊,如果沒有使用上條命令
這兩組命令所支持的效果一樣!
以上命令主要驗證Linux內核是否支持macvlan功能!
macvlan允許在主機的一個網絡接口上配置多個虛擬的網絡接口,這些網絡接口有自己獨立的mac地址,也可以配置IP地址進行通信。macvlan下的虛擬機或者容器網絡和主機在同一網段中,共享一個廣播域。macvlan和bridge比較相似,但因為它省去了bridge的存在,所以在配置和調試時比較簡單,而且效率較高。除此之外,macvlan自身也完美支持VLAN。
如果希望容器或者虛擬機放在主機相同的網絡中,享受已經存在網絡棧的各種優勢,可以考慮macvlan。
macvlan和overlay網絡不同,overlay的作用范圍是global;而macvlan的作用范圍是local。global類型的網絡其作用于一組docker daemon集群,local類型的網絡只作用于單一主機。
每臺主機創建的macvlan網絡是獨立的,A機器行創建的macvlan網絡并不影響B機器上的網絡。
兩臺主機在網卡配置混雜模式、兩臺主機上macvlan存在overlap、兩個macvlan網絡沒有分配過同樣的IP,以上三個條件滿足后,同樣可以實現跨主機通信!
如圖:
(1)關閉Linux防火墻和SELinux;
(2)修改主機名;
關于macvlan單網絡通信這里就不介紹了,直接介紹macvlan多網絡通信!方法如下:
(1)開啟網卡混雜模式
[root@dockerA ~]# ip link set ens33 promisc on //開啟網卡的混雜模式
[root@dockerA ~]# ip link show ens33 //查詢網卡已經支持PROMISC
2: ens33: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:66:72:13 brd ff:ff:ff:ff:ff:ff
[root@dockerA ~]# modprobe 8021q /加載8021q內核模塊
[root@dockerA ~]# modinfo 8021q //有返回信息則表示支持8021q內核模塊
(2)創建虛擬網卡
由于一個網卡最好創建出一個macvlan網卡,所以需創建虛擬網卡以滿足要求!
[root@dockerA ~]# cd /etc/sysconfig/network-scripts/
[root@dockerA network-scripts]# sed -i 's/static/manual/g' ifcfg-ens33
[root@dockerA network-scripts]# cp -p ifcfg-ens33 ifcfg-ens33.10
[root@dockerA network-scripts]# cp -p ifcfg-ens33 ifcfg-ens33.20
[root@dockerA network-scripts]# vim ifcfg-ens33.10
BOOTPROTO=none
NAME=ens33.10
DEVICE=ens33.10
ONBOOT=yes
IPADDR=192.168.10.1
NETMASK=255.255.255.0
GATEWAY=192.168.10.254
VLAN=yes
//保證和原本的物理網卡不在同一網段,并且打開vlan的支持模式
[root@dockerA network-scripts]# vim ifcfg-ens33.20
BOOTPROTO=none
NAME=ens33.20
DEVICE=ens33.20
ONBOOT=yes
IPADDR=192.168.20.1
NETMASK=255.255.255.0
GATEWAY=192.168.20.254
VLAN=yes
[root@dockerA network-scripts]# ifup ifcfg-ens33.10
[root@dockerA network-scripts]# ifup ifcfg-ens33.20
[root@dockerA network-scripts]# ifconfig ens33.10
ens33.10: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.10.1 netmask 255.255.255.0 broadcast 192.168.10.255
inet6 fe80::20c:29ff:fe66:7213 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:66:72:13 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 29 bytes 4052 (3.9 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@dockerA network-scripts]# ifconfig ens33.20
ens33.20: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.20.1 netmask 255.255.255.0 broadcast 192.168.20.255
inet6 fe80::20c:29ff:fe66:7213 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:66:72:13 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 28 bytes 3987 (3.8 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
//確保虛擬網卡已經生效
dockerB主機上的操作與dockerA主機上的操作一致(注意IP不一樣)!要保證兩臺docker主機的虛擬網卡可以通信!
[root@dockerB network-scripts]# ifconfig ens33.10
ens33.10: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.10.2 netmask 255.255.255.0 broadcast 192.168.10.255
inet6 fe80::20c:29ff:feb7:1bbd prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:b7:1b:bd txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 29 bytes 4100 (4.0 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@dockerB network-scripts]# ifconfig ens33.20
ens33.20: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.20.2 netmask 255.255.255.0 broadcast 192.168.20.255
inet6 fe80::20c:29ff:feb7:1bbd prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:b7:1b:bd txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 29 bytes 4100 (4.0 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
(3)創建macvlan網卡
[root@dockerA ~]# docker network create -d macvlan --subnet 172.16.10.0/24 --gateway 172.16.10.1 -o parent=ens33.10 mac_net10
[root@dockerA ~]# docker network create -d macvlan --subnet 172.16.20.0/24 --gateway 172.16.20.1 -o parent=ens33.20 mac_net20
//創建虛擬網卡并針對其網段、網關
//-d:指令網卡驅動類型,-o parent:綁定在那張網卡上
[root@dockerA ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
0a74599fef51 bridge bridge local
624b3ba70637 host host local
cb81dde7685d mac_net10 macvlan local
983927dbcae8 mac_net20 macvlan local
62f80646f707 none null local
dockerB主機上的創建虛擬網卡時,命令一模一樣,指定的網段、名稱必須一樣,因為要保證其通過虛擬網卡可以通信!
[root@dockerB ~]# docker network create -d macvlan --subnet 172.16.10.0/24 --gateway 172.16.10.1 -o parent=ens33.10 mac_net10
[root@dockerB ~]# docker network create -d macvlan --subnet 172.16.20.0/24 --gateway 172.16.20.1 -o parent=ens33.20 mac_net20
(4)基于創建的macvlan網卡創建容器,驗證是否可以通信!
dockerA主機創建容器:
[root@dockerA ~]# docker run -itd --name box10 --network mac_net10 --ip 172.16.10.10 busybox
[root@dockerA ~]# docker run -itd --name box20 --network mac_net20 --ip 172.16.20.10 busybox
dockerB主機創建容器:
[root@dockerB ~]# docker run -itd --name box11 --network mac_net10 --ip 172.16.10.20 busybox
[root@dockerB ~]# docker run -itd --name box21 --network mac_net20 --ip 172.16.20.20 busybox
進入容器進行驗證:
[root@dockerA ~]# docker exec -it box10 /bin/sh
/ # ping 172.16.10.20
PING 172.16.10.20 (172.16.10.20): 56 data bytes
64 bytes from 172.16.10.20: seq=0 ttl=64 time=0.653 ms
64 bytes from 172.16.10.20: seq=1 ttl=64 time=0.966 ms
[root@dockerA ~]# docker exec -it box20 /bin/sh/ # ping 172.16.20.20
PING 172.16.20.20 (172.16.20.20): 56 data bytes
64 bytes from 172.16.20.20: seq=0 ttl=64 time=0.734 ms
64 bytes from 172.16.20.20: seq=1 ttl=64 time=0.718 ms
注意:實驗環境驗證時,應使用虛擬機橋接模式;并且,測試時,只能ping通另一條docker host容器的ip,因為創建的虛擬macvlan的范圍是local!
(1)手動指定映射端口
[root@localhost ~]# docker run -itd --name web1 -p 90:80 nginx
//將一個容器的nginx服務映射到宿主機的90端口
(2)隨機映射端口
[root@localhost ~]# docker run -itd --name web2 -p 80 nginx
//如果-p之后只有一個端口,則是容器中的端口(宿主機會隨機映射一個端口)從32768端口開始
(3)將容器中的端口全部映射到宿主機上
[root@localhost ~]# docker run -itd --name web4 -P nginx
//注意:大寫的P
//從宿主機隨機映射端口到容器,容器內所有暴露的端口,都會一一映射
以上操作,個人驗證沒有問題,這里就不截圖示范了!
—————————本文到此結束,感謝觀看—————————
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。