閱讀562 返回首頁    go 阿裏雲 go 技術社區[雲棲]


[翻譯]Macvlan 網絡驅動入門

Macvlan 網絡驅動入門


Macvlan網絡驅動是為了在Docker的用戶的使用場景中提供一個穩定的,生產就緒的網絡驅動。目前Libnetwork 允許用戶控製IPv4和IPv6地址管理。對於需要將容器網絡和底層網絡集成的用戶來說,VLAN的驅動也允許他們完全控製二層VLAN taggine。而對於使用不依賴於物理網絡約束的overlay網絡方式部署網絡結構的用戶,可以參考multi-host overlay 的驅動部署容器的網絡。

Macvlan是一種新的網絡虛擬化技術。Linux使用非常輕量的方式實現Macvlan,因為Mavlan不使用傳統的Linux bridge做隔離和區分,而是直接與Linux的以太網接口或者子接口關聯,以實現在物理網絡中網絡和連接的隔離。

Macvlan提供了很多獨特的功能以及為後麵更多模式加入的接口。Macvlan中的那些模式的優勢在於比較高的網絡性能,以及不依賴於Linux Bridge技術,簡化虛擬網絡的結構。移除了傳統的Docker宿主機的網絡設備和容器中虛擬網絡設備中間的Linux bridge,而使用容器的虛擬網絡接口直接掛載到宿主機的網絡接口刪個。這樣在Docker上就可以更加方便的暴漏服務出去,因為這種方式不需要端口映射就可以讓外部訪問到容器中的服務。

實現準備

  • 下麵這個示例中的宿主機是使用Docker 1.12.0以上的版本的單機上測試的。

  • 所有的示例都可以在運行了Docker的宿主機上測試,示例中使用了sub-interface比如eth0.10可以替換成eth0或者別的可用的宿主機上的parent-interface。子接口名字中有.字符的可以即使的自動的被創建。如果不指定-o parent的參數值,就會自動創建一個dummy的接口保證本地宿主機容器的連通性。

  • 內核要求:

  • 使用uname -r命令輸出和檢查kernel版本
  • 支持Macvlan的kernel版本:v3.9–3.19 和 4.0+

Macvlan Bridge模式使用示例

Macvlan Bridge模式每個容器有一個獨立的MAC地址,用於記錄宿主機上的MAC地址的端口的映射。

  • Macvlan驅動的網絡會被掛載到一個宿主機上的網絡接口,例如宿主機的物理網絡接口eth0,用於802.1q VLAN tagging的子接口,例如eth0.10(.10表示VLAN 10),或者綁定宿主機的適配器,將兩個以太網接口捆綁成一個邏輯接口。

  • 指定的網關是宿主機的外部的基礎網絡設施提供的網關

  • 每個Macvlan Bridge模式的Docker網絡都是相互隔離的,並且一個網絡接口不允許多個網絡同時掛載。並且理論上一個宿主機的網絡適配器最多隻能掛載4,094個子接口。

  • macvlan bridge中,同一個子網內的任何一個容器都可以在不需要網關的情況下與別的容器互相通信。
  • docker network命令對於vlan的驅動同樣適用
  • 在Macvlan模式下,在不同網絡/子網中的容器不能在沒有外部路由的情況下互相訪問,或者同一個網絡擁有多個子網,子網間也是不能在沒有外部路由的情況下互相訪問。

在下麵的示例中,docker宿主機的eth0接口有一個在172.16.86.0/24網絡中的IP和默認的網關地址172.16.86.1。這個網關是一個地址是172.16.86.1的外部路由器。對於bridge模式中,宿主機的eth0是不需要配置IP地址的,它僅僅是為了轉發到上層網絡中的交換機和路由器。

Simple Macvlan Bridge Mode Example

注意 在Macvlan bridge模式中子網的配置需要跟宿主機的接口的配置一致。例如,使用和宿主機以太網接口一直的子網和網關配置,這個網絡接口可以通過-o parent=選項指定。

  • 這個例子中我們使用的父接口是eth0並且它在子網172.16.86.0/24的網段上。在docker network中看到的容器需要和-o parent=使用同樣的子網配置。網關是一個網絡中的外部的路由器,到這個路有器之間沒有ip地址偽裝和別的代理。
  • 使用網絡驅動需要在創建網絡時指明-d 驅動名選項,在這個驅動既-d macvlan選項
  • 父接口配置通過-o parent=eth0,如下:
ip addr show eth0
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet 172.16.86.250/24 brd 172.16.86.255 scope global eth0

創建macvlan網絡,並啟動兩個容器掛載到這個網絡中:

# Macvlan  (-o macvlan_mode= Defaults to Bridge mode if not specified)
docker network create -d macvlan \
    --subnet=172.16.86.0/24 \
    --gateway=172.16.86.1  \
    -o parent=eth0 pub_net

# Run a container on the new network specifying the --ip address.
docker  run --net=pub_net --ip=172.16.86.10 -itd alpine /bin/sh

# Start a second container and ping the first
docker  run --net=pub_net -it --rm alpine /bin/sh
ping -c 4 172.16.86.10

看一下這倆容器的IP和路由表:


ip a show eth0
    eth0@if3: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UNKNOWN
    link/ether 46:b2:6b:26:2f:69 brd ff:ff:ff:ff:ff:ff
    inet 172.16.86.2/24 scope global eth0

ip route
    default via 172.16.86.1 dev eth0
    172.16.86.0/24 dev eth0  src 172.16.86.2

# NOTE: the containers can NOT ping the underlying host interfaces as
# they are intentionally filtered by Linux for additional isolation.
# In this case the containers cannot ping the -o parent=172.16.86.250

你可以通過-o mavlan_mode=bridge參數指定bridge模式,如果不指定 You can explicitly specify the bridge mode option -o macvlan_mode=bridge. 而且在不指定是默認也是bridge模式.

雖然在Macvlan模式中父接口eth0並不需要IP地址,但一般接口不會沒有IP地址吧,在創建網絡的時候如果使用默認的IPAM的話,可以使用--aux-address=x.x.x.x的表示,這樣在分配給容器IP地址時就會排除掉指定的IP地址,下麵這個例子就是排除了eth0的網絡地址的命令:

docker network create -d macvlan \
    --subnet=172.16.86.0/24 \
    --gateway=172.16.86.1  \
    --aux-address="exclude_host=172.16.86.250" \
    -o parent=eth0 pub_net

另外一個默認的Docker IPAM驅動提供的IP地址選取的參數是ip-range=。這個表示了驅動分配IP地址的範圍是ip-range的地址段,而不是使用--subnet=的參數的段。例如下麵這個例子,IP地址的分配將從192.168.32.128開始分配。

docker network create -d macvlan  \
    --subnet=192.168.32.0/24  \
    --ip-range=192.168.32.128/25 \
    --gateway=192.168.32.254  \
    -o parent=eth0 macnet32

# Start a container and verify the address is 192.168.32.128
docker run --net=macnet32 -it --rm alpine /bin/sh

網絡可以通過如下方式刪除:

docker network rm <network_name or id>
  • 注意 在Macvlan你不能ping或者聯通宿主機的namespace中的IP地址,比如你創建了容器,並試圖ping Docker宿主機上的eth0的地址,這個是通的。這個通信由於安全性和隔離性被kernel的內核模塊攔截了。

Docker的網絡命令可以參考 使用Docker network命令

Macvlan 802.1q Trunk Bridge 模式使用示例

VLAN技術很長時間都被用作數據中心虛擬化網絡的解決方案,並且在今天還有很多的使用。VLAN通過一個12位的標簽,區分不同的域的方式實現對單個或者多個子網的邏輯的分組。對於網絡工程師來說通過VLAN劃分網絡和配置例如webdb或者其他需要隔離的服務的安全是在正常不過的事了。

