本文首發於個人公衆號 Linux雲計算網絡(id: cloud_dev),專一於乾貨分享,號內有 10T 書籍和視頻資源,後臺回覆 「1024」便可領取,歡迎你們關注,二維碼文末能夠掃。
上一篇文章咱們詳細介紹了 macvlan 這種技術,macvlan 詳解,因爲它高效易配置的特性,被用在了 Docker 的網絡方案設計中,這篇文章就來講說這個。html
在 Docker 中,macvlan 是衆多 Docker 網絡模型中的一種,而且是一種跨主機的網絡模型,做爲一種驅動(driver)啓用(-d 參數指定),Docker macvlan 只支持 bridge 模式。linux
下面咱們作兩個實驗,分別驗證相同 macvlan 網絡和不一樣 macvlan 網絡的連通性。docker
首先準備兩個主機節點的 Docker 環境,搭建以下拓撲圖示:編程
1 首先使用 docker network create
分別在兩臺主機上建立兩個 macvlan 網絡:ubuntu
root@ubuntu:~# docker network create -d macvlan --subnet=172.16.10.0/24 --gateway=172.16.10.1 -o parent=enp0s8 mac1
這條命令中,安全
-d
指定 Docker 網絡 driver--subnet
指定 macvlan 網絡所在的網絡--gateway
指定網關-o parent
指定用來分配 macvlan 網絡的物理網卡以後能夠看到當前主機的網絡環境,其中出現了 macvlan 網絡:網絡
root@ubuntu:~# docker network ls NETWORK ID NAME DRIVER SCOPE 128956db798a bridge bridge local 19fb1af129e6 host host local 2509b3717813 mac1 macvlan local d5b0798e725e none null local
2 在 host1 運行容器 c1,並指定使用 macvlan 網絡:工具
root@ubuntu:~# docker run -itd --name c1 --ip=172.16.10.2 --network mac1 busybox
這條命令中,post
--ip
指定容器 c1 使用的 IP,這樣作的目的是防止自動分配,形成 IP 衝突--network
指定 macvlan 網絡一樣在 host2 中運行容器 c2:雲計算
root@ubuntu:~# docker run -itd --name c2 --ip=172.16.10.3 --network mac1 busybox
3 在 host1 c1 中 ping host2 c2:
root@ubuntu:~# docker exec c1 ping -c 2 172.16.10.3 PING 172.16.10.3 (172.16.10.3): 56 data bytes 64 bytes from 172.16.10.3: seq=0 ttl=64 time=0.641 ms 64 bytes from 172.16.10.3: seq=1 ttl=64 time=0.393 ms --- 172.16.10.3 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.393/0.517/0.641 ms
注意:以上的實驗都須要物理網卡 enp0s8 開啓混雜模式,否則會 ping 不通。
接下來,咱們來看看不一樣 macvlan 網絡之間的連通性,搭建如下的拓撲環境:
因爲 macvlan 網絡會獨佔物理網卡,也就是說一張物理網卡只能建立一個 macvlan 網絡,若是咱們想建立多個 macvlan 網絡就得用多張網卡,但主機的物理網卡是有限的,怎麼辦呢?
好在 macvlan 網絡也是支持 VLAN 子接口的,因此,咱們能夠經過 VLAN 技術將一個網口劃分出多個子網口,這樣就能夠基於子網口來建立 macvlan 網絡了,下面是具體的建立過程。
1 首先分別在兩臺主機上將物理網口 enp0s8 建立出兩個 VLAN 子接口。
# 使用 vconfig 命令在 eth0 配置兩個 VLAN root@ubuntu:~# vconfig add enp0s8 100 root@ubuntu:~# vconfig add enp0s8 200 # 設置 VLAN 的 REORDER_HDR 參數,默認就好了 root@ubuntu:~# vconfig set_flag enp0s8.100 1 1 root@ubuntu:~# vconfig set_flag enp0s8.200 1 1 # 啓用接口 root@ubuntu:~# ifconfig enp0s8.100 up root@ubuntu:~# ifconfig enp0s8.200 up
2 分別在 host1 和 host2 上基於兩個 VLAN 子接口建立 2 個 macvlan 網絡,mac10 和 mac20。
root@ubuntu:~# docker network create -d macvlan --subnet=172.16.10.0/24 --gateway=172.16.10.1 -o parent=enp0s8.100 mac10 root@ubuntu:~# docker network create -d macvlan --subnet=172.16.20.0/24 --gateway=172.16.20.1 -o parent=enp0s8.200 mac20
3 分別在 host1 和 host2 上運行容器,並指定不一樣的 macvlan 網絡。
# host1 root@ubuntu:~# docker run -itd --name d1 --ip=172.16.10.10 --network mac10 busybox root@ubuntu:~# docker run -itd --name d2 --ip=172.16.20.10 --network mac20 busybox # host2 root@ubuntu:~# docker run -itd --name d3 --ip=172.16.10.11 --network mac10 busybox root@ubuntu:~# docker run -itd --name d4 --ip=172.16.20.11 --network mac20 busybox
經過驗證,d1 和 d3,d2 和 d4 在同一 macvlan 網絡下,互相能夠 ping 通,d1 和 d2,d1 和 d4 在不一樣的 macvlan 網絡下,互相 ping 不通。
這個緣由也很明確,不一樣 macvlan 網絡處於不一樣的網絡,並且經過 VLAN 隔離,天然 ping 不了。
但這也只是在二層上通不了,經過三層的路由是能夠通的,咱們這就來驗證下。
從新找一臺主機 host3,經過打開 ip_forward
把它改形成一臺路由器(至於爲何能夠這樣,能夠參考我以前的一篇文章),用來打通兩個 macvlan 網絡,大概的圖示以下所示:
1 首先對 host3 執行 sysctl -w net.ipv4.ip_forward=1
打開路由開關。
2 而後建立兩個 VLAN 子接口,一個做爲 macvlan 網絡 mac10 的網關,一個做爲 mac20 的網關。
[root@localhost ~]# vconfig add enp0s8 100 [root@localhost ~]# vconfig add enp0s8 200 [root@localhost ~]# vconfig set_flag enp0s8.100 1 1 [root@localhost ~]# vconfig set_flag enp0s8.200 1 1 # 對 vlan 子接口配置網關 IP 並啓用 [root@localhost ~]# ifconfig enp0s8.100 172.16.10.1 netmask 255.255.255.0 up [root@localhost ~]# ifconfig enp0s8.200 172.16.20.1 netmask 255.255.255.0 up
3 這樣以後再從 d1 ping d2 和 d4,就能夠 ping 通了。
root@ubuntu:~# docker exec d1 ping -c 2 172.16.20.10 PING 172.16.20.10 (172.16.20.10): 56 data bytes 64 bytes from 172.16.20.10: seq=0 ttl=63 time=0.661 ms 64 bytes from 172.16.20.10: seq=1 ttl=63 time=0.717 ms --- 172.16.20.10 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.661/0.689/0.717 ms
root@ubuntu:~# docker exec d1 ping -c 2 172.16.20.11 PING 172.16.20.11 (172.16.20.11): 56 data bytes 64 bytes from 172.16.20.11: seq=0 ttl=63 time=0.548 ms 64 bytes from 172.16.20.11: seq=1 ttl=63 time=0.529 ms --- 172.16.20.11 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.529/0.538/0.548 ms
PS:可能有些系統作了安全限制,可能 ping 不通,這時候能夠添加如下 iptables 規則,目的是讓系統可以轉發不通 VLAN 的數據包。
iptables -t nat -A POSTROUTING -o enp0s8.100 -j MASQUERADE iptables -t nat -A POSTROUTING -oenp0s8.200 -j MASQUERADE iptables -A FORWARD -i enp0s8.100 -o enp0s8.200 -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A FORWARD -i enp0s8.200 -o enp0s8.100 -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A FORWARD -i enp0s8.100 -o enp0s8.200 -j ACCEPT iptables -A FORWARD -i enp0s8.200 -o enp0s8.100 -j ACCEPT
爲何配置 VLAN 子接口,配上 IP 就能夠通了,咱們能夠看下路由表就知道了。
首先看容器 d1 的路由:
root@ubuntu:~# docker exec d1 ip route default via 172.16.10.1 dev eth0 172.16.10.0/24 dev eth0 scope link src 172.16.10.10
咱們在建立容器的時候指定了網關 172.16.10.1
,因此數據包天然會被路由到 host3 的接口。再來看下 host3 的路由:
[root@localhost ~]# ip route default via 192.168.108.1 dev enp0s3 proto dhcp metric 100 172.16.10.0/24 dev enp0s8.100 proto kernel scope link src 172.16.10.1 172.16.20.0/24 dev enp0s8.200 proto kernel scope link src 172.16.20.1 192.168.56.0/24 dev enp0s8 proto kernel scope link src 192.168.56.122 metric 101 192.168.108.0/24 dev enp0s3 proto kernel scope link src 192.168.108.2 metric 100
能夠看到,去往 172.16.10.0/24
網段的數據包會從 enp0s8.100 出去,同理 172.16.20.0/24
網段也是,再加上 host3 的 ip_forward
打開,這就打通了兩個 macvlan 網絡之間的通路。
macvlan 是一種網卡虛擬化技術,可以將一張網卡虛擬出多張網卡。
macvlan 的四種通訊模式,經常使用模式是 bridge。
在 Docker 中,macvlan 只支持 bridge 模式。
相同 macvlan 能夠通訊,不一樣 macvlan 二層沒法通訊,能夠藉助三層路由完成通訊。
思考一下:
後臺回覆「加羣」,帶你進入高手如雲交流羣
個人公衆號 「Linux雲計算網絡」(id: cloud_dev) ,號內有 10T 書籍和視頻資源,後臺回覆 「1024」 便可領取,分享的內容包括但不限於 Linux、網絡、雲計算虛擬化、容器Docker、OpenStack、Kubernetes、工具、SDN、OVS、DPDK、Go、Python、C/C++編程技術等內容,歡迎你們關注。
參考:
https://www.cnblogs.com/Cloud...