博文大綱: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
當Docker server啓動時,會在主機上建立一個名爲docker0的虛擬網橋,此主機上啓動的Docker容器就會鏈接到這個虛擬網橋上。虛擬網橋的工做方式和物理交換機相似,這樣主機上的全部容器就經過交換機連在了一個二層網絡中,通常Docker會使用172.17.0.0/16這個網段,並將這個網段分配給docker0網橋使用(在主機上使用ifconfig命令能夠看到docker0),而後爲容器分配一個同網段的IP地址。vim
單機環境下的網絡拓撲以下(主機地址是10.10.0.186/24):瀏覽器
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地址。
consul:數據中心的含義,能夠將其當作數據庫來理解,相似於Redis等非關係型數據庫,採用的是鍵-值對的方式,存放着各個容器的IP及端口信息。
我對consul服務的瞭解也不是太多,若想要詳細瞭解此服務,仍是參考其餘文檔吧,若之後有機會,我會詳細寫下來consul這個服務。
consul的功能很強大,能夠以羣集的方式運行,而且具有健康監測等功能。
下面開始配置consul服務。
若須要安裝部署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服務器。
[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服務器IP等相關信息,以下:
[root@docker02 ~]# docker network create -d overlay my_olay #建立一個名字爲my_olay的voerlay網絡
[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
———————— 本文至此結束,感謝閱讀 ————————