首頁 > 軟體

Docker網路模式與設定Docker自定義網路(bridge模式)

2020-06-16 16:12:22

一、簡述VMware中三種網路模式

? 可能,對於許多接觸Linux作業系統的朋友而言,起初都是通過虛擬機器軟體進行層層深入的學習。而對於其中一種軟體——VMware軟體的網路連線可能就是初學者的一個難題。可能一直都並不了解所提供的三種網路模式的原理和意義。那麼本小節將簡單講述一下有關VMware的三種網路模式:Bridged(橋接模式)、NAT(網路地址轉換模式)、Host-Only(僅主機模式)。而此三種分別對應於網絡卡裝置中的VMnet0、VMnet1(或者後期新增建立的)、VMnet8(NAT網絡卡也只能有一個)

1.1橋接模式

? 概念:橋接模式就是一種將主機(好比是你的筆電上的)的網絡卡與虛擬機器的網絡卡利用虛擬網橋進行通訊。

? 原理理解:對這種模式的理解可以認為是將物理機虛擬為一個交換機,所有橋接設定的虛擬機器連線到這個交換機的一個介面上,當然物理機也一樣需要連線到這個交換機,也就是說橋接模式下的所有網絡卡都是交換模式,相互可以存取而且互不干擾。

? 典型特徵:虛擬機器的IP地址需要與主機在同一網段,如果需要聯網則閘道器與DNS需要與主機網絡卡一致。

? 具體可以再通過下面的圖示理解:

1.2網路地址轉換模式

? NAT模式的話相對來說應該是最熟悉的了。網路地址轉換,既然有地址轉換,肯定是發生了轉變了。NAT模式就比較適合於IP資源緊缺,而且希望虛擬機器可以聯網的情況。

? NAT模式借助的是虛擬的NAT裝置以及虛擬的DHCP伺服器,從而使得虛擬機器可以聯網。如下圖所示:

1.3僅主機模式

? 僅主機模式呢,其實說白了就是沒有NAT裝置的網路模式,僅使用的是VMnet1虛擬網絡卡與虛擬交換機連線,從而與虛擬機器通訊,而這種模式就實現了虛擬機器與外網的隔離,即獨立的一台伺服器,只與主機互相通訊。如下圖所示:

? 好的,現在大概了解了VMware中三種網路模式的原理了吧,現在繼續來聊聊在docker中的網路模式。

二、docker的網路模式

2.1docker網路實現原理

? docker使用Linux橋接的方式,即在宿主機虛擬一個docker容器網橋(docker0),docker啟動一個 容器時會根據docker網橋的網段分配給容器一個IP地址,這個地址就是容器ip,同時docker就是每個容器的預設閘道器。因此,同一個宿主機內的容器就可以通過容器ip地址直接通訊。

? 一般情況下,我們在安裝和啟動docker服務之後使用ifconfig命令即可檢視到這個docker0的虛擬網橋裝置:

[root@localhost ~]# ifconfig | head -7
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:58:71:c9:ba  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

從上面顯示的結果來看,預設的容器閘道器地址為172.17.0.1/16哈!當然loopback網絡卡是回環網絡卡,測試驗證(TCP/IP連線),virtual bridge則是虛擬網橋(想想KVM【雲原生】)

? 當然,docker網橋是宿主機虛擬出來的,並不是真實存在的網路裝置,外部網路是無法通過ip地址直接定址的,這就表明我們需要通過其他的方式來使外部網路可以存取容器,一般會通過存取宿主機ip結合容器的埠(並且埠一般是進行了埠對映,之後會講述)進行容器的存取。

2.2docker四種網路模式

下面直接通過下面的表格來區分理解一下docker的四種網路模式

docker網路模式設定說明
host   容器和宿主機共用Network namespace
container模式   容器和另外一個容器共用Network namespace
none模式   容器有獨立的Network namespace,但並沒有對其進行任何網路設定,如分配veth pair 和網橋連線,設定IP等
bridge模式   預設的模式

其實啟動docker服務之後,可以使用docker network相關命令控制管理網路,下面我們檢視一下網路列表:(預設存在下面三個)下面逐一介紹(結合第一小節的內容來理解docker 中的網路原理)

[root@localhost ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
3763f78eb404        bridge              bridge              local
3bb2f50eb211        host                host                local
e12cd7b98c54        none                null                local

2.2.1host模式

host模式結合VMware中的僅主機模式即可理解,通過下圖表示一下:

從上圖可以看出,如果在啟動容器後使用的是host模式,那麼這個容器將不會獲得一個獨立的Network Namespace(網路名稱空間),而是和宿主機系統共用一個Network Namespace。並且這就意味著容器將不會虛擬出自己的網絡卡以及設定自己的ip等,而是使用宿主機的ip以及埠。不過呢,在其他方面例如檔案系統等還是與之隔離的。

這種方式最大優勢在於網路效能比較好但是缺點也很明顯——網路的隔離性很弱。

2.2.2container模式

? 這個模式正如上述表格中的說明一般,是表示指定新建立的容器和已經存在的一個容器共用一個Network Namespace。當然這也表示新建的這個容器不會建立自己的網絡卡等相關操作,而是和與指定的容器共用這些資源。

? 這種模式也和上述的host差不多,除了網路方面,其檔案系統、進程列表等都是隔離的。

參照下圖:

2.2.3none模式

? 使用none模式,Docker容器擁有自己的Network Namespace,但是,不會對Docker容器進行任何的網路設定。這就表明這個Docker容器沒有網絡卡、IP、路由等資訊。需要我們自己為Docker容器新增網絡卡、設定IP等。這種方式網路的隔離性最為徹底,即表明關閉了容器的網路功能,也無法存取這個容器。

示意圖如下:

2.2.4bridge模式

? 該模式就是我們在啟動docker服務後預設的docker網路模式,其會在主機上建立一個名為docker0的虛擬網橋,這個主機上的所有啟動的容器就會連線到這個虛擬網橋上。結合VMware中網橋模式原理,想想物理交換機的原理,就不難理解了。

? 從docker0子網中分配一個IP給容器使用,並設定docker0的IP地址為容器的預設閘道器。在主機上建立一對虛擬網絡卡veth pair裝置,Docker將veth pair裝置的一端放在新建立的容器中(這個veth對我們在OpenStack中見過,筆者覺得可以將之理解為一個橋樑,建立橋兩岸的關係而存在的一種虛擬裝置),並命名為eth0(容器的網絡卡),另一端放在主機中,以vethxxx這樣類似的名字命名,並將這個網路裝置加入到docker0網橋中。

? 使用docker run -p 命令時,docker實際是在防火牆做了DNAT規則,實現埠轉發的功能。

下面通過一個節點的伺服器結構圖來理解:

當然,這四種模式都不需要手動設定,真正需要設定的是自定義網路。

三、docker網路控制相關命令設定

上面已經給出了對應docker網路控制的命令docker network,下面具體看一下這個命令的具體說明:

docker network的命令用法:
Usage:  docker network COMMAND

Manage networks

Commands:
  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  prune       Remove all unused networks
  rm          Remove one or more networks

3.1橋接命令設定

我們通過嘗試、排錯和驗證的方式來設定docker網路。

因為需要NAT地址轉換功能,所以需要開啟防火牆,但是核心防護還是關了吧。

[root@localhost ~]# systemctl start firewalld.service 
[root@localhost ~]# systemctl status firewalld.service 
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
   Active: active (running) since 一 2020-04-06 10:18:40 CST; 2s ago
     Docs: man:firewalld(1)
 Main PID: 65611 (firewalld)
...

初始化環境:(後面會返回到這個環境狀態)

[root@localhost ~]# docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

我們嘗試通過docker網橋方式(橋接)給一個容器設定一個ip地址(自定義的),下面看一下命令執行的結果:

[root@localhost ~]# docker run -itd --name test --network bridge --ip 172.17.0.10 CentOS:7 /bin/bash
Unable to find image 'centos:7' locally
7: Pulling from library/centos
ab5ef0e58194: Pull complete 
Digest: sha256:4a701376d03f6b39b8c2a8f4a8e499441b0d567f9ab9d58e4991de4472fb813c
Status: Downloaded newer image for centos:7
29f9e9cbb398085d7c89bed2982d626bfb7e564371a76a6cb693cffa68b917af
docker: Error response from daemon: user specified IP address is supported on user defined networks only.

首先,由於沒有改映象,所以會先拉取映象之後建立以及嘗試執行容器,但是會遇到報錯,報錯原因是因為使用者自己設定的ip地址只適合於他們自己定義的網路。但是這並不影響映象的獲取與建立,我們嘗試執行看看結果:

[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              7                   5e35e350aded        4 months ago        203MB
[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
29f9e9cbb398        centos:7            "/bin/bash"         About a minute ago   Created                                 test
[root@localhost ~]# docker start 29f9e9cbb398
Error response from daemon: user specified IP address is supported on user defined networks only
Error: failed to start containers: 29f9e9cbb398

? 很顯然,結果告訴我們還是上述的原因導致了這個問題,好吧只能刪除這個容器了。索性還原為初始化環境吧(其實可以去掉--network bridge就不會報錯,但是設定的ip地址會不生效,可以自行嘗試一下),我們不指定ip地址來試一下,順便驗證一下不加這個引數試試,最後還原為初始化狀態後我們再通過自定義的方式來設定ip地址吧。

[root@localhost ~]# docker run -itd --name demo centos:7 /bin/bash
984545df8ebf2c30f4ccf3f5f4699ed67bd2a93cbc068f2ace4865a828b4a4d1
[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
984545df8ebf        centos:7            "/bin/bash"         8 seconds ago       Up 6 seconds                            demo

進入容器檢視ip地址


[root@localhost ~]# docker exec -it 984545df8ebf /bin/bash
[root@984545df8ebf /]# yum install -y net-tools
Loaded plugins: fastestmirror, ovl
Determining fastest mirrors
[root@984545df8ebf /]# ifconfig 
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 2201  bytes 15042254 (14.3 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1999  bytes 111171 (108.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        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地址。

[root@localhost ~]# docker network create --subnet=172.18.0.0/24 mynetwork
Error response from daemon: Failed to Setup IP tables: Unable to enable SKIP DNAT rule:  (iptables failed: iptables --wait -t nat -I DOCKER -i br-4cd28c051bec -j RETURN: iptables: No chain/target/match by that name.
 (exit status 1))

看來很不幸啊,又error了,不要慌,我們看看是什麼原因導致的,這個報錯的根源看似是防火牆,說是無法跳過DNAT(目標網路地址轉換)規則,其實導致這個問題的原因是我們剛剛開啟了防火牆,卻沒有重新啟動docker服務,就有點類似更改了組態檔沒有重新啟動服務。

[root@localhost ~]# systemctl restart docker
[root@localhost ~]# docker network create --subnet=172.18.0.0/24 mynetwork
723d0fd514eb219d57667f72c3eb75fc4864af0cd94c21b6c70e868fb8d520a1
[root@localhost ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
00008a1e778b        bridge              bridge              local
3bb2f50eb211        host                host                local
723d0fd514eb        mynetwork           bridge              local
e12cd7b98c54        none                null                local
[root@localhost ~]# 

此時進行驗證自定義設定一個容器的固定IP地址的測試:

[root@localhost ~]# docker run -itd --name test2 --network mynetwork --ip 172.18.0.10 centos:7 /bin/bash
Unable to find image 'centos:7' locally
7: Pulling from library/centos
ab5ef0e58194: Pull complete 
Digest: sha256:4a701376d03f6b39b8c2a8f4a8e499441b0d567f9ab9d58e4991de4472fb813c
Status: Downloaded newer image for centos:7
683ad76f7789b5c16f251577047a288a3a4a00777128a216adfee15985b94c04

檢視容器的狀態,進入容器檢視ip地址

[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
683ad76f7789        centos:7            "/bin/bash"         23 seconds ago      Up 22 seconds                           test2
[root@localhost ~]# docker exec -it 683ad76f7789 /bin/bash
[root@683ad76f7789 /]# yum install -y net-tools
Loaded plugins: fastestmirror, ovl
...
[root@683ad76f7789 /]# ifconfig 
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.18.0.10  netmask 255.255.255.0  broadcast 172.18.0.255
        ether 02:42:ac:12:00:0a  txqueuelen 0  (Ethernet)
        RX packets 2302  bytes 15050471 (14.3 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2049  bytes 113777 (111.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 62  bytes 7019 (6.8 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 62  bytes 7019 (6.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

此時發現自定義的網路設定容器ip地址成功了。

四、總結

? 本文通過對VMware軟體中的三種網路模式工作的原理,層層遞進深入講解docker的各種網路模式,並且通過案例結合排障思路詳細介紹了有關docker網橋模式是如何設定容器ip地址的,有預設模式以及自定義模式。

?最後,需要注意的是命令還是需要多記多敲多練,謝謝閱讀!


IT145.com E-mail:sddin#qq.com