本節主要是介紹Docker默認的網路行為,包含創建的默認網路型別以及如何創建用戶自定義網路,也會介紹如何在單一主機或者跨主機集群上創建網路的資源需求,
1、默認網路
當你安裝了docker,她自動創建了3個網路,可以使用docker network命令來查看

這三個網路被docker內建,當你運行一個容器的時候,可以使用--network引數來指定你的容器連接到哪一個網路,
1)bridge網路
默認連接到docker0這個網橋上,

注:brctl命令在centos中可以使用yum install bridge-utils來安裝
啟動并運行一個容器

[root@localhost ~]# docker exec -it test1 /bin/bash

可以看到test1容器已經獲取了一個地址172.17.0.3,和主機的docker0介面地址在同一個網路,并將主機的docker0介面地址設定為了網關,

在物理主機上,查看網橋docker0,可以看到已經多了一個介面,

Docker容器默認使用bridge模式的網路,其特點如下:
- 使用一個linux bridge,默認docker0,
- 使用veth對,一頭在容器的網路namespace中,一頭在docker0上,
- 該模式下Docker Container不具有一個公有IP,因為宿主機的IP地址與veth pair的IP地址不在同一個網段內,
- Docker采用NAT方式,將容器內部的服務監聽的埠與宿主機的某一個埠port進行”系結“,使得宿主機以外的世界可以主動將網路保存發送至容器內部,
- 外界訪問容器內的服務時,需要訪問宿主機的IP以及宿主機的埠port,
- NAT模式由于是在三層網路上的實作手段,故肯定會影響網路的傳輸效率,
- 容器擁有獨立、隔離的網路堆疊;讓容器和宿主機以外的世界通過NAT簡歷通信
效果是這樣的:

示意圖如下:

在物理主機上查看iptables的nat表,可以看到在POSTROUTING鏈中做了地址偽裝:MASQUERADE動作,這樣容器就可以通過原地址轉換NAT訪問外部網路了,
通過iptables -t nat -vnL命令查看到:

可以使用docker network inspect bridge命令來查看bridge網路情況:
[root@localhost ~]# docker network inspect bridge
[
{
"Name": "bridge",
"Id": "d22bd827a7eb3206cd71bd7c60c4fe68b8ba068a2716abf89b7a5a3c68dd9635",
"Created": "2020-10-21T21:37:12.892688838+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
2)none網路模式:
網路模式為none,即不為Docker容器構造任何網路環境,不會為容器創建網路介面,一旦Docker容器采用了none網路模式,那么容器內部就只能使用loopback網路設備,不會再有其他的網路資源,Docker Container的網路模式意味著不給該容器創建任何網路環境,容器只能使用127.0.0.1的本機網路,
啟動一個容器,設為none網路
[root@localhost ~]# dockerv run -it -d --network none --name test3 ubuntu /bin/bash
由于沒有網路不能使用yum安裝ip addr命令,所以不能查看網卡,
3)host網路模式
Host模式并沒有為容器創建一個隔離的網路環境,而之所以稱之為host模式,是因為該模式下的Docker容器會和host宿主機共享同一個網路namespace,故Docker Container可以和宿主機一樣,使用宿主機的eth0,實作和外界的通信,換言之,Docker Container其特點包括:
- 這種模式下的容器沒有隔離的network namespace
- 容器的IP地址同Docker host的IP地址
- 需要注意容器中服務的埠號不能與Docker host上已經使用的埠號相沖突
- host模式能夠和其它模式共存
示意圖:

例如,我們在192.168.22.7/24的機器上用host模式啟動一個含有web應用的Docker容器,監聽tcp80埠,當我們在容器中執行任何類似ifconfig命令查看網路環境時,看到的都是宿主機上的資訊,而外界訪問容器中的應用,則直接使用192.168.22.7:80即可,不用任何NAT轉換,就如直接跑在宿主機一樣,但是,容器的其他方面,如檔案系統、行程串列等還是和宿主機隔離的,
啟動容器前,查看物理主機的httpd行程

啟動一個容器:
[root@localhost ~]# docker run -itd --privileged --name test5 --network host centos:7 init
進入容器,安裝httpd容器,并啟動:
[root@localhost ~]# docker exec -it test5 /bin/bash
[root@localhost /]# yum -y install httpd
[root@localhost /]# systemctl start httpd
[root@localhost /]# echo "test docker host network" > /var/www/html/index.html
退出容器,在此查看httpd行程:

訪問主機的80埠,可以訪問到容器test5網站服務(注意防火墻):
[root@localhost ~]# firewall-cmd --add-port=80/tcp
success

4)container模式
這個模式指定新創建的容器和已經存在的一個容器共享一個Network Namespace,而不是和宿主機共享,新創建的容器不會創建自己的網卡,配置自己的IP,而是和一個指定的容器共享IP、埠范圍等,同樣,兩個容器除了網路方面,其他的如檔案系統、進行串列等還是隔離的,兩個容器的行程可以通過lo網卡設備通信,
Container網路模式是Docker中一種較為特別的網路模式,這兩個容器之間不存在網路隔離,而這兩個容器又與宿主機以及除此之外其他的容器存在網路隔離,
注意:因為此時兩個容器要共享一個network namespace,因此需要注意埠沖突情況,否則第二個容器將無法被啟動
示意圖:

運行一個容器:查看容器IP



啟動另外一個容器,使用test5容器網路:
[root@localhost ~]# docker run -itd --name test6 --network container:test5 centos:7 /bin/bash
5f726c21a516f081212f0b6dee91f0e86ba30dd8eb1c88f2fc38ca8c04222e79

進入test6容器,查看網路情況,可以看到兩個容器地址資訊相同,是共享的


通過上面的docker網路學習,已經可以實作容器和外部網路通信了,但是如何讓外部網路來訪問容器呢?
外部訪問容器:
容器中可以運行一些網路應用,要讓外部也可以訪問這些應用,可以通過-P或-p引數來指定埠映射,
當使用-P(大寫)標記時,Docker會隨機映射一個隨機埠到內部容器開放的網路埠,
注意:-P使用時需要指定--expose選項或dockerfile中用expose指令容器要暴露的埠,指定需要對外提供服務的埠,
從docker hub下載一個http的鏡像


使用這個下載的鏡像啟動一個容器:

可以看到容器的80埠被隨機映射到主機的32768埠
訪問主機IP地址的32768埠,就可以訪問到容器的httpd服務,

-p(小寫)則可以指定要映射的埠,并且,在一個指定埠上只可以系結一個容器,支持的格式有ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort
注意:
- 容器有自己的內部網路和ip地址(使用docker inspect可以獲取所有的變數,)
- -p標記可以多次使用來系結多個埠

可以看到主機8000埠已經和容器web-test002的80埠做了映射
訪問主機的8000埠

映射到指定地址的指定埠:
可以使用ip:hostPort:containerPort格式,指定映射使用一個特定地址,比如宿主機網卡配置的一個地址192.168.22.7

映射到指定地址的任意埠:
使用ip::containerPort系結192.168.22.7的任意埠到容器80埠,本地主機會自動分配一個口,--name為啟動的容器指定一個容器名,

注意:還可以使用udp標記來指定udp埠
[root@localhost ~]# docker run -d -p 127.0.0.1:5000:5000/udp --name db4 mysql
查看映射埠配置

docker埠映射實質上是在iptables的nat表中添加了DNAT規則:


