linux 虛擬網絡設備的使用


1. linux 常見虛擬網絡設備分類

常見虛擬網絡設備有:bridge, tun/tap, veth-pairs, macvlan, macvtap等。有一篇博文寫的挺好的,圖文並茂:虛擬網絡設備,然而這篇文章是一篇譯文而且內容不全,詳見英文原版連接:Introduction to Linux interfaces for virtual networking

2. bridge設備

bridge設備就是橋接設備,可以看作是一個簡單的交換機,創建方式很簡單:

ip link add dev br0 type bridge # 添加一個網橋設備br0
ip link set tap0 master br0 # 將網卡tap0連接到br0
ip link set enth0 master br0

如果裝過livirtd,它會產生一個名稱為virbr0的bridge設備和一個名叫virbr0-nic的tap設備。

3. tap設備的使用

雖然有這么多博文,但是我還是看不懂tap設備是個什么東西。經過搜索以及實踐,大概明白了tap設備的工作方式。

tap設備是一個工作在二層的設備,可以看作是一個與二層設備進行交互的接口,或者看作是一個特殊的網卡。但是,這個特殊網卡需要有程序來使用它,比如說虛擬機軟件或者vpn軟件。tap設備的一端連接者網絡設備,一般是網橋(bridge),另一端連接着使用這個tap設備的應用程序,比如說虛擬機軟件。tap設備不需要配置ip地址也可以工作。注意:虛擬機軟件使用tap設備,而里面的虛擬機使用的是虛擬機軟件虛擬出來的一個跟tap設備關聯的一個虛擬網卡(有點繞口(汗!)

一個實踐的例子

創建一個tap設備tap0,然后將tap0用到kvm虛擬機當中。

ip tuntap add dev tap0 mode tap # 創建tap0
ip link set tap0 master virbr0 # 將tap0連接到virbr0上,virbr0是libvirtd自帶的網橋設備。
ip link set tap0 up # 開啟tap0設備

創建虛擬機,編輯網卡設備的xml,填入如下內容:

<interface type="ethernet">
  <mac address="52:54:00:25:57:81"/>
  <target dev="tap0" managed="no"/>
  <model type="virtio"/>
  <address type="pci" domain="0x0000" bus="0x01" slot="0x00" function="0x0"/>
</interface>

注意此處managed="no"意思是不讓libvirtd管理該設備。否則,tap0設備屬性會被libvirtd修改,導致連接失敗。

然后啟動虛擬機看看網絡是否暢通。

4. veth-pairs設備的使用

在之前的systemd-nspawn實踐中已經接觸過veth-pairs了,即--network-veth選項。這個選項會在主機中創建一對兒veth設備,這對設備兩端是聯通的,可以用於不同網絡命名空間的通信,如containers之間的通信。啟動centos container,在Host的/sys/class/net目錄下會出現設備:

ve-centos7@if2

這就是在當前命名空間中的veth pairs設備的其中一個,另一個存在於container的命名空間中。在centos7容器中執行ip addr,可看到:

host0@if5

此時的問題在於,如何從Host上訪問container中的veth設備,畢竟container只是一個命名空間而非虛擬機。然而由於systemd-nspawn使用的是匿名的命名空間(anonymous namespace),ip netns只能處理命名的命名空間(named network namespace)。經過查閱,在進程相應/proc/<PID>/ns目錄下可以找到對應命名空間文件。參考How to access an unnamed network namespace,這個連接可能由於眾所周知的原因無法訪問,我把內容復制到這里:

Some programs might create network namespaces without registering them in /run/netns as iproute2 does. This makes it hard to access them with readily available tools like ip netns exec. However, there is a way to register those network namespace, after they have been created.

The following session creates and enters an unnamed namespace:

# unshare -n bash
# ip a l
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
# echo $$
6508

The pid is the only information which we need. Of course we could also gather that by using ps auxf or a variety of other methods.

Now, to register the namespace, we can run the following in another shell:

# touch /run/netns/new_namespace
# mount -o bind /proc/6508/ns/net /run/netns/new_namespace

After this is done, we can access it like any other network namespace created by iproute2:

# ip netns exec unnamed1 bash
# ip link set lo up

And now, if we run ip a l again in the shell we spawned with unshare:

# ip a l
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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

訪問進程的namespace的方法有了,關於如何尋找container對應的命名空間,可以使用ps aux | grep systemd命令,找到<PID>較大的那個/lib/systemd/systemd進程,該進程的namespace就是centos7容器所在的namespace。通過上述方法掛載該container的命名空間,通過ip netns exec <name> bash進入到container的命名空間內。手動mount掛載很麻煩,經過查閱發現可以使用ip netns命令自動掛載,以centos7容器為例,將其命名空間掛載到/run/netns/centos7,可以在Host中使用下面方法:

ip netns attach centos7 <PID>  # 此處的PID就是container的systemd在Host中的PID
ip netns exec centos7 bash # 切換到centos7容器的命名空間

然后ip addr就可以看到host0網卡了。至此,systemd-nspawn的veth網卡終於搞明白了。

veth設備能不能用於qemu虛擬機呢?並不能。參考use veth device with qemu。根據這個網頁所說,qemu不能直接用veth設備,但是可以使用macvtap設備連接到veth設備。動手試試:

ip link add veth0 type veth peer name veth1 # 創建veth設備對
ip link set veth0 master virbr0 # 將veth0連接到virbr0網橋上
ip link add mac-veth1 link veth1 type macvtap mode vepa # 創建一個macvtap設備
ip link set <device> up # 把上面三個設備都打開,否則無法聯網

虛擬機編輯xml文件如下:

<interface type="ethernet">
  <mac address="6a:47:6c:b4:d0:41"/> <!-- 注意此處的mac地址跟mac-veth1的mac地址一樣 -->
  <target dev="mac-veth1" managed="no"/>
  <model type="virtio"/>
  <address type="pci" domain="0x0000" bus="0x01" slot="0x00" function="0x0"/>
</interface>

基本上跟tap設備沒有差別,唯一要注意的地方是mac地址必須跟macvtap設備的mac地址一樣。開機試試,成功聯網!如果不想自己創建macvtap設備,也可以讓虛擬機自己創建。如下:

<interface type='direct' trustGuestRxFilters='no'>
  <mac address="6a:47:6c:b4:d0:41"/>
  <source dev='veth1' mode='vepa'/>
  <model type="virtio"/>
  <address type="pci" domain="0x0000" bus="0x01" slot="0x00" function="0x0"/>
</interface>

5. macvlan和macvtap設備的使用

macvlan原理就是在一個物理網卡上創建多個有mac地址的虛擬網卡。macvtap設備是基於macvlan實現的,只不過macvtap創建了一個設備文件(/dev/tapX,X是一個數字),以便於跟應用程序交互。它們都包含四種模式:vepa, bridge, private,passthru四種。區別如下:

  • vepa:全稱Virtual Ethernet Port Aggregator mode,所有虛擬網卡幀都要發給外部交換機。外部交換機需要支持harpin模式才能使虛擬網卡之間相互通信。
  • bridge:所有虛擬網卡之間是聯通的,可以直接進行通信。
  • private:禁止虛擬網卡之間的通信,即使外部交換機支持harpin模式也不行。
  • passthru:只允許創建一個虛擬網卡,所有物理網卡的流量都會轉發到這個虛擬網卡,常用於macvtap模式。

至於數據包流程圖可以文章開頭的參考連接。

macvlan和macvtap區別就在於,macvlan一般用於系統本身,如container等,macvtap一般用於應用程序,如虛擬機等。

創建語法:

ip link add link DEVICE name NAME type { macvlan | macvtap } mode { private | vepa | bridge | passthru  [ nopromisc ] | source }

其中DEVICE是目標物理網卡,NAME是要創建的虛擬網卡名。創建完成后的網卡名稱一般是“虛擬網卡名@物理網卡名”。

systemd-nspawn也可以指定使用macvlan。選項--network-macvlan=<interface_name>會創建一個macvlan虛擬網卡,<interface_name>是對應物理網卡的名稱。

最后補充一點:使用macvlan或macvtap時,不論使用哪種模式,虛擬網卡都無法跟物理網卡直接通信。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM