上篇文章講述了有關docker的資源控制,主要是三個方面:CPU、內存以及IO。本文將講述docker的4中網絡模式。docker
可能,對於許多接觸Linux操做系統的朋友而言,起初都是經過虛擬機軟件進行層層深刻的學習。而對於其中一種軟件——VMware軟件的網絡鏈接可能就是初學者的一個難題。可能一直都並不瞭解所提供的三種網絡模式的原理和意義。那麼本小節將簡單講述一下有關VMware的三種網絡模式:Bridged(橋接模式)、NAT(網絡地址轉換模式)、Host-Only(僅主機模式)。而此三種分別對應於網卡設備中的VMnet0、VMnet1(或者後期新增建立的)、VMnet8(NAT網卡也只能有一個)shell
概念:橋接模式就是一種將主機(比如是你的筆記本上的)的網卡與虛擬機的網卡利用虛擬網橋進行通訊。centos
原理理解:對這種模式的理解能夠認爲是將物理機虛擬爲一個交換機,全部橋接設置的虛擬機鏈接到這個交換機的一個接口上,固然物理機也同樣須要鏈接到這個交換機,也就是說橋接模式下的全部網卡都是交換模式,相互能夠訪問並且互不干擾。bash
典型特徵:虛擬機的IP地址須要與主機在同一網段,若是須要聯網則網關與DNS須要與主機網卡一致。服務器
具體能夠再經過下面的圖示理解:網絡
NAT模式的話相對來講應該是最熟悉的了。網絡地址轉換,既然有地址轉換,確定是發生了轉變了。NAT模式就比較適合於IP資源緊缺,並且但願虛擬機能夠聯網的狀況。ide
NAT模式藉助的是虛擬的NAT設備以及虛擬的DHCP服務器,從而使得虛擬機能夠聯網。以下圖所示:oop
僅主機模式呢,其實說白了就是沒有NAT設備的網絡模式,僅使用的是VMnet1虛擬網卡與虛擬交換機鏈接,從而與虛擬機通訊,而這種模式就實現了虛擬機與外網的隔離,即獨立的一臺服務器,只與主機互相通訊。以下圖所示:性能
好的,如今大概瞭解了VMware中三種網絡模式的原理了吧,如今繼續來聊聊在docker中的網絡模式。學習
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結合容器的端口(而且端口通常是進行了端口映射,以後會講述)進行容器的訪問。
下面直接經過下面的表格來區分理解一下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
host模式結合VMware中的僅主機模式便可理解,經過下圖表示一下:
從上圖能夠看出,若是在啓動容器後使用的是host模式,那麼這個容器將不會得到一個獨立的Network Namespace(網絡命名空間),而是和宿主機系統共用一個Network Namespace。而且這就意味着容器將不會虛擬出本身的網卡以及配置本身的ip等,而是使用宿主機的ip以及端口。不過呢,在其餘方面例如文件系統等仍是與之隔離的。
這種方式最大優點在於網絡性能比較好可是缺點也很明顯——網絡的隔離性很弱。
這個模式正如上述表格中的說明通常,是表示指定新建立的容器和已經存在的一個容器共享一個Network Namespace。固然這也表示新建的這個容器不會建立本身的網卡等相關操做,而是和與指定的容器共享這些資源。
這種模式也和上述的host差很少,除了網絡方面,其文件系統、進程列表等都是隔離的。
參照下圖:
使用none模式,Docker容器擁有本身的Network Namespace,可是,不會對Docker容器進行任何的網絡配置。這就代表這個Docker容器沒有網卡、IP、路由等信息。須要咱們本身爲Docker容器添加網卡、配置IP等。這種方式網絡的隔離性最爲完全,即代表關閉了容器的網絡功能,也沒法訪問這個容器。
示意圖以下:
該模式就是咱們在啓動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 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
咱們經過嘗試、排錯和驗證的方式來配置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地址的,有默認模式以及自定義模式。
最後,須要注意的是命令仍是須要多記多敲多練,謝謝閱讀!