單機多es容器服務部署的網絡模式

3.1 Bridge模式的拓撲

當Docker server啓動時,會在主機上建立一個名爲docker0的虛擬網橋,此主機上啓動的Docker容器會鏈接到這個虛擬網橋上。虛擬網橋的工做方式和物理交換機相似,這樣主機上的全部容器就經過交換機連在了一個二層網絡中。接下來就要爲容器分配IP了,Docker會從RFC1918所定義的私有IP網段中,選擇一個和宿主機不一樣的IP地址和子網分配給docker0,鏈接到docker0的容器就從這個子網中選擇一個未佔用的IP使用。如通常Docker會使用172.17.0.0/16這個網段,並將172.17.0.1/16分配給docker0網橋(在主機上使用ifconfig命令是能夠看到docker0的,能夠認爲它是網橋的管理接口,在宿主機上做爲一塊虛擬網卡使用)。單機環境下的網絡拓撲以下,主機地址爲10.10.0.186/24。nginx

3.2 Docker:網絡模式詳解

Docker完成以上網絡配置的過程大體是這樣的:web

1. 在主機上建立一對虛擬網卡veth pair設備。veth設備老是成對出現的,它們組成了一個數據的通道,數據從一個設備進入,就會從另外一個設備出來。所以,veth設備經常使用來鏈接兩個網絡設備。docker

2. Docker將veth pair設備的一端放在新建立的容器中,並命名爲eth0。另外一端放在主機中,以veth65f9這樣相似的名字命名,並將這個網絡設備加入到docker0網橋中,能夠經過brctl show命令查看。安全

1
2
3
$ brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.02425f21c208       no

3. 從docker0子網中分配一個IP給容器使用,並設置docker0的IP地址爲容器的默認網關。網絡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 運行容器;
$ docker run --name=nginx_bridge --net=bridge -p 80:80 -d nginx       
9582dbec7981085ab1f159edcc4bf35e2ee8d5a03984d214bce32a30eab4921a
 
# 查看容器;
$ docker ps
CONTAINER ID        IMAGE          COMMAND                  CREATED             STATUS              PORTS                NAMES
9582dbec7981        nginx           "nginx -g 'daemon ..."    3 seconds ago       Up 2 seconds        0.0.0.0:80->80/tcp   nginx_bridge
 
# 查看容器網絡;
$ docker inspect 9582dbec7981
"Networks" : {
     "bridge" : {
         "IPAMConfig" null ,
         "Links" null ,
         "Aliases" null ,
         "NetworkID" "9e017f5d4724039f24acc8aec634c8d2af3a9024f67585fce0a0d2b3cb470059" ,
         "EndpointID" "81b94c1b57de26f9c6690942cd78689041d6c27a564e079d7b1f603ecc104b3b" ,
         "Gateway" "172.17.0.1" ,
         "IPAddress" "172.17.0.2" ,
         "IPPrefixLen" : 16,
         "IPv6Gateway" "" ,
         "GlobalIPv6Address" "" ,
         "GlobalIPv6PrefixLen" : 0,
         "MacAddress" "02:42:ac:11:00:02"
     }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
$ docker network inspect bridge
[
     {
         "Name" "bridge" ,
         "Id" "9e017f5d4724039f24acc8aec634c8d2af3a9024f67585fce0a0d2b3cb470059" ,
         "Created" "2017-08-09T23:20:28.061678042-04:00" ,
         "Scope" "local" ,
         "Driver" "bridge" ,
         "EnableIPv6" false ,
         "IPAM" : {
             "Driver" "default" ,
             "Options" null ,
             "Config" : [
                 {
                     "Subnet" "172.17.0.0/16"
                 }
             ]
         },
         "Internal" false ,
         "Attachable" false ,
         "Ingress" false ,
         "Containers" : {
             "9582dbec7981085ab1f159edcc4bf35e2ee8d5a03984d214bce32a30eab4921a" : {
                 "Name" "nginx_bridge" ,
                 "EndpointID" "81b94c1b57de26f9c6690942cd78689041d6c27a564e079d7b1f603ecc104b3b" ,
                 "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" : {}
     }
]

網絡拓撲介紹完後,接着介紹一下bridge模式下容器是如何通訊的。tcp

3.3 bridge模式下容器的通訊

在bridge模式下,連在同一網橋上的容器能夠相互通訊(若出於安全考慮,也能夠禁止它們之間通訊,方法是在DOCKER_OPTS變量中設置–icc=false,這樣只有使用–link才能使兩個容器通訊)。spa

Docker能夠開啓容器間通訊(意味着默認配置--icc=true),也就是說,宿主機上的全部容器能夠不受任何限制地相互通訊,這可能致使拒絕服務攻擊。進一步地,Docker能夠經過--ip_forward和--iptables兩個選項控制容器間、容器和外部世界的通訊。.net

容器也能夠與外部通訊,咱們看一下主機上的Iptable規則,能夠看到這麼一條code

1
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE

這條規則會將源地址爲172.17.0.0/16的包(也就是從Docker容器產生的包),而且不是從docker0網卡發出的,進行源地址轉換,轉換成主機網卡的地址。這麼說可能不太好理解,舉一個例子說明一下。假設主機有一塊網卡爲eth0,IP地址爲10.10.101.105/24,網關爲10.10.101.254。從主機上一個IP爲172.17.0.1/16的容器中ping百度(180.76.3.151)。IP包首先從容器發往本身的默認網關docker0,包到達docker0後,也就到達了主機上。而後會查詢主機的路由表,發現包應該從主機的eth0發往主機的網關10.10.105.254/24。接着包會轉發給eth0,並從eth0發出去(主機的ip_forward轉發應該已經打開)。這時候,上面的Iptable規則就會起做用,對包作SNAT轉換,將源地址換爲eth0的地址。這樣,在外界看來,這個包就是從10.10.101.105上發出來的,Docker容器對外是不可見的。server

那麼,外面的機器是如何訪問Docker容器的服務呢?咱們首先用下面命令建立一個含有web應用的容器,將容器的80端口映射到主機的80端口。

1
$ docker run --name=nginx_bridge --net=bridge -p 80:80 -d nginx

而後查看Iptable規則的變化,發現多了這樣一條規則:

1
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.2:80

此條規則就是對主機eth0收到的目的端口爲80的tcp流量進行DNAT轉換,將流量發往172.17.0.2:80,也就是咱們上面建立的Docker容器。因此,外界只需訪問10.10.101.105:80就能夠訪問到容器中的服務。

除此以外,咱們還能夠自定義Docker使用的IP地址、DNS等信息,甚至使用本身定義的網橋,可是其工做方式仍是同樣的。E

相關文章
相關標籤/搜索