docker 網(wǎng)絡(luò)配置

本文主要是介紹docker默認(rèn)的網(wǎng)絡(luò)行為,包含創(chuàng)建的默認(rèn)網(wǎng)絡(luò)類型以及如何創(chuàng)建用戶自定義網(wǎng)絡(luò),也會介紹如何在單一主機或者跨主機集群上創(chuàng)建網(wǎng)絡(luò)的資源需求。

默認(rèn)網(wǎng)絡(luò)

當(dāng)你安裝了docker,它自動創(chuàng)建了3個網(wǎng)絡(luò),可以使用docker network命令來查看


1.png

這三個網(wǎng)絡(luò)被docker內(nèi)建。當(dāng)你運行一個容器的時候,可以使用--network參數(shù)來指定
你的容器連接到哪一個網(wǎng)絡(luò)。

1、bridge網(wǎng)絡(luò)

默認(rèn)連接到docker0這個網(wǎng)橋上。

2.png

注:brctl 命令在centos中可以使用yum install bridge-utils 來安裝

啟動并運行一個容器


3.png

可以看到test1容器已經(jīng)獲取了一個地址172.17.0.2,和主機的docker0接口地址在同一網(wǎng)絡(luò),并將主機的docker0接口地址設(shè)置為了網(wǎng)關(guān)。


4.png

在物理主機上,查看網(wǎng)橋docker0,可以看到已經(jīng)多了一個接口
5.png

Docker 容器默認(rèn)使用 bridge 模式的網(wǎng)絡(luò)。其特點如下:

  • 使用一個 linux bridge,默認(rèn)為 docker0
  • 使用 veth 對,一頭在容器的網(wǎng)絡(luò) namespace 中,一頭在 docker0 上
  • 該模式下Docker Container不具有一個公有IP,因為宿主機的IP地址與vethpair的 IP地址不在同一個網(wǎng)段內(nèi)
  • Docker采用 NAT 方式,將容器內(nèi)部的服務(wù)監(jiān)聽的端口與宿主機的某一個端口port 進(jìn)行“綁定”,使得宿主機以外的世界可以主動將網(wǎng)絡(luò)報文發(fā)送至容器內(nèi)部
  • 外界訪問容器內(nèi)的服務(wù)時,需要訪問宿主機的 IP 以及宿主機的端口 port
  • NAT 模式由于是在三層網(wǎng)絡(luò)上的實現(xiàn)手段,故肯定會影響網(wǎng)絡(luò)的傳輸效率。
  • 容器擁有獨立、隔離的網(wǎng)絡(luò)棧;讓容器和宿主機以外的世界通過NAT建立通信
效果是這樣的:
6.png
示意圖如下:

7.png

在物理主機上查看iptables的nat表,可以看到在POSTROUTING鏈中做了地址偽裝:MASQUERADE動作,這樣容器就可以通過源地址轉(zhuǎn)換NAT訪問外部網(wǎng)絡(luò)了。
通過iptables -t nat -vnL命令查看到:
8.png

可以使用docker network inspect bridge命令來查看bridge網(wǎng)絡(luò)情況:

[root@docker01 sysctl.d]# docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id":
"2d82fcfaa00883ff4f6637b7fa199489dc9a2332a73b6f0d306625f72bb5979b",
        "Created": "2018-01-03T11:16:46.249349532+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": {
           
"976c6814378e8bb27c209ce711434a70334d12a5ef13e965320501f7586f65f3": {
                "Name": "test1",
                "EndpointID":
"c3ed6dda70d048580b061812b4f53f94a4a4c1a90146897c7b0e7c71df967d57",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "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網(wǎng)絡(luò)模式:

網(wǎng)絡(luò)模式為 none,即不為Docker容器構(gòu)造任何網(wǎng)絡(luò)環(huán)境,不會為容器創(chuàng)建網(wǎng)絡(luò)接口,一旦Docker容器采用了none網(wǎng)絡(luò)模式,那么容器內(nèi)部就只能使用loopback網(wǎng)絡(luò)設(shè)備,不會再有其他的網(wǎng)絡(luò)資源。Docker Container的none網(wǎng)絡(luò)模式意味著不給該容器創(chuàng)建任何網(wǎng)絡(luò)環(huán)境,容器只能使用127.0.0.1的本機網(wǎng)絡(luò)。

啟動一個容器,設(shè)為none網(wǎng)絡(luò)

docker run -it -d --network none --name test2 centos7:new002 /bin/bash
進(jìn)入容器,查看網(wǎng)絡(luò)情況:

9.png

3、host網(wǎng)絡(luò)模式

Host模式并沒有為容器創(chuàng)建一個隔離的網(wǎng)絡(luò)環(huán)境。而之所以稱之為host模式,是因為該模式下的Docker 容器會和host宿主機共享同一個網(wǎng)絡(luò)namespace,故Docker Container可以和宿主機一樣,使用宿主機的eth0,實現(xiàn)和外界的通信。換言之,Docker Container的IP地址即為宿主機 eth0的IP地址。

其特點包括:
  • 這種模式下的容器沒有隔離的 network namespace
  • 容器的 IP 地址同 Docker host 的 IP 地址
  • 需要注意容器中服務(wù)的端口號不能與 Docker host 上已經(jīng)使用的端口號相沖突
  • host 模式能夠和其它模式共存
    示意圖:


    1.png

    例如,我們在192.168.1.102/24 的機器上用 host 模式啟動一個含有 web 應(yīng)用的 Docker容器,監(jiān)聽 tcp 80 端口。當(dāng)我們在容器中執(zhí)行任何類似 ifconfig 命令查看網(wǎng)絡(luò)環(huán)境時,看到的都是宿主機上的信息。而外界訪問容器中的應(yīng)用,則直接使用192.168.1.102:80 即可,不用任何 NAT 轉(zhuǎn)換,就如直接跑在宿主機中一樣。但是,容器的其他方面,如文件系
    統(tǒng)、進(jìn)程列表等還是和宿主機隔離的。

啟動容器前,查看物理主機的httpd進(jìn)程


2.png

啟動一個容器:

docker run -itd --privileged --name test7 --network host centos7:new002 init
3.png

進(jìn)入容器,安裝httpd服務(wù),并啟動

[root@docker01 ~]# docker exec -it test7 /bin/bash
[root@docker01 /]# yum install httpd -y
[root@docker01 /]# systemctl start httpd
[root@docker01 /]# echo "test docker host network" > /var/www/html/index.html

退出容器,再次查看httpd進(jìn)程


4.png

訪問主機的80端口,可以訪問到容器test7中的網(wǎng)站服務(wù):


5.png

注意防火墻:
6.png

4、container 模式

這個模式指定新創(chuàng)建的容器和已經(jīng)存在的一個容器共享一個 Network Namespace,而不是和宿主機共享。新創(chuàng)建的容器不會創(chuàng)建自己的網(wǎng)卡,配置自己的 IP,而是和一個指定的容器共享 IP、端口范圍等。同樣,兩個容器除了網(wǎng)絡(luò)方面,其他的如文件系統(tǒng)、進(jìn)程列表等還是隔離的。兩個容器的進(jìn)程可以通過 lo 網(wǎng)卡設(shè)備通信。

Container 網(wǎng)絡(luò)模式是 Docker 中一種較為特別的網(wǎng)絡(luò)的模式。這兩個容器之間不存在網(wǎng)絡(luò)隔離,而這兩個容器又與宿主機以及除此之外其他的容器存在網(wǎng)絡(luò)隔離。
注意:因為此時兩個容器要共享一個network namespace,因此需要注意端口沖突情況,否則第二個容器將無法被啟動。
示意圖:

7.png

運行一個容器:查看容器的IP
8.png

啟動另外一個容器,使用test1容器的網(wǎng)絡(luò)
docker run -it -d --name test8 --network container:test1 centos7:new002 /bin/bash
9.png

進(jìn)入容器test8,查看網(wǎng)絡(luò)情況,可以看到兩個容器地址信息相同,是共享的
1.png

通過上面的docker網(wǎng)絡(luò)學(xué)習(xí),已經(jīng)可以實現(xiàn)容器和外部網(wǎng)絡(luò)通信了,但是如何讓外部網(wǎng)絡(luò)來訪問容器呢?
外部訪問容器:
容器中可以運行一些網(wǎng)絡(luò)應(yīng)用,要讓外部也可以訪問這些應(yīng)用,可以通過 -P 或 -p 參數(shù)來指定端口映射。
當(dāng)使用–P(大寫)標(biāo)記時,Docker 會隨機映射一個隨機的端口到內(nèi)部容器開放的網(wǎng)絡(luò)端口。
注:-P使用時需要指定--expose選項或dockerfile中用expose指令容器要暴露的端口,指定需要對外提供服務(wù)的端口

從docker hub下載一個httpd鏡像

[root@docker01 ~]# docker pull httpd

2.png

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

可以看到容器的80端口被隨機映射到主機的32768端口
訪問主機IP地址的32768端口,就可以訪問到容器的httpd服務(wù)
4.png

-p(小寫)則可以指定要映射的端口,并且,在一個指定端口上只可以綁定一個容器。支持的格式有ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort

注意:
?容器有自己的內(nèi)部網(wǎng)絡(luò)和 ip 地址(使用  docker inspect  可以獲取所有的變量。)
? -p 標(biāo)記可以多次使用來綁定多個端口

5.png

可以看到主機的8000端口已經(jīng)和容器web-test002的80端口做了映射
訪問主機的8000端口
image.png

映射到指定地址的指定端口
可以使用 ip:hostPort:containerPort 格式,指定映射使用一個特定地址,比如宿主機網(wǎng)卡
配置的一個地址192.168.1.102
1.png

映射到指定地址的任意端口
使用 ip::containerPort 綁定192.168.1.102的任意端口到容器的80端口,本地主機會自動
分配一個口。--name為啟動的容器指定一個容器名。
2.png

注:還可以使用 udp 標(biāo)記來指定 udp 端口

# docker run -d -p 127.0.0.1:5000:5000/udp –name db4 commit:v1

查看映射端口配置
使用 docker port 來查看當(dāng)前映射的端口配置,也可以查看到綁定的地址


3.png

docker端口映射實質(zhì)上是在iptables 的nat表中添加了DNAT規(guī)則


4.png

用戶定義網(wǎng)絡(luò)(User-defined networks)

建議使用用戶定義的橋接網(wǎng)絡(luò)來控制容器之間彼此通信,并啟用容器名稱和IP地址的自動DNS解析,docker默認(rèn)提供了用于創(chuàng)建這些網(wǎng)絡(luò)的默認(rèn)網(wǎng)絡(luò)驅(qū)動程序,你能創(chuàng)建:
  • bridge network

  • overlay network

  • MACVLAN network

  • network plugin

  • remote network

    您可以根據(jù)需要創(chuàng)建盡可能多的網(wǎng)絡(luò),并且可以在任何給定的時間將容器連接到0個或多個網(wǎng)絡(luò)。此外,還可以在不重新啟動容器的情況下連接和斷開網(wǎng)絡(luò)中的運行容器。當(dāng)容器連接到多個網(wǎng)絡(luò)時,它的外部連接是通過第一個非內(nèi)部網(wǎng)絡(luò)提供的。
    Bridge networks
    是docker中最常見的網(wǎng)絡(luò)類型,它類似與默認(rèn)的橋接網(wǎng)絡(luò),但是添加了一些新功能,去掉了一些舊功能。
    可以通過下面的命令創(chuàng)建一個bridge網(wǎng)絡(luò)

docker network create --driver bridge isolated_nw

查看網(wǎng)絡(luò)情況:

[root@docker01 ~]# docker network inspect isolated_nw
[
    {
        "Name": "isolated_nw",
        "Id":
"61ed2c0fb3befae89f9f3642f46b8702578eb77d331593cc337cb7f601ada41c",
        "Created": "2018-01-04T10:28:30.080659461+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": {
           
"810bf5548fdf263ced0f9b358cbbb08bf1438201578472ae74101a36bebfcf34": {
                "Name": "web001",
                "EndpointID":
"051f35c6dd332a3013f1d5e6bb5afd2d5aaacf16b9ed724d6f25c722a3bbea7e",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
 [root@docker01 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
519fb0569cc3        bridge              bridge              local
731204303d51        host                host                local
61ed2c0fb3be        isolated_nw         bridge              local
6f69db181323        none                null                local

啟動一個容器然后將其加入新創(chuàng)建的網(wǎng)絡(luò):

[root@docker01 ~]# docker run -itd --network isolated_nw --name web002 httpd
77c9bb8d8414d4cf9444445916f07b5f29dcd5ff8ab768089e365370c4614872
[root@docker01 ~]# docker network inspect isolated_nw
[
    {
        "Name": "isolated_nw",
        "Id":
"61ed2c0fb3befae89f9f3642f46b8702578eb77d331593cc337cb7f601ada41c",
        "Created": "2018-01-04T10:28:30.080659461+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": {
           
"77c9bb8d8414d4cf9444445916f07b5f29dcd5ff8ab768089e365370c4614872": {
                "Name": "web002",
                "EndpointID":
"c1c1bf1f40890b28850b4b7d80d376ffc143e88259b8ffb18e7612caa93e5a22",
                "MacAddress": "02:42:ac:12:00:03",
                "IPv4Address": "172.18.0.3/16",
                "IPv6Address": ""
            },
           
"810bf5548fdf263ced0f9b358cbbb08bf1438201578472ae74101a36bebfcf34": {
                "Name": "web001",
                "EndpointID":
"051f35c6dd332a3013f1d5e6bb5afd2d5aaacf16b9ed724d6f25c722a3bbea7e",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

加入你創(chuàng)建的網(wǎng)絡(luò)中的容器必須在同一個HOST主機上,網(wǎng)絡(luò)中的每個容器都可以立即與網(wǎng)絡(luò)中的其他容器通信。然而,網(wǎng)絡(luò)本身將容器與外部網(wǎng)絡(luò)隔離開來。


5.png

在用戶定義的網(wǎng)橋網(wǎng)絡(luò)中,不支持linking??梢栽谶@個網(wǎng)絡(luò)中公開和發(fā)布容器端口,也就是expose and publish 。


6.png

如果你想在單一主機上運行一個相對小的網(wǎng)絡(luò),使用橋接網(wǎng)絡(luò)是有效果的。
然而你想創(chuàng)建一個大網(wǎng)絡(luò),可以通過overlay 網(wǎng)絡(luò)來實現(xiàn)。

跨主機docker容器通信方案介紹:

現(xiàn)有的主要Docker網(wǎng)絡(luò)方案

基于實現(xiàn)方式分類:
隧道方案

通過隧道,或者說Overlay Networking的方式:

  • Weave:UDP廣播,本機建立新的BR,通過PCAP互通。
  • Open vSwitch(OVS):基于VxLAN和GRE協(xié)議,但是性能方面損失比較嚴(yán)重。
  • Flannel:UDP廣播,VxLan。
    隧道方案在IaaS層的網(wǎng)絡(luò)中應(yīng)用也比較多,大家共識是隨著節(jié)點規(guī)模的增長復(fù)雜度會提升,而且出了網(wǎng)絡(luò)問題跟蹤起來比較麻煩,大規(guī)模集群情況下這是需要考慮的一個點。
路由方案

通過路由來實現(xiàn),比較典型的代表有:

  • Calico:基于BGP協(xié)議的路由方案,支持很細(xì)致的ACL控制,對混合云親和度比較高。
  • Macvlan:從邏輯和Kernel層來看隔離性和性能最優(yōu)的方案,基于二層隔離,所以需要二層路由器支持,大多數(shù)云服務(wù)商不支持,所以混合云上比較難以實現(xiàn)。

路由方案一般是從3層或者2層實現(xiàn)隔離和跨主機容器互通的,出了問題也很容易排查。

基于網(wǎng)絡(luò)模型分類

Docker Libnetwork Container Network Model(CNM)陣營

  • Docker Swarm overlay
  • Macvlan & IP network drivers
  • Calico
  • Contiv(from Cisco)
    Docker Libnetwork的優(yōu)勢就是原生,而且和Docker容器生命周期結(jié)合緊密;缺點也可以理解為是原生,被Docker“綁架”。

Container Network Interface(CNI)陣營

  • Kubernetes
  • Weave
  • Macvlan
  • Flannel
  • Calico
  • Contiv
  • Mesos CNI
    CNI的優(yōu)勢是兼容其他容器技術(shù)(e.g. rkt)及上層編排系統(tǒng)(Kuberneres & Mesos),而且社區(qū)活躍勢頭迅猛,Kubernetes加上CoreOS主推;缺點是非Docker原生。
    從上的可以看出,有一些第三方的網(wǎng)絡(luò)方案是同時屬于兩個陣營的。
    下面主要介紹了Docker容器平臺中的libnetwork,flannel,calico,weave這幾種跨主機通信方案,并對各個方案的原理進(jìn)行闡述。
Libnetwork

Libnetwork是從1.6版本開始將Docker的網(wǎng)絡(luò)功能從Docker核心代碼中分離出去,形成一個單獨的庫。Libnetwork的目標(biāo)是定義一個健壯的容器網(wǎng)絡(luò)模型,提供一個一致的編程接口和應(yīng)用程序的網(wǎng)絡(luò)抽象。

Libnetwork通過插件的形式為Docker提供網(wǎng)絡(luò)功能,使得用戶可以根據(jù)自己的需求實現(xiàn)自己的Driver來提供不同的網(wǎng)絡(luò)功能。從1.9版本開始,docker已經(jīng)實現(xiàn)了基于Libnetwork和libkv庫的網(wǎng)絡(luò)模式-多主機的Overlay網(wǎng)絡(luò)。

Libnetwork所要實現(xiàn)的網(wǎng)絡(luò)模型基本是這樣的:用戶可以創(chuàng)建一個或多個網(wǎng)絡(luò)(一個網(wǎng)絡(luò)就是一個網(wǎng)橋或者一個VLAN),一個容器可以加入一個或多個網(wǎng)絡(luò)。 同一個網(wǎng)絡(luò)中容器可以通信,不同網(wǎng)絡(luò)中的容器隔離。

Libnetwork實現(xiàn)了一個叫做Container Network Model (CNM)的東西,也就是說希望成為容器的標(biāo)準(zhǔn)網(wǎng)絡(luò)模型、框架。其包含了下面幾個概念:


7.png
  • Sandbox。Sandbox包含容器網(wǎng)絡(luò)棧的配置,包括容器接口,路由表,DNS配置等的管理。 linux network namespace是常見的一種sandbox的實現(xiàn)。Sandbox中包含眾多網(wǎng)絡(luò)中的若干Endpoint。
  • Endpoint。Neutron中和Endpoint相對的概念應(yīng)該是VNIC,也就是虛擬機的虛擬網(wǎng)卡(也可以看成是VIF)。Endpoint的常見實現(xiàn)包括veth pair、Openvswitch的internal port。當(dāng)Sandbox要和外界通信的時候就是通過Endpoint連接到外界的,最簡單的情況就是連接到一個Bridge上。
  • Network。Network是一組可以互相通信的Endpoints集合,組內(nèi)endpoint可以相互通訊。不同組內(nèi)endpoint是不能通迅的,是完全隔離的。常見的實現(xiàn)包括linux bridge,vlan等。

目前已經(jīng)實現(xiàn)了如下Driver:

  • Host:主機網(wǎng)絡(luò),只用這種網(wǎng)絡(luò)的容器會使用主機的網(wǎng)絡(luò),這種網(wǎng)絡(luò)對外界是完全開放的,能夠訪問到主機,就能訪問到容器。
  • Bridge:橋接網(wǎng)絡(luò),這個Driver就是Docker現(xiàn)有網(wǎng)絡(luò)Bridge模式的實現(xiàn)。除非創(chuàng)建容器的時候指定網(wǎng)絡(luò),不然容器就會默認(rèn)的使用橋接網(wǎng)絡(luò)。屬于這個網(wǎng)絡(luò)的容器之間可以相互通信,外界想要訪問到這個網(wǎng)絡(luò)的容器需使用橋接網(wǎng)絡(luò)。
  • Null: Driver的空實現(xiàn),類似于Docker容器的None模式。使用這種網(wǎng)絡(luò)的容器會完全隔離。
  • Overlay: Overlay驅(qū)動可以實現(xiàn)通過vxlan等重疊網(wǎng)絡(luò)封裝技術(shù)跨越多個主機的網(wǎng)絡(luò),目前Docker已經(jīng)自帶該驅(qū)動。
  • Remote:Remote驅(qū)動包不提供驅(qū)動,但提供了融合第三方驅(qū)動的接口。
Flannel

Flannel之前的名字是Rudder,它是由CoreOS團隊針對Kubernetes設(shè)計的一個重載網(wǎng)絡(luò)工具,它的主要思路是:預(yù)先留出一個網(wǎng)段,每個主機使用其中一部分,然后每個容器被分配不同的ip;讓所有的容器認(rèn)為大家在同一個直連的網(wǎng)絡(luò),底層通過UDP/VxLAN等進(jìn)行報文的封裝和轉(zhuǎn)發(fā)。

Flannel類似于weave、vxlan,提供了一個可配置的虛擬承載網(wǎng)絡(luò)。Flannel以一個daemon形式運行,負(fù)責(zé)子網(wǎng)的分配,flannel使用etcd存儲、交換網(wǎng)絡(luò)配置、狀態(tài)等信息。

flannel基本原理

flannel默認(rèn)使用8285端口作為UDP封裝報文的端口,VxLan使用8472端口。


8.png
  1. 容器直接使用目標(biāo)容器的ip訪問,默認(rèn)通過容器內(nèi)部的eth0發(fā)送出去。
  2. 報文通過veth pair被發(fā)送到vethXXX。
  3. vethXXX是直接連接到虛擬交換機docker0的,報文通過虛擬bridge docker0發(fā)送出去。
  4. 查找路由表,外部容器ip的報文都會轉(zhuǎn)發(fā)到flannel0虛擬網(wǎng)卡,這是一個P2P的虛擬網(wǎng)卡,然后報文就被轉(zhuǎn)發(fā)到監(jiān)聽在另一端的flanneld。
  5. flanneld通過etcd維護(hù)了各個節(jié)點之間的路由表,把原來的報文UDP封裝一層,通過配置的iface發(fā)送出去。
  6. 報文通過主機之間的網(wǎng)絡(luò)找到目標(biāo)主機。
  7. 報文繼續(xù)往上,到傳輸層,交給監(jiān)聽在8285端口的flanneld程序處理。
  8. 數(shù)據(jù)被解包,然后發(fā)送給flannel0虛擬網(wǎng)卡。
  9. 查找路由表,發(fā)現(xiàn)對應(yīng)容器的報文要交給docker0。
  10. docker0找到連到自己的容器,把報文發(fā)送過去。
Calico

Calico是一個純3層的數(shù)據(jù)中心網(wǎng)絡(luò)方案,而且無縫集成像OpenStack這種IaaS云架構(gòu),能夠提供可控的VM、容器、裸機之間的IP通信。

它基于BPG協(xié)議和Linux自己的路由轉(zhuǎn)發(fā)機制,不依賴特殊硬件,沒有使用NAT或Tunnel等技術(shù)。能夠方便的部署在物理服務(wù)器、虛擬機或者容器環(huán)境下。同時它自帶的基于Iptables的ACL管理組件非常靈活,能夠滿足比較復(fù)雜的安全隔離需求。

Calico在每一個計算節(jié)點利用Linux Kernel實現(xiàn)了一個高效的vRouter來負(fù)責(zé)數(shù)據(jù)轉(zhuǎn)發(fā),而每個vRouter通過BGP協(xié)議負(fù)責(zé)把自己上運行的workload的路由信息向整個Calico網(wǎng)絡(luò)內(nèi)傳播—小規(guī)模部署可以直接互聯(lián),大規(guī)模下可通過指定的BGP route reflector來完成。

這樣保證最終所有的workload之間的數(shù)據(jù)流量都是通過IP路由的方式完成互聯(lián)的。

基本原理
9.png

Calico的方案如上圖所示。它把每個操作系統(tǒng)的協(xié)議棧認(rèn)為是一個路由器,然后把所有的容
器認(rèn)為是連在這個路由器上的網(wǎng)絡(luò)終端,在路由器之間跑標(biāo)準(zhǔn)的路由協(xié)議—BGP的協(xié)議,然
后讓它們自己去學(xué)習(xí)這個網(wǎng)絡(luò)拓?fù)湓撊绾无D(zhuǎn)發(fā)。所以Calico方案其實是一個純?nèi)龑拥姆桨福?br> 也就是說讓每臺機器的協(xié)議棧的三層去確保兩個容器,跨主機容器之間的三層連通性。

Calico架構(gòu)
10.png

結(jié)合上面這張圖,我們來過一遍Calico的核心組件:

  • Felix:Calico Agent,跑在每臺需要運行Workload的節(jié)點上,主要負(fù)責(zé)配置路由及ACLS等信息來確保Endpoint的連通狀態(tài)。
  • etcd:分布式鍵值存儲,主要負(fù)責(zé)網(wǎng)絡(luò)元數(shù)據(jù)一致性,確保Calico網(wǎng)絡(luò)狀態(tài)的準(zhǔn)確性。
  • BGP Client(BIRD): 主要負(fù)責(zé)把Felix寫入Kernel的路由信息分發(fā)到當(dāng)前Calico網(wǎng)絡(luò),確保Workload間的通信的有效性。
  • BGP Route Reflector(BIRD):大規(guī)模部署時使用,摒棄所有節(jié)點互聯(lián)的mesh模式,通過一個或者多個BGP Route Reflector來完成集中式的路由分發(fā)。

每個節(jié)點上會運行兩個主要的程序,一個是它自己的叫Felix,它會監(jiān)聽ECTD中心的存儲,從它獲取事件,比如說用戶在這臺機器上加了一個IP,或者是分配了一個容器等。接著會在這臺機器上創(chuàng)建出一個容器,并將其網(wǎng)卡、IP、MAC都設(shè)置好,然后在內(nèi)核的路由表里面寫一條,注明這個IP應(yīng)該到這張網(wǎng)卡。

bird是一個標(biāo)準(zhǔn)的路由程序,它會從內(nèi)核里面獲取哪一些IP的路由發(fā)生了變化,然后通過標(biāo)準(zhǔn)BGP的路由協(xié)議擴散到整個其他的宿主機上,讓外界都知道這個IP在這里,你們路由的時候得到這里來。

由于Calico是一種純?nèi)龑拥膶崿F(xiàn),因此可以避免與二層方案相關(guān)的數(shù)據(jù)包封裝的操作,中間沒有任何的NAT,沒有任何的overlay,所以它的轉(zhuǎn)發(fā)效率可能是所有方案中最高的,因為它的包直接走原生TCP/IP的協(xié)議棧,它的隔離也因為這個棧而變得好做。因為TCP/IP的協(xié)議棧提供了一整套的防火墻的規(guī)則,所以它可以通過IPTABLES的規(guī)則達(dá)到比較復(fù)雜的隔離邏輯。

Calico優(yōu)劣勢

  • Calico的優(yōu)勢
  1. 網(wǎng)絡(luò)拓?fù)渲庇^易懂,平行式擴展,可擴展性強
  2. 容器間網(wǎng)絡(luò)三層隔離,無需要擔(dān)心arp風(fēng)暴
  3. 基于iptable/linux kernel包轉(zhuǎn)發(fā)效率高,損耗低
  4. 更容易的編程語言(python)
  5. 社區(qū)活躍,正式版本較成熟
  • Calico的劣勢
  1. calico僅支持TCP, UDP, ICMP andICMPv6協(xié)議,如果你想使用L4協(xié)議,你只能選擇Flannel,Weave或Docker Overlay Network。
  2. Calico沒有加密數(shù)據(jù)路徑。 用不可信網(wǎng)絡(luò)上的Calico建立覆蓋網(wǎng)絡(luò)是不安全的。
  3. 沒有IP重疊支持。 雖然Calico社區(qū)正在開發(fā)一個實驗功能,將重疊IPv4包放入IPv6包中。 但這只是一個輔助解決方案,并不完全支持技術(shù)上的IP重疊。
Weave

Weave是由Zett.io公司開發(fā)的,它能夠創(chuàng)建一個虛擬網(wǎng)絡(luò),用于連接部署在多臺主機上的Docker容器,這樣容器就像被接入了同一個網(wǎng)絡(luò)交換機,那些使用網(wǎng)絡(luò)的應(yīng)用程序不必去配置端口映射和鏈接等信息。

外部設(shè)備能夠訪問Weave網(wǎng)絡(luò)上的應(yīng)用程序容器所提供的服務(wù),同時已有的內(nèi)部系統(tǒng)也能夠暴露到應(yīng)用程序容器上。Weave能夠穿透防火墻并運行在部分連接的網(wǎng)絡(luò)上,另外,Weave的通信支持加密,所以用戶可以從一個不受信任的網(wǎng)絡(luò)連接到主機。

Weave實現(xiàn)原理
11.png

容器的網(wǎng)絡(luò)通訊都通過route服務(wù)和網(wǎng)橋轉(zhuǎn)發(fā)。

12.png

Weave會在主機上創(chuàng)建一個網(wǎng)橋,每一個容器通過veth pair連接到該網(wǎng)橋上,同時網(wǎng)橋上有個Weave router的容器與之連接,該router會通過連接在網(wǎng)橋上的接口來抓取網(wǎng)絡(luò)包(該接口工作在Promiscuous模式)。

在每一個部署Docker的主機(可能是物理機也可能是虛擬機)上都部署有一個W(即Weaverouter),它本身也可以以一個容器的形式部署)。Weave run的時候就可以給每個veth的容器端分配一個ip和相應(yīng)的掩碼。veth的網(wǎng)橋這端就是Weave router容器,并在Weavelaunch的時候分配好ip和掩碼。

Weave網(wǎng)絡(luò)是由這些weave routers組成的對等端點(peer)構(gòu)成,每個對等的一端都有自己的名字,其中包括一個可讀性好的名字用于表示狀態(tài)和日志的輸出,一個唯一標(biāo)識符用于運行中相互區(qū)別,即使重啟Docker主機名字也保持不變,這些名字默認(rèn)是mac地址。

每個部署了Weave router的主機都需要將TCP和UDP的6783端口的防火墻設(shè)置打開,保證Weave router之間控制面流量和數(shù)據(jù)面流量的通過??刂泼嬗蓋eave routers之間建立的TCP連接構(gòu)成,通過它進(jìn)行握手和拓?fù)潢P(guān)系信息的交換通信。 這個通信可以被配置為加密通信。而數(shù)據(jù)面Weave routers之間建立的UDP連接構(gòu)成,這些連接大部分都會加密。這些連接都是全雙工的,并且可以穿越防火墻。

Weave優(yōu)劣勢

  • Weave優(yōu)勢
  1. 支持主機間通信加密。
  2. 支持container動態(tài)加入或者剝離網(wǎng)絡(luò)。
  3. 支持跨主機多子網(wǎng)通信。
  • Weave劣勢
  1. 只能通過weave launch或者weave connect加入weave網(wǎng)絡(luò)。

各方案對比

  • Flannel和overlay方案均使用承載網(wǎng)絡(luò),承載網(wǎng)絡(luò)的優(yōu)勢和劣勢都是非常明顯。
優(yōu)勢有:對底層網(wǎng)絡(luò)依賴較少,不管底層是物理網(wǎng)絡(luò)還是虛擬網(wǎng)絡(luò),對層疊網(wǎng)絡(luò)的配置管理影響較少;配置簡單,邏輯清晰,易于理解和學(xué)習(xí),非常適用于開發(fā)測試等對網(wǎng)絡(luò)性能要求不高的場景。
劣勢主要包括:網(wǎng)絡(luò)封裝是一種傳輸開銷,對網(wǎng)絡(luò)性能會有影響,不適用于對網(wǎng)絡(luò)性能要求高的生產(chǎn)場景;由于對底層網(wǎng)絡(luò)結(jié)構(gòu)缺乏了解,無法做到真正有效的流量工程控制,也會對網(wǎng)絡(luò)性能產(chǎn)生影響;某些情況下也不能完全做到與下層網(wǎng)絡(luò)無關(guān),例如隧道封裝會對網(wǎng)絡(luò)的MTU限制產(chǎn)生影響。
  • Calico方案因為沒有隧道封裝的網(wǎng)絡(luò)開銷,會帶來相對較高的網(wǎng)絡(luò)性能。不支持多租戶,由于沒有封裝所有的容器只能通過真實的IP來區(qū)分自己,這就要求所有租戶的容器統(tǒng)一分配一個地址空間。Calico基于三層轉(zhuǎn)發(fā)的原理對物理架構(gòu)可能會有一定的要求和侵入性。
  • weave可以穿透防火墻,安全性較高,流量是被加密的,允許主機連接通過一個不被信任的網(wǎng)絡(luò),同樣會有承載網(wǎng)絡(luò)的帶來的優(yōu)缺點。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容