1. 程式人生 > >Docker網路虛擬化

Docker網路虛擬化

一、Docker網路虛擬化原理

Docker 的網路實現其實就是利用了 Linux 上的網路名稱空間和虛擬網路裝置(特別是 veth pair).

首先,要實現網路通訊,機器需要至少一個網路介面(物理介面或虛擬介面)來收發資料包;此外,如果不同子網之間要進行通訊,需要路由機制。

Docker 中的網路介面預設都是虛擬的介面。虛擬介面的優勢之一是轉發效率較高。 Linux 通過在核心中進行資料複製來實現虛擬介面之間的資料轉發,傳送介面的傳送快取中的資料包被直接複製到接收介面的接收快取中。對於本地系統和容器內系統看來就像是一個正常的乙太網卡,只是它不需要真正同外部網路裝置通訊,速度要快很多。

Docker 容器網路就利用了這項技術。它在本地主機和容器內分別建立一個虛擬介面,並讓它們彼此連通(這樣的一對介面叫做 veth pair)。

netns 是在 linux 中提供網路虛擬化的一個專案,使用 netns 網路空間虛擬化可以在本地虛擬化出多個網路環境,目前 netns 在 lxc 容器中被用來為容器提供網路。
使用 netns 建立的網路空間獨立於當前系統的網路空間,其中的網路裝置以及 iptables 規則等都是獨立的,就好像進入了另外一個網路一樣。

Docker 建立一個容器的時候,會執行如下操作:
  • 建立一對虛擬介面,分別放到本地主機和新容器中;
  • 本地主機一端橋接到預設的 docker0 或指定網橋上,並具有一個唯一的名字,如 veth0;
  • 容器一端放到新容器中,並修改名字作為 eth0,這個介面只在容器的名稱空間可見;
  • 從網橋可用地址段中獲取一個空閒地址分配給容器的 eth0,並配置預設路由到橋接網絡卡 veth0。

完成這些之後,容器就可以使用 eth0 虛擬網絡卡來連線其他容器和其他網路。

通過 –net 引數來指定容器的網路配置,有4個可選值:
  • –net=bridge 這個是預設值,連線到預設的網橋。
  • –net=host 告訴 Docker 不要將容器網路放到隔離的名稱空間中,即不要容器化容器內的網路。此時容器使用本地主機的網路,它擁有完全的本地主機介面訪問許可權。容器程序可以跟主機其它 root 程序一樣可以開啟低範圍的埠,可以訪問本地網路服務比如 D-bus,還可以讓容器做一些影響整個主機系統的事情,比如重啟主機。因此使用這個選項的時候要非常小心。如果進一步的使用 –privileged=true,容器會被允許直接配置主機的網路堆疊。
  • –net=container:NAME_or_ID 讓 Docker 將新建容器的程序放到一個已存在容器的網路棧中,新容器程序有自己的檔案系統、程序列表和資源限制,但會和已存在的容器共享 IP 地址和埠等網路資源,兩者程序可以直接通過 lo 環回介面通訊。
  • –net=none 讓 Docker 將新容器放到隔離的網路棧中,但是不進行網路配置。之後,使用者可以自己進行配置。

二、網路虛擬化部署

1、啟動一個 /bin/bash 容器,指定 –net=none 引數
[[email protected] ~]# docker run -it --name vm1 --net none ubuntu

在這裡插入圖片描述
在這裡插入圖片描述

2、在本地主機查詢容器的程序 id,併為它建立網路名稱空間。
[[email protected] ~]# docker inspect vm1 | grep Pid
            "Pid": 5597,                 ##Pid為5597
            "PidMode": "",
            "PidsLimit": 0,
[[email protected] ~]# ln -s /proc/5597/ns/net /var/run/netns/5597
3、建立一對 “veth pair” 介面 veth0 和 veth1,繫結 veth0 到網橋 docker0,並啟用它
[[email protected] ~]# ip link add name veth0 type veth peer name veth1
[[email protected] ~]# brctl addif docker0 veth0    ##繫結 veth0 到網橋 docker0
[[email protected] ~]# ip link set up dev veth0  
  • 建立介面veth0 和 veth1
    在這裡插入圖片描述

  • 繫結 veth0 到網橋 docker0
    在這裡插入圖片描述

  • 開啟veth0介面
    在這裡插入圖片描述

4、將veth1放到容器的網路名稱空間,命名為 eth0,啟動它並配置一個可用 IP(橋接網段)和預設閘道器。
[[email protected] ~]# ip link set veth1 netns 5597   #將veth1加到namespace “5597” 
[[email protected] ~]# ip netns exec 5597 ip link set veth1 name eth0
[[email protected] ~]# ip netns exec 5597 ip link set up dev eth0
[[email protected] ~]# ip netns exec 5597 ip addr add 172.17.0.51/24 dev eth0
[[email protected] ~]# ip netns exec 5597 ip route add default via 172.17.0.1
  • 開啟埠前,eth0埠為DOWN
    在這裡插入圖片描述
  • 開啟埠後,eth0埠為UP
    在這裡插入圖片描述
  • 配置ip
    在這裡插入圖片描述
  • 配置閘道器
    在這裡插入圖片描述
以上,就是 Docker 配置網路的具體過程。

當容器結束後,Docker 會清空容器,容器內的 eth0 會隨網路名稱空間一起被清除,veth0 介面也被自動從 docker0 解除安裝。

此外,使用者可以使用 ip netns exec 命令來在指定網路名稱空間中進行配置,從而配置容器內的網路。