目前一個宿主機上需要連接多個虛擬網絡是很正常的,Linux網絡很早就支持VLAN的標簽,它的標準是802.1q,用於管理網絡中的數據隔離。可以通過配置連接到Docker宿主機的以太網連接支持802.1q的VLAN ID,以便於創建Linux的子接口,而每個子接口可以用唯一的VLAN ID。

Multi Tenant 802.1q Vlans

眾所周知,給Linux宿主機配置802.1q的操作時很複雜和痛苦的,它需要配置一係列的文件,以便於在係統重啟後依然能保證配置。如果再引入了網橋的話,物理網卡的接口需要掛載到這個網橋上,然後每個網橋獲得IP地址。因為還需要再不同網橋上隔離訪問,這樣就導致了非常複雜的網絡配置。

和其他Docker網絡驅動類似,驅動的首要目標即緩解管理網絡資源時操作的痛苦。為了那個目的,當一個網絡在創建網絡的時候收到一個並不存在的子接口作為網絡的父接口,那麼驅動就會在創建網絡的時候創建一個VLAN標記的接口。

當宿主機重啟時,這個驅動會在Docker daemon重啟的時候重新創建網絡的網絡接口,而不是修改那些複雜的網絡配置文件。如果VLAN的子接口是Docker daemon在docker network create的時候創建的,那麼在Docker重啟後隻會重新創建這個子接口,並在在docker network rm的時候刪除這個子接口。

如果用戶不希望Docker修改-o parent參數中的子接口,那麼用戶隻簡單的需要在這個參數中傳入一個已經存在的接口作為網絡的父接口。像eth0這樣的父接口是不會被刪除的,隻有那些不是master的接口才能被刪除。

這個驅動添加和刪除的vlan子接口的格式是interface_name.vlan_tag

例如:eth0.50意思是父接口是eth0,掛載在它上麵的一個子接口是eth0.50,並且vlan id是50。這個配置等價到ip link的配置命令是: ip link add link eth0 name eth0.50 type vlan id 50

Vlan ID 50

在Docker的宿主機上創建第一個VLAN標記和隔離的網絡,通過在創建網絡的時候指定了-o parent=eth0.50指定父接口為vlan id為50的接口eth0.50。這個父接口也可以手動指定別的名字,但如果那樣就必須手動通過ip link或者配置文件創建和刪除父接口。如果通過-o parent指定的接口存在的話,隻要這個接口兼容與Linux 網絡接口的標準就可以被使用。

# 現在創建網絡掛載到VLAN標記的接口上
docker network  create  -d macvlan \
    --subnet=192.168.50.0/24 \
    --gateway=192.168.50.1 \
    -o parent=eth0.50 macvlan50

# 在兩個不同的終端上,啟動兩個Docker容器,然後兩個容器就分別可以ping通另外一個。
docker run --net=macvlan50 -it --name macvlan_test5 --rm alpine /bin/sh
docker run --net=macvlan50 -it --name macvlan_test6 --rm alpine /bin/sh

Vlan ID 60

創建另外一個隔離的,VLAN標記的隔離的網絡,通過在創建網絡的時候指定了-o parent=eth0.60指定父接口為vlan id為60的接口eth0.60,而macvlan_mode=參數的默認值為macvlan_mode=bridge,可以看到在下麵這個示例中有相同的結果。

# 現在創建網絡掛載到VLAN標記的接口上
docker network  create  -d macvlan \
    --subnet=192.168.60.0/24 \
    --gateway=192.168.60.1 \
    -o parent=eth0.60 -o \
    -o macvlan_mode=bridge macvlan60

# 在兩個不同的終端上,啟動兩個Docker容器,然後兩個容器就分別可以ping通另外一個。
docker run --net=macvlan60 -it --name macvlan_test7 --rm alpine /bin/sh
docker run --net=macvlan60 -it --name macvlan_test8 --rm alpine /bin/sh

例子: 多個子網的 Macvlan 802.1q Trunking

下麵的例子除了添加了更多的用戶選擇的容器子網的綁定外和前麵的例子是一樣的。在MacVlan/Bridge模式,容器隻能ping通同一個子網/廣播域,除非有外部的路由去路由不同的子網的網絡流量。

### 創建多個L2網絡
docker network create -d ipvlan \
    --subnet=192.168.210.0/24 \
    --subnet=192.168.212.0/24 \
    --gateway=192.168.210.254  \
    --gateway=192.168.212.254  \
     -o ipvlan_mode=l2 ipvlan210

# 測試 192.168.210.0/24 容器間連接性
docker run --net=ipvlan210 --ip=192.168.210.10 -itd alpine /bin/sh
docker run --net=ipvlan210 --ip=192.168.210.9 -it --rm alpine ping -c 2 192.168.210.10

# 測試 192.168.212.0/24 容器間連接性
docker run --net=ipvlan210 --ip=192.168.212.10 -itd alpine /bin/sh
docker run --net=ipvlan210 --ip=192.168.212.9 -it --rm alpine ping -c 2 192.168.212.10

多層 IPv4 IPv6 Macvlan Bridge 模式

示例: Macvlan Bridge模式, 802.1q trunk, VLAN ID: 218, 多個子網 構成的多層

# 創建多個子網網段的macvlan網絡
docker network  create  -d macvlan \
    --subnet=192.168.216.0/24 --subnet=192.168.218.0/24 \
    --gateway=192.168.216.1  --gateway=192.168.218.1 \
    --subnet=2001:db8:abc8::/64 --gateway=2001:db8:abc8::10 \
     -o parent=eth0.218 \
     -o macvlan_mode=bridge macvlan216

# 在第一個192.168.216.0/24網段創建一個容器
docker run --net=macvlan216 --name=macnet216_test --ip=192.168.216.10 -itd alpine /bin/sh

# 在第二個192.168.218.0/24網段創建容器
docker run --net=macvlan216 --name=macnet216_test --ip=192.168.218.10 -itd alpine /bin/sh

# 通過192.168.216.0/24的網段的容器Ping 在192.168.216.0/24網段中的第一個容器
docker run --net=macvlan216 --ip=192.168.216.11 -it --rm alpine /bin/sh
ping 192.168.216.10

# 通過192.168.218.0/24的網段的容器Ping 在192.168.218.0/24網段中的第一個容器
docker run --net=macvlan216 --ip=192.168.218.11 -it --rm alpine /bin/sh
ping 192.168.218.10

查看其中一個容器的詳情:

docker run --net=macvlan216 --ip=192.168.216.11 -it --rm alpine /bin/sh

root@526f3060d759:/# ip a show eth0
    eth0@if92: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
    link/ether 8e:9a:99:25:b6:16 brd ff:ff:ff:ff:ff:ff
    inet 192.168.216.11/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 2001:db8:abc4::8c9a:99ff:fe25:b616/64 scope link tentative
       valid_lft forever preferred_lft forever
    inet6 2001:db8:abc8::2/64 scope link nodad
       valid_lft forever preferred_lft forever

# 指定的IP V4的網關地址是192.168.216.1
root@526f3060d759:/# ip route
  default via 192.168.216.1 dev eth0
  192.168.216.0/24 dev eth0  proto kernel  scope link  src 192.168.216.11

# 指定的IP V6的網關地址是 2001:db8:abc8::10
root@526f3060d759:/# ip -6 route
  2001:db8:abc4::/64 dev eth0  proto kernel  metric 256
  2001:db8:abc8::/64 dev eth0  proto kernel  metric 256
  default via 2001:db8:abc8::10 dev eth0  metric 1024
原文鏈接:https://docs.docker.com/engine/userguide/networking/get-started-macvlan/#dual-stack-ipv4-ipv6-macvlan-bridge-mode

最後更新:2017-09-04 10:02:27

  上一篇:go  BLOCKED,WAITING,TIMED_WAITING有什麼區別?-用生活的例子解釋
  下一篇:go  SSSSSSSSSSSSSSSSSSSSSSS