3、用戶自定義網路:
建議使用用戶定義的橋接網路來控制容器之間的彼此通信,并啟用容器名稱和IP地址的自動DNS決議,docker默認提供了用于創建這些網路的默認網路驅動程式,你能創建:
- bridge network
- overlay network
- MACVLAN network
- network plugin
- remote network
您可以根據需要創建盡可能多的網路,并且可以在任何給定的時間將容器連接到0個或多個網路,此外,還可以在不重新啟動容器的情況下連接和斷開網路中的運行容器,當容器連接到多個網路時,它的外部連接是通過第一個非內部網路提供的,
Bridge network:
是docker中最常見的網路型別,它類似于默認的橋接網路,但是添加了一些新功能,去掉一些舊功能,
可以通過下面的命令創建一個bridge網路:
[root@localhost ~]# docker network create --driver bridge isolated_nw
d219160db427d56bc8dd4b1d7f98534834e13da48da1636d251436a2731187be
查看網路情況:
[root@localhost ~]# docker network inspect isolated_nw
[
{
"Name": "isolated_nw",
"Id": "d219160db427d56bc8dd4b1d7f98534834e13da48da1636d251436a2731187be",
"Created": "2020-10-22T00:18:59.886808362+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
查看網橋:

啟動一個容器然后將其加入新創建的網路:
[root@localhost ~]# docker run -itd --network isolated_nw --name web002 httpd
7201f6f3536b8af1feaf7f99fa347839138b49cf243d33bbf66a4e5ec4dcb05b
[root@localhost ~]# docker network inspect isolated_nw
[
{
"Name": "isolated_nw",
"Id": "d219160db427d56bc8dd4b1d7f98534834e13da48da1636d251436a2731187be",
"Created": "2020-10-22T00:18:59.886808362+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"7201f6f3536b8af1feaf7f99fa347839138b49cf243d33bbf66a4e5ec4dcb05b": {
"Name": "web002",
"EndpointID": "b0aa915664497f50d459f64ce1f5ffd1f46621a046982c89430fa701f1ddf6ff",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
加入你創建的網路中的容器必須在同一個HOST主機上,網路中的每個容器都可以立即與網路中的其他容器通信,然而,網路本身將容器與外部網路隔離開來,

在用戶定義的網橋網路中,不支持linking(連接),可以在這個網路中公開和發布容器埠,也就是expose and publish(暴露埠和公開埠)

注解:external host為外界主機,
如果你想在單一主機上運行一個相對小的網路,使用橋接網路是有效果的,
然而你想創建一個大網路,可以通過Overlay網路來實作,
跨主機Docker容器通信方案:
現有的主要Docker網路方案
1、基于實作方式分類:
1)隧道方案
通過隧道,或者說Overlay Networking的方式:
- Weave:UDP廣播,本機建立新的BR,通過PCAP互通,
- Open vSwitch(OVS):基于VxLan和GRE協議,但是性能方面損失比較嚴重,
- Flannel:UDP廣播,VxLan,
注解:
VxLan:VxLAN(Virtual eXtensible Local Area Network,虛擬擴展局域網)技術很好地解決了現有VLAN技術無法滿足大二層網路需求的問題,VxLAN技術是一種大二層的虛擬網路技術,主要原理是引入一個UDP格式的外層隧道作為資料鏈路層,而原有資料報文內容作為隧道凈荷加以傳輸,由于外層采用了UDP作為傳輸手段,凈荷資料可以輕松地在二三層網路中傳送,VxLAN已成為業界主流的虛擬網路技術之一,IETF正在制定相關標準,
GRE協議:通用路由封裝 (GRE)定義了在任意一種網路層協議上封裝任意一個其它網路層協議的協議,
隧道方案在IaaS層的網路中應用也比較多,大家共識是隨著節點規模的增長復雜度會提升,而且出了網路問題跟蹤起來比較麻煩,大規模群集情況下這是需要考慮的一點,
2)路由方案
通過路由來實作,比較典型的代表有:
- Calico:基于BGP協議的路由方案,支持很細致的ACL控制,對混合云親和度比較高,
- Macvlan:從邏輯和Kernel層來看隔離性和性能最優的方案,基于二層隔離,所以需要二層路由支持,大多數云服務商不支持,所以混合云上比較難以實作,
注解:BGP:(BGP/BGP4:Border Gateway Protocol,邊界網關協議)是一種實作自治系統AS(Autonomous System)之間的路由可達,并選擇最佳路由的距離矢量路由協議,
MP-BGP是對BGP-4進行了擴展,來達到在不同網路中應用的目的,BGP-4原有的訊息機制和路由機制并沒有改變,MP-BGP在IPv6單播網路上的應用稱為BGP4+,在IPv4組播網路上的應用稱為MBGP(Multicast BGP),
AS自治系統:互聯網是一個網路; 它被分解成數十萬個稱為自治系統(AS)的小型網路,這些網路中的每一個本質上都是由單個組織運行的大型路由器池,
自治系統是由單個組織管理的大型網路或網路組,AS可能有許多子網,但都共享相同的路由策略,通常,AS是ISP或具有自己的網路的非常大的組織,以及從該網路到ISP的多個上游連接(這稱為“多宿主網路”),每個AS都分配有自己的自治系統編號(ASN),以便輕松識別它們,
路由方案一般是從3層或者2層實作隔離和跨主機容器互通的,出了問題也很容易排查,
2、基于網路模型分類:
Docker Libnetwork Container Network Model(CNM)陣營
- Docker Swarm Overlay
- Macvlan & IP network drivers
- Calico
- Contiv(from Cisco)
Docker Libnetwork的優勢就是原生,而且和Docker容器生命周期結合緊密;缺點也可以理解為原生,被Docker“綁架”,
Container Network Interface(CNI)陣營
- Kubernetes
- Weave
- Macvlan
- Flannel
- Calico
- Contiv
- Mesos CNI
CNI的優勢是兼容其他容器技術(e.g.rkt)及上層編排系統(Kuberneres & Mesos),而且社區活躍勢頭迅猛,Kuberneres加上CoreOS主推了,缺點是非Docker原生,
從上面的可以看出,有一些第三方的網路方案是同時屬于兩個陣營的,
下面主要介紹了Docker容器平臺中的Libnetwork,Flannel、Calico、Weave這幾種跨主機通信方案,并對各個方法的原理進行闡述,
Libnetwork:
Libnetwork是從1.6版本開始將Docker的網路功能從Docker核心代碼中分離出去,形成一個單獨的庫,Libnetwork的目標是定義一個健壯的容器網路模型,提供一個一致的編程介面和應用程式的網路抽象,
Libnetwork通過插件的形式為Docker提供網路功能,使得用戶可以根據自己的需求實作自己的Driver來提供不同的網路功能,從1.9版本開始,Docker已經實作了基于Libnetwork和Libkv庫的網路模式-多主機Overlay網路,
Libnetwork索要實作的網路模型基本是這樣的:用戶可以創建一個或多個網路(一個網路就是一個網橋或者一個VLAN),一個容器可以加入一個或多個網路,同一個網路中容器可以通信,不同網路中的容器隔離,
Libnetwork實作了一個叫做Container Network Model(CNM)的東西,也就是說希望成為容器的標準網路模型、框架,其中包含了下面幾個概念:

- Sandbox:Sandbox包含容器網路堆疊的配置,包括容器介面,路由表,DNS配置等管理,Linux network namespace是常見的一種Sandbox的實作,Sandbox中包含眾多網路中的若干Endpoint,
- Endpoint:Neutron中和Endpoint相對的概念應該是VNIC,也就是虛擬機的虛擬網卡(也可以看成VIF),Endpoint的常見實作包括veth pair、Openvswitch的internal port當Sandbox要和外界通信的時候就是通過Endpoint連接到外界的,最簡單的情況就是連接到一個Bridge上,
- Network:Network是一組可以互相通信的Endpoint集合,組內Endpoint可以相互通訊,不同組內Endpoint是不能通信的,是完全隔離的,常見的實作包括Linux bridge,Vlan等,
目前已經實作了如下driver:
- Host:主機網路,只用這種網路的容器會使用主機的網路,這種網路對外界是完全開放的,能夠訪問到主機,就能訪問到容器,
- Bridge:橋接網路,這個Driver就是Docker現有網路Bridge模式的實作,除非創建容器的時候指定網路,不然容器就會默認使用橋接網路,屬于這個網路的容器之間可以互相通信,外界想要訪問到這個網路的容器需要使用橋接網路,
- Null:Driver的空實作,類似于Docker容器的None模式,使用這種網路的容器會完全隔離,
- Overlay:Overlay驅動可實作通過Vxlan等重疊網路封裝技術跨越多個主機的網路,目前Docker已經自帶該驅動,
- Remote:Remote驅動包不提供驅動,但提供了融合第三方驅動的介面,
Flannel:
Flannel之前的名字是Rudder,它是由CoreOS團隊針對Kubernetes設計的一個多載網路工具,它的主要思路是:預先留出一個網段,每個主機使用其中一部分,然后每個容器被分配不同的IP;讓所有的容器認為大家在同一個直連網路上,底層通過UDP/VxLan等進行報文的封裝和轉發,
Flannel類似于Weave、VxLAN,提供了一個可配置的虛擬承載網路,Flannel以一個daemon(守護行程)形式運行,負責子網的分配,Flannel使用etcd(類似資料庫)存盤,交換網路配置,狀態等資訊,
Flannel基本原理
Flannel默認使用8285埠作為UDP封裝報文的埠,VxLAN使用8472埠,

1)容器直接使用目標容器的IP訪問,默認通過容器內部的eth0發送出去,
2)報文通過veth pair被發送到vethXXX,
3)vethXXX是直接連接到虛擬交換機docker0的,報文通過虛擬bridge docker0發送出去,
4)查找路由表,外部容器ip的報文都會轉發到flannel0虛擬網卡,這是一個P2P(個人對個人)的虛擬網卡,然后報文就被轉發到監聽在另一端的flanneld,
5)flanneld通過etcd維護了各個節點之間的路由表,把原來的報文UDP封裝一層,通過配置的iface(類似回環lo)發送出去,
6)報文通過主機之間的網路找到目標主機,
7)報文繼續往上,到傳輸層,交給監聽在8285埠的flanneld程式處理,
8)資料被解包,然后發送給flannel0虛擬網卡
9)查找路由表,發現對應容器的報文要交給docker0,
10)docker0找到連接到自己的容器,把報文發送過去,
Calico
Calico是一個純3層的資料中心網路方案,而且無縫集成像Openstack這種IaaS(基礎設施即服務)云架構,能夠提供可控的VM、容器、裸機之間的IP通信,
它基于BPG協議和Linux自己的路由轉發機制,不依賴特殊硬體,沒有使用NAT或Tunnel等技術,能夠方便的部署在物理服務器、虛擬機或者容器環境下,同時它自帶的基于iptables的ACL管理組件非常靈活,能夠滿足比較復雜的安全隔離需求,
Calico在每一個計算節點利用Linux Kernel實作一個高效的VRouter來負責資料轉發,而每個vRouter通過BGP協議負責把自己運行的workload(作業網路)的路由資訊向整個Calico網路內傳播——小規模部署可以直接互聯,大規模下可通過制定的BGP route reflector(公共程式集)來完成,
這樣保證最終所有的workload之間的資料流量都是通過IP路由的方式完成互聯的,
基本原理:

Calico的方案如上圖所示,它把每個作業系統的協議堆疊認為是一個路由器,然后把所有的容器認為是連在這個路由器上網路終端,在路由器之間跑標準的路由協議——BGP的協議,然后讓他們自己去學習這個網路拓撲該如何轉發,所以Calico方案其實是一個純3層的方案,也就是說讓每臺機器的協議堆疊的3層去確保兩個容器、跨主機容器之間的3層連通性,
Calico架構:

結合上面這張圖,我們來過一遍Calico的核心組件:
- Felix:Calico Agent,跑在每臺需要運行Workload的節點上,主要負責配置路由及ACLS(訪問控制串列)等資訊來確保Endpoint(端點)的連通狀態,
- etcd:分布式鍵值存盤,主要負責網路元資料一致性,確保Calico網路狀態的準確性,
- BGP Client(BIRD):主要負責把Felix寫入Kernel的路由資訊分發到當前Calico網路,確保Workload間的通信的有效性,
- BGP Route Reflector(BIRD):大規模部署時使用,摒棄所有節點互聯的mesh(無線網格網路)模式,通過一個或者多個BGP Route Reflector來完成集中式路由分發,
每個節點上會運行兩個主要的程式,一個是它自己的叫Felix,它會監聽ECTD中心的存盤,從它獲取事件,比如說用戶在這臺機器上加了一個IP,或者是分配了一個容器等,接著會在這臺機器上創建出一個容器,并將其網卡、IP、MAC都設定好了,然后在內核的路由表里面寫一條,注明這個IP應該到這張網卡,
bird是一個標準的路由程式,它會從內核里面獲取哪一些IP的路由發生了變化,然后通過標準BGP的路由協議擴散到整個其他的宿主機上,讓外界都知道這個IP在這里,你們路由的時候要到這里來,
由于Calico是一種純三層的實作,因此可以避免與二層方案相關的資料包封裝的操作,中間沒有任何的NAT,沒有任何的Overlay,所以它的轉發效率可能是所有方案中最高的,因為它的包直接走原生TCP/IP的協議堆疊,它的隔離也因為這個堆疊而變得好做,因為TCP/IP協議堆疊是提供了一整套的防火墻的規則,所以它可以通過iptables的規則達到比較復雜的隔離邏輯,
Calico優劣勢:
- Calico優勢
1、網路拓撲直觀易懂,平行式擴展,可擴展型強,
2、容器間網路三層隔離,無需要擔心arp風暴,
3、基于iptable/linux kernel包轉發效率高,損耗低,
4、更容易的變成語言(python)
5、社區活躍,正式版本成熟
- Calico劣勢
1、Calico僅支持TCP、UDP、ICMPandICMPv6協議,如果你想使用L4協議,你只能選擇Flannel,Weave或Docker Overlay Network,
2、Calico沒有加密資料路徑,用不可信網路上的Calico建立覆寫網路時不安全的,
3、沒有IP重疊支持,雖然Calico社區正在開發一個實驗功能,將重疊IPv4包放入IPv6包中,但這只是一個輔助解決方案,并不完全支持技術上的IP重疊,
Weave
Weave是由Zett.io公司開發的,它能夠創建一個虛擬網路,用于連接部署在多臺主機上的Docker容器,這樣容器就像被接入了同一個網路交換機,那些使用網路的應用程式不必去配置埠映射和鏈接等資訊,
外部設備能夠訪問Weaver網路上的應用程式容器所提供的服務,同時已有的內部系統也能夠暴露到應用程式容器上,Weave能夠穿透防火墻并運行在部分鏈接的網路上,另外,Weave的通信支持加密,所以用戶可以從一個不受信任的網路連接到主機,
Weave實作原理:(主機A、B、C運行的容器如圖所示)

容器的網路通訊都通過route服務和網橋轉發,

Weave會在主機上創建一個網橋,每一個容器通過veth pair連接到該網橋上,同時網橋上有個Weave router的容器與之連接,該router會通過連接在網橋上的介面來抓取網路包(該介面作業在Promiscuous混雜模式(網路中的一種術語,是指一臺機器的網卡能夠接受所有經過它的資料流,)),
在每一臺部署Docker的主機(可能是物理機也可能是虛擬機)上都部署有一個W(即Weave router),它本身也可以以一個容器的形式部署,Weave run的時候就可以給每個veth的容器端分配一個IP和相應的掩碼,veth的網橋這端就是Weave router容器,并在Weave launch(發射)的時候分配好IP和掩碼,
Weave網路是由這些Weave routers組成的對等端點(peer)構成,每個對等的一端都有自己的名字,其中包括一個可讀性好的名字用于表示狀態和日志輸出,一個唯一識別符號用于運行中相互區別,即使重啟Docker主機名字也保持不變,這些名字默認是MAC地址,
每個部署了Weave router的主機都需要將TCP和UDP的6783埠的防火墻設定打開,保證Weave router之間控制面流量和資料面流量的通過,控制面由Weave routers之間建立的TCP連接構成,通過它進行握手和拓撲關系資訊的交換通信,這個通信可以被配置為加密通信,而資料面由Weave routers之間建立的UDP連接構成,這些連接大部分都會加密,這些連接都是全雙工的,并且可以穿越防火墻,
Weave優劣勢:
- Weave優勢
1、支持主機間通信加密,
2、支持container動態加入或者剝離網路,
3、支持跨主機多子網通信,
- Weave劣勢
1、只能通過Weave launch或者Weave connect加入Weave網路,
各個方案對比
- Flannel和Overlay方案均使用承載網路,承載網路的優勢和劣勢都是非常明顯的,
優勢:對底層網路依賴較少,不管底層是物理網路還是虛擬網路,對層疊網路的配置管理影響較少;配置簡單,邏輯清晰,易于理解和學習,非常使用與開發測驗對網路性能要求不高的場景,
劣勢:網路封裝是一種傳輸開銷,對網路性能會有影響,不適用于對網路性能要求高的生產場景;由于對底層網路結構缺乏了解,無法做到真正有效的流程工程控制,也會對網路性能產生影響,某些情況下也不能完全做到與下層網路無關,例如隧道封裝會對網路的MTU限制產生影響,
- Calico方案因為沒有隧道封裝的網路開銷,會帶來相對比較高的網路性能,不支持多租戶,由于沒有封裝所有的容器只能通過真實的IP地址來區分自己,這就要求所有租戶的容器統一分配一個地址空間,Calico基于三層轉發的原理對物理架構可能會有一定的要求和侵入性,
- Weave可以穿透防火墻,安全性較高,流量是被加密的,允許主機連接通過一個不被信任的網路,同樣會有承載網路帶來的優缺點,
Docker網路管理命令如下:
- docker network create
- docker network connect
- docker network ls
- docker network rm
- docker network disconnect
- docker network inspect
創建網路:
默認創建的是bridge網路:
[root@localhost ~]# docker network create simple-network
f07ccd0b1cadba30204786dfc7af4faf3ea43e121e3ac799107d29ce8c4f54d3
[root@localhost ~]# docker network inspect simple-network
[
{
"Name": "simple-network",
"Id": "f07ccd0b1cadba30204786dfc7af4faf3ea43e121e3ac799107d29ce8c4f54d3",
"Created": "2020-10-25T17:22:57.666963117+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.19.0.0/16",
"Gateway": "172.19.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
不像bridge網路,直接可以創建,創建Overlay網路需要一些條件:
- 訪問到一個鍵值存盤,支持Consul,Etcd,Zookeeper分布式鍵值存盤
- 與鍵值存盤連接的主機集群
- 在Sware群集中的每個主機上正確配置了引擎的daemon
支持Overlay網路的docker選項:
- --cluster-store
- --cluster-store-opt
- --cluster-advertise
當你創建了一個網路,默認會創建一個不重疊的子網,使用--subnet選項可以直接指定子網路,在bridge網路中只可以指定一個子網路,而在Overlay網路中支持多個子網路,
除了--subnet,還可以指定:--gateway,--ip-range,--aux-address選項,
[root@localhost ~]# docker network create -d overlay \
> --subnet=192.168.22.0/16 \
> --subnet=192.170.22.0/16 \
> --gateway=192.168.22.100 \
> --gateway=192.170.22.100 \
> --ip-range=192.168.23.0/24 \
> --aux-address="my-router=192.168.23.5" --aux-address="my-switch=192.168.23.6" \
> --aux-address="my-printer=192.170.23.5" --aux-address="my-nas=192.170.23.6" \
> my-multihost-network
注意:以上是示例,告訴怎么去配置Overlay網路,請在Docker swarm中使用,單獨使用會報錯,錯誤資訊如下:
Error response from daemon: This node is not a swarm manager. Use "docker swarm init" or "docker swarm join" to connect this node to swarm and try again.
(守護行程的錯誤回應:此節點不是群集管理器,使用“docker swarm init”或“docker swarm join”將此節點連接到swarm,然后重試,)
要確保子網不會重疊,否則,網路會創建失敗并回傳錯誤,
創建自定義網路時,可以向驅動程式傳遞附加選項,bridge驅動接受以下選項:
| Option(選項) | Equivalent(等效) | Description(描述) |
| com.docker.network.bridge.name | - | bridge name to be used when creating the Linux bridge (在創建Linux網橋時使用的網橋名) |
| com.docker.network.bridge.enable_ip_masquerade | --ip-masq | Enable IP masquerading(啟用IP偽裝) |
| com.docker.network.bridge.enable_icc | --icc | Enable or disable inter container connectivity(啟用或禁用容器間連接) |
| com.docker.network.bridge.host_binding_ipv4 | --ip | Default IP when binding container ports(系結容器埠時的默認IP) |
| com.docker.network.driver.mtu | --mtu | Set the containers network MTU(設定容器網路的MTU) |
com.docker.network.driver.mtu這個選項也支持Overlay驅動,
下面的引數在使用docker network create命令時,可以傳遞給任意網路驅動,
| Argument(論點) | Equivalent(等效) | Description(描述) |
| --internal(內部) | - | Restrice external access to the network(限制外部訪問網路) |
| --ipv6 | --ipv6 | Enable IPv6 networking(啟用ipv6網路) |
例如:
[root@localhost ~]# docker network create -o "com.docker.network.bridge.host_binding_ipv4"="192.168.22.7" my-network
8a26ce23bc9e44f3eec4f89e98f0dbbbf660366cdf3eda70ba0de7c9812efd33
[root@localhost ~]# docker network inspect my-network
[
{
"Name": "my-network",
"Id": "8a26ce23bc9e44f3eec4f89e98f0dbbbf660366cdf3eda70ba0de7c9812efd33",
"Created": "2020-10-25T18:17:57.426584326+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.20.0.0/16",
"Gateway": "172.20.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {
"com.docker.network.bridge.host_binding_ipv4": "192.168.22.7"
},
"Labels": {}
}
]
啟動一個容器并發布埠:可以看到系結的地址,
[root@localhost ~]# docker run -itd -P --network my-network --name web001 httpd
f45cfdfdc1d0cc801fc3df49fb7893311d1d7405fbbead3a461b6145af98a42f
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f45cfdfdc1d0 httpd "httpd-foreground" 11 seconds ago Up 9 seconds 192.168.22.7:32769->80/tcp web001
7201f6f3536b httpd "httpd-foreground" 3 days ago Up 3 days 80/tcp web002
0c90b2488372 httpd "httpd-foreground" 3 days ago Up 3 days 0.0.0.0:8000->80/tcp web-test002
b7f279a988ec httpd "httpd-foreground" 3 days ago Up 3 days 192.168.22.7:32768->80/tcp webserver
1714a06a13da httpd "httpd-foreground" 3 days ago Up 3 days 192.168.22.7:80->80/tcp, 192.168.22.7:10112->22/tcp dazzling_lewin
連接到容器:
可以連接已存在的容器到一個或者多個網路中,一個容器可以連接到多個不同網路驅動的網路中,
當連接一旦建立,容器便可以和其他的容器通訊,通過IP或者容器名稱,
對于支持多個主機連接的Overlay網路或者自定義插件,連接到同一個多主機網路的不同主機上的容器,也可以用這種方式通信,
基本容器網路示例:
1、首先,創建和運行兩個容器:container1和container2
[root@localhost ~]# docker run -itd --name container1 centos /bin/bash
d9d0c1fdf76aba061bbdbbc5b17551db48c87d8ec230dbd264b7f50ba15bad81
[root@localhost ~]# docker run -itd --name container2 centos /bin/bash
e933d14177b13c8319137b090470ca1196327e9b2733e0380445b801f2a18873
2、創建一個用戶自定義網路isolated_nw,是bridge網路
[root@localhost ~]# docker network create -d bridge --subnet 172.25.0.0/16 --gateway 172.25.0.1 isolated_nw
91aced71d72b3a6e9efcaf0d38d2c013f298db1fa68e88792052140baf272976
3、連接container2容器到這個新創建網路,并inspace這個網路,檢查網路的連接,
[root@localhost ~]# docker network connect isolated_nw container2
[root@localhost ~]# docker network inspect isolated_nw
[
{
"Name": "isolated_nw",
"Id": "91aced71d72b3a6e9efcaf0d38d2c013f298db1fa68e88792052140baf272976",
"Created": "2020-10-25T19:08:54.585910719+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.25.0.0/16",
"Gateway": "172.25.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"70383c4821843facc8d3feb416512b49a335ccadd98f5d92cc939a302afaf029": {
"Name": "container2",
"EndpointID": "71d8e71423a4096d9b2163fd149753c8e446f8e2ef9693e1d1c955acf8c76d4e",
"MacAddress": "02:42:ac:14:00:02",
"IPv4Address": "172.25.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
4、創建容器container3,并分配一個固定IP172.25.3.3
[root@localhost ~]# docker run -itd --name container3 --network isolated_nw --ip=172.25.3.3 centos /bin/bash
f2379d55bf81ebf5231175bf901ac7f962482875d89703e6649b0db31688cc99
使用--ip和--ip6引數指定IP地址,如果是用戶定義的網路,在容器重啟的時候,會保持有效,如果不是用戶定義的網路,分配的IP地址是不會保持有效的,
5、檢查container3的網路資源,
[root@localhost ~]# docker inspect --format '{{json .NetworkSettings.Networks}}' container3 | python -m json.tool
{
"isolated_nw": {
"Aliases": [
"f2379d55bf81"
],
"DriverOpts": null,
"EndpointID": "53d30f41d9304c4520bf24d301ddc9945d49ac3784ed88c7fbb13c93cb3220f1",
"Gateway": "172.25.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAMConfig": {
"IPv4Address": "172.25.3.3"
},
"IPAddress": "172.25.3.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"Links": null,
"MacAddress": "02:42:ac:19:03:03",
"NetworkID": "019293fb7cb0aaab3957de99af1a8bb8a651cbb14abfefbf756c25c44b0a6c18"
}
}
6、檢查container2容器的網路資源:
[root@localhost ~]# docker inspect --format '{{json .NetworkSettings.Networks}}' containet2 | python -m json.tool
{
"bridge": {
"Aliases": null,
"DriverOpts": null,
"EndpointID": "c17697970b44a7ef722992f2cd6b6792ad7b00958eab7c68ea1f532516946582",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAMConfig": null,
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"Links": null,
"MacAddress": "02:42:ac:11:00:03",
"NetworkID": "c013430953bd85703126b0ad85811edf4432a43036585fb9ee3788a097a67adb"
},
"isolated_nw": {
"Aliases": [
"816ece7dc447"
],
"DriverOpts": {},
"EndpointID": "5978aadc59d67bc64a057b1d47a32de64558a7b59d73e813a8e56cb33bf7d691",
"Gateway": "172.25.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAMConfig": {},
"IPAddress": "172.25.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"Links": null,
"MacAddress": "02:42:ac:19:00:02",
"NetworkID": "019293fb7cb0aaab3957de99af1a8bb8a651cbb14abfefbf756c25c44b0a6c18"
}
}
現在container2屬于兩個網路,

7、進入容器container2,并嘗試和container3及container1通信,
[root@localhost ~]# docker exec -it container2 /bin/bash

有兩個IP,網關是連接到的第一個玩過的網關,
docker內嵌了DNS服務,意思是連接到同一個網路的容器,可以使用容器名進行通信,

默認的bridge網路是不可以使用名稱通信的,IP可以,

如果想讓默認網路中,也可以使用容器名進行通信呢?
使用link的特性,這是唯一推薦會用link的場景,應該使用自定義的網路來替代它的,
在默認網路中使用link增加以下特性:
- 決議容器名到IP地址
- 定義網路別名
- --link=CONTAINER-NAME:ALIAS
- 增強網路連接的安全性
- 環境變數注入
例如:
[root@localhost ~]# docker run -itd --name container4 --link containet1:c1 centos /bin/bash
84fadca13e7f1d2b1a1c54adcda2c69b9a97baf61ea1463e0c7b635a7df3de56

(上圖的容器名稱寫錯了,按照正常的容器英文名字寫container)
取消連接:
[root@localhost ~]# docker network disconnect isolated_nw containet2
[root@localhost ~]# docker network disconnect isolated_nw container3
洗掉網路:

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/229119.html
標籤:其他
