Docker之網絡管理(容器間通訊的配置)

博文大綱:web

  • 1、Bridge模式(同一臺Docker服務器上容器間的通訊)
  • 2、部署consul服務實現Docker容器跨主機通訊

前言:

當你開始大規模使用Docker時,你會發現須要瞭解不少關於網絡的知識。Docker做爲目前最火的輕量級容器技術,有不少使人稱道的功能,如Docker的鏡像管理。然而,Docker一樣有着不少不完善的地方,網絡方面就是Docker比較薄弱的部分。所以,咱們有必要深刻了解Docker的網絡知識,以知足更高的網絡需求。本文首先介紹了Docker自身的4種網絡工做方式,而後介紹一些自定義網絡模式。docker


咱們安裝Docker時,它會自動建立三個網絡,bridge(建立容器默認鏈接到此網絡)、 none 、host。數據庫

  • host:容器將不會虛擬出本身的網卡,配置本身的IP等,而是使用宿主機的IP和端口。
  • None:該模式關閉了容器的網絡功能,至關於一個迴環網絡。
  • Bridge:此模式會爲每個容器分配、設置IP等,並將容器鏈接到一個叫docker0的虛擬網橋,經過docker0網橋以及Iptables nat表配置與宿主機通訊。
[root@docker ~]# docker network ls    #執行該命令查看docker建立的網絡

關於上述提到的三個網絡解釋以下:編程

  • Host:至關於Vmware中的橋接模式,與宿主機在同一個網絡中,但沒有獨立的IP地址。衆所周知,Docker使用了Linux的Namespaces技術來進行資源隔離,如PID Namespace隔離進程,Mount Namespace隔離文件系統,Network Namespace隔離網絡等。一個Network Namespace提供了一份獨立的網絡環境,包括網卡、路由、Iptable規則等都與其餘的Network Namespace隔離。一個Docker容器通常會分配一個獨立的Network Namespace。但若是啓動容器的時候使用host模式,那麼這個容器將不會得到一個獨立的Network Namespace,而是和宿主機共用一個Network Namespace。容器將不會虛擬出本身的網卡,配置本身的IP等,而是使用宿主機的IP和端口。基於Host模式啓動的容器,在容器內執行ifconfig時,看到的都是宿主機上的信息。該模式不夠靈活,容易出現端口衝突問題。
  • None:該模式將容器放置在它本身的網絡棧中,可是並不進行任何配置。實際上,該模式關閉了容器的網絡功能,相似於會換地址,在如下兩種狀況下是有用的:容器並不須要網絡(例如只須要寫磁盤卷的批處理任務)。
  • overlay:顧名思義:覆蓋,但它又不是覆蓋,它的做用就是在容器原有的網絡基礎之上,再添加一塊網卡,併爲其分配一個IP地址,能夠將全部的docker容器關聯到同一個局域網中,適用於容器與容器是跨主機進行通訊的場景。
  • Bridge:至關於Vmware中的NAT模式,容器使用獨立的network Namespace,而且鏈接到docker0虛擬網卡(默認模式)。經過docker網橋以及IPtables nat表配置與宿主機通訊;Bridge模式是Docker默認的網絡設置,此模式會爲每個容器分配一個Network nameSpace、設置IP等,並將一個主機上的Docker容器鏈接到一個虛擬網橋docker0上。

在生產環境中,應用的最多的就是Bridge模式和overlay模式了。這篇博文將圍繞着這兩個模式進行介紹。bootstrap

1、Bridge模式

當Docker server啓動時,會在主機上建立一個名爲docker0的虛擬網橋,此主機上啓動的Docker容器就會鏈接到這個虛擬網橋上。虛擬網橋的工做方式和物理交換機相似,這樣主機上的全部容器就經過交換機連在了一個二層網絡中,通常Docker會使用172.17.0.0/16這個網段,並將這個網段分配給docker0網橋使用(在主機上使用ifconfig命令能夠看到docker0),而後爲容器分配一個同網段的IP地址。vim

單機環境下的網絡拓撲以下(主機地址是10.10.0.186/24):瀏覽器

Docker之網絡管理(容器間通訊的配置)

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

  • 在主機上建立一對虛擬網卡veth pair設備。veth設備老是成對出現的,它們組成了一個數據的通道,數據從一個設備進入,就會從另外一個設備出來。所以,veth設備經常使用來鏈接兩個網絡設備。
  • Docker將veth pair設備的一端放在新建立的容器中,並命名爲eth0。另外一端放在主機中,以veth65f9這樣相似的名字命名,並將這個網絡設備加入到docker0網橋中,能夠經過brctl show命令查看。
  • 從docker0子網中分配一個IP給容器使用,並設置docker0的IP地址爲容器的默認網關。

當全部的容器都是基於默認的docker0進行建立的,那麼拋開防火牆、IPtables等相關的設置外,理論上,各個容器是能夠相互通訊的,可是docker0這個網絡是系統自帶的,有些功能不可以實現,而且不夠靈活。網絡

其實咱們也是能夠自定義建立網絡的,而且能夠指定其具體屬於哪一個網段等。這是docker 0沒法實現的,那麼,若是各個容器,不是基於同一個網絡(如Docker0)建立的話,那麼?如何使它們互通呢?tcp

下面來一段配置,來看一下Bridge的工做模式。

實現的效果以下:

  • 基於docker0(docker的驅動名稱使bridge)網絡建立2個容器,分別是box一、box2。
  • 建立自定義網絡,網絡類型爲bridge,名稱爲my_net1.基於此網絡建立兩個容器box3,box4(若不指定網段,會使用172.18.0.0/16這個網段,基於docker0增長一個網絡位)
  • 建立自定義網絡,網絡類型爲bridge,名稱爲my_net2,指定網段爲172.20.18.0/24,基於此網絡建立兩個容器box5(ip爲172.20.18.6),box6(IP爲172.20.18.8)。
  • 配置實現box2可以和box3相互通訊,box4和box5能夠相互通訊。
[root@docker ~]# docker run -itd --name box1 --network bridge busybox    
#建立一個容器box1,--network選項能夠省略,默認就是bridge,這裏只是爲了展現命令
[root@docker ~]# docker run -itd --name box2 --network bridge busybox   #同上,這裏建立一個容器box2
[root@docker ~]# docker network create -d bridge my_net1    #建立一個橋接網絡,名稱爲my_net1
[root@docker ~]# docker run -tid --name box3 --network my_net1 busybox    #基於my_net1建立容器box3
[root@docker ~]# docker run -tid --name box4 --network my_net1 busybox   #同上,建立box4
[root@docker ~]# docker network create -d bridge --subnet 172.20.18.0/24 my_net2   #建立一個橋接網絡my_net2,並指定其網段
[root@docker ~]# docker run -tid --name box5 --network my_net2 --ip 172.20.18.6 busybox   
#基於my_net2網絡,建立一個容器box5,而且指定其IP地址
[root@docker ~]# docker run -tid --name box6 --network my_net2 --ip 172.20.18.8 busybox    #同上
[root@docker ~]# docker network connect my_net1 box2      #將box2鏈接到my_net1這個網絡
[root@docker ~]# docker exec box2 ping box3   #進行ping測試,能夠發現box2能夠ping通box3了。
#而若是沒有將box2鏈接到網絡my_net1,是絕對不會ping通的。
PING box3 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.069 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.076 ms
[root@docker ~]# docker network connect my_net2 box4   #將box4鏈接到my_net2網絡
#同box2和box3的ping測試,若沒有將box4鏈接到box5所在的網絡,是不可能ping通的。
[root@docker ~]# docker exec box5 ip a    #查看box5的IP地址
         .......................#省略部份內容
16: eth0@if17: <BROADCAST,MULTICAST,UP,LO500 qdisc noqueue 
    link/ether 02:42:ac:14:12:06 brd ff:ff:ff:ff:ff:ff
    inet 172.20.18.6/24 brd 172.20.18.255 scope global eth0     #確認其IP
       valid_lft forever preferred_lft forever
[root@docker ~]# docker exec box4 ping 172.20.18.6   #在box4容器上對box5的IP進行ping測試,能夠ping通
PING box5 (172.20.18.6): 56 data bytes
64 bytes from 172.20.18.6: seq=0 ttl=64 time=0.090 ms
64 bytes from 172.20.18.6: seq=1 ttl=64 time=0.130 ms

通過以上配置,已經實現了最終的效果,須要注意的是,咱們徹底能夠將建立的my_net一、my_net2網絡驅動理解爲一個交換機,而執行命令docker network connect my_net1 box2,則至關於將box2這個容器添加了一塊網卡,而後鏈接到了my_net1這個交換機,而後這個容器就多了一塊網卡,而且擁有my_net1這個交換機中IP地址。在上述的配置中,box2不但能夠和box3進行通訊,也是能夠和box4進行通訊的,由於它們都是鏈接在了my_net1這個「交換機」上。

注意:

  • 容器之間可使用容器名進行通訊,但前提使用的是自定義的網絡,如上面的my_net一、my_net2;
  • 若是在建立自定義網絡的同時,指定了該網絡的網段,那麼,使用此網絡的容器也能夠指定容器的IP地址,若沒有指定該網絡的網段,則不能夠指定容器的IP地址。

2、部署consul服務實現Docker容器跨主機通訊

consul:數據中心的含義,能夠將其當作數據庫來理解,相似於Redis等非關係型數據庫,採用的是鍵-值對的方式,存放着各個容器的IP及端口信息。

我對consul服務的瞭解也不是太多,若想要詳細瞭解此服務,仍是參考其餘文檔吧,若之後有機會,我會詳細寫下來consul這個服務。

consul的功能很強大,能夠以羣集的方式運行,而且具有健康監測等功能。

下面開始配置consul服務。

一、環境準備以下:

  • Docker服務器三臺,我這裏的docker版本爲18.09.0;
  • 第一臺Docker服務器的IP是192.168.20.7,其運行consul服務;
  • 後兩臺爲測試端,只須要有docker環境便可。

若須要安裝部署Docker服務器,能夠參考博文:Docker的安裝詳細配置

二、第一臺Docker服務器配置以下:

[root@docker ~]# docker pull progrium/consul          #下載consul鏡像
[root@docker ~]# docker run -d -p 8500:8500 -h consul --name consul --restart=always progrium/consul -server -bootstrap
#運行consul容器,該服務的默認端口是8500,「-p」:表示將容器的8500端口映射到宿主機的8500端口
#「-h」:表示consul的主機名;「--name consul」表示爲該容器名;「--restart=always」表示能夠隨着docker服務的啓動而啓動;
#「-serve -bootstarp」:表示當在羣集中,加上這兩個選項可使其以master的身份出現
[root@docker ~]# netstat -anput | grep 8500   #肯定8500端口在監聽
tcp6       0      0 :::8500                 :::*

OK,至此,單節點的consul服務就完成了,如今切換至第二臺Docker服務器。

三、第二臺Docker服務器配置以下:

[root@docker02 ~]# vim /usr/lib/systemd/system/docker.service  #編輯docker主配置文件
         ..............#省略部份內容,搜索「Start」定位到下面配置行,修改以下:
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376 --cluster-store=consul://192.168.20.7:8500 --cluster-advertise=ens33:2376
#各項解釋以下:
#/var/run/docker.sock:Docker的一個編程接口
# 「 -H tcp://0.0.0.0:2376 」 :使用本機的tcp2376端口;
# 「 --cluster-store=consul://192.168.20.7:8500」:指定運行着consul服務的第一臺docker服務器IP及端口;
# 「 --cluster-advertise=ens33:2376」:從本機的ens33網卡經過2376端口蒐集網絡信息,存儲在consul上
#修改完成後,保存退出便可。
[root@docker02 ~]# systemctl daemon-reload    #從新加載配置文件
[root@docker02 ~]# systemctl restart docker    #重啓docker服務

四、而後在第三臺docker服務器上,進行與第二臺Docker服務器同樣的配置操做,主要是爲了指定consul服務的監聽端口。(自行配置,這裏就不寫了,記得更改完成後,重啓docker服務)

五、如今使用瀏覽器訪問consul服務的web頁面(訪問:192.168.20.7:8500),以下:

Docker之網絡管理(容器間通訊的配置)

Docker之網絡管理(容器間通訊的配置)

便可看到用來測試的那兩臺docker服務器IP等相關信息,以下:
Docker之網絡管理(容器間通訊的配置)

六、回到第二臺Docker服務器上,建立一個overlay網絡:

[root@docker02 ~]# docker network create -d overlay my_olay         #建立一個名字爲my_olay的voerlay網絡

七、切換至第三臺Docker服務器上,發現能夠看到剛剛在第二臺Docker服務器上建立的overlay網絡:

[root@docker03 ~]# docker network ls     #查看docker03的網絡,發現其不但有overlay網絡,
#並且其SCOPE(範圍)是global(全局的)
NETWORK ID          NAME                DRIVER              SCOPE
8d5b00cf07ab        bridge              bridge              local
17c053a80f5a        host                host                local
c428fc28bb11        my_olay             overlay             global
323935eaa5c3        none                null                local

其實,如今在第二臺Docker服務器上基於剛剛建立的overlay網絡運行一個容器,在第三臺Docker服務器上也基於這個overlay網絡運行一個容器,這兩個在不一樣主機上的容器是能夠互通的,以下:

##################第二臺Docker服務器上配置以下:###########################
[root@docker02 ~]# docker run -tid --name web01 --network my_olay busybox    #基於網絡my_olay運行一個容器web01
[root@docker02 ~]# docker exec web01 ip a         #查看其IP信息,發現其除了迴環地址,還有兩個IP
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue 
    link/ether 02:42:0a:00:00:02 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.2/24 brd 10.0.0.255 scope global eth0     #這個地址就是my_olay給的
       valid_lft forever preferred_lft forever
11: eth1@if12: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.2/16 brd 172.18.255.255 scope global eth1  
       valid_lft forever preferred_lft forever
##################第三臺Docker服務器上配置以下:###########################
[root@docker03 ~]# docker run -tid --name web02 --network my_olay busybox     #基於網絡my_olay運行一個容器web02
[root@docker03 ~]# docker exec web02 ip a     #查看web02的IP
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue 
    link/ether 02:42:0a:00:00:03 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.3/24 brd 10.0.0.255 scope global eth0            #這個地址就是my_olay給的
       valid_lft forever preferred_lft forever
11: eth1@if12: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.2/16 brd 172.18.255.255 scope global eth1
       valid_lft forever preferred_lft forever
#########在第二臺Docker服務器上對第三臺Docker服務器上的容器進行ping測試##########
[root@docker02 ~]# docker exec web01 ping web02      #肯定能夠ping通
PING web02 (10.0.0.3): 56 data bytes
64 bytes from 10.0.0.3: seq=0 ttl=64 time=1.091 ms
64 bytes from 10.0.0.3: seq=1 ttl=64 time=1.007 ms

———————— 本文至此結束,感謝閱讀 ————————

相關文章
相關標籤/搜索