1. 程式人生 > >docker基礎篇(一)補

docker基礎篇(一)補

gin 全雙工 開始 gist 運行時 opts text 自然 標準

  經過一個星期的加班到9點,終於將docker的網絡部分小小的總結了一下,小編在這之前也發布過關於docker的內容,本來想就此結束,但是總感覺少了些什麽,只會docker的命令,仿佛不能深入的理解docker強大之處,所以小編決定在補充一下關於docker的網絡部分,包括docker的網絡模式、容器通信、以及相應的實戰操作。雖然這部分有些難以理解,但是細細研讀之後,一定會有所收獲。

1.docker的網絡模式

  安裝Docker時,它會自動創建三個網絡,bridge(創建容器默認連接到此網絡,也就是在不使用--network參數時)、 none 、host。還有以後一種自定義模式,自定義模式有三種:bridge、overlay、macvlan。

我們可以使用一下命令,查看本機容器間通信的幾種方式:

 docker network ls

技術分享圖片
  我們可以在docker run的時候使用--net= none/ host/ bridge來設置容器具體使用哪種模式。

(1)默認網絡通信模式bridge網橋

  默認情況下docker運行容器時,宿主機會創建一個bridge網橋,是一個名叫docker 0的虛擬網橋 ,默認docker 0 IP為172.17.0.1,網橋再給容器分配虛擬子網IP,並且以網橋IP作為網關。在不指定網絡的情況下,容器之間的通信都是通過bridge網橋進行通信。然後網橋在與宿主機鏡像進行IP轉換,端口映射等通信。

  這種bridge網橋與容器,與宿主機之間的通信,有點類似與三層路由交換:
    技術分享圖片

(2) host宿主機模式

  如果容器指定網絡模式為host,容器不會有自己的network namespace,而是和宿主機共用一個network網絡及IP,容器不會有虛擬出自己的網卡、IP等,當然除了網絡通信這一塊和宿主機綁定了,其余的容器內容還是和宿主機安全隔離了。這種在做容器遷移時,很不方便,不推薦使用。
技術分享圖片

(3) none模式

  容器指定網絡模式-net為none時,docker容器不再擁有自己的network namespace,但是所有網絡配置都得自行配置,如IP、網卡等,這種方式很麻煩。(關閉了容器的網絡功能)

技術分享圖片
這裏補充兩個docker服務運行時參數
-b BRIDGE or--bridge=BRIDGE ——指定容器掛載的網橋;
--fixed-cidr=10.200.55.64/26 #定制容器的IP地址範圍

2.單機間的容器通信

  單機間的通信,就是同一宿主機中的不同容器之間的通信,容器之間可通過 IP,Docker DNS Server 和joined 容器三種方式通信。

(1)IP通信

  兩個容器要能通信,必須要有屬於同一個網絡的網卡。滿足這個條件後,容器就可以通過 IP 交互了。這也是默認的方式,我們在使用--net= bridge,docker虛擬出來的一個docker0網橋,會給每一個容器在docker0網橋的網段中分配一個IP,這樣同主機中的容器的IP是同一網段的自然可以通過IP相互訪問。
演示:

[[email protected] ~]# ifconfig

技術分享圖片
這裏看到我的這臺機器中的docker0的網橋的地址為172.17.0.1,這臺機器中啟動的所有的docker的容器的IP都是這個網段的。

[[email protected] ~]# docker ps  #查看正在運行的docker容器

技術分享圖片
我這裏有兩個一個是registry一個是MySQL。

[[email protected] ~]# docker inspect 28b2c91d4be4|grep -i ipaddress #查看容器的IP

技術分享圖片

[[email protected] ~]# docker inspect 5708c1dcbdd7|grep -i ipaddress #查看容器的IP

技術分享圖片
可以發現這兩個容器的IP地址果然都是172.17.0.1網段的。

(2)docker DNS server

  通過 IP 訪問容器雖然滿足了通信的需求,但還是不夠靈活。因為我們在部署服務之前可能不能確定IP。比如:現在部署一個Nginx web服務,但是每次容器啟動分配的IP地址都會改變,我們無法通過固定的IIP地址去訪問web服務,這樣每次訪問時都要查看IP,非常麻煩,對於這個問題,可以通過 docker 自帶的 DNS 服務解決。
  從 Docker 1.10 版本開始,docker daemon 實現了一個內嵌的 DNS server,使容器可以直接通過"容器名"通信。方法很簡單,只要在啟動時用 --name 為容器命名就可以了。
演示:

#下面在同主機啟動兩個Ubuntu系統並指定--name:
[[email protected] ~]#docker run -it --network=brideg2 --name box1 ubuntu:net /bin/bash
[[email protected] ~]#docker run -it --name --network= brideg2 box2 ubuntu:net /bin/bash

技術分享圖片
我們發現使用--name,的容器名稱可以ping通其他容器。
註意:使用 docker DNS 有個限制:只能在 user-defined 網絡中使用。也就是說,默認的 bridge 網絡是無法使用 DNS 的。

(3) joined 容器

  joined 容器是另一種實現容器間通信的方式。它可以使兩個或多個容器共享一個網絡棧,共享網卡和配置信息,joined 容器之間可以通過 127.0.0.1 直接通信。
演示:

#啟動一個http服務
[[email protected] ~]# docker run -dit --name my-apache-app  -p 8099:80 -v "/http":/usr/local/apache2/htdocs/ httpd
#創建一個Ubuntu容器容器並通過 --network=container: my-apache-app指定 jointed 容器為 my-apache-app
[[email protected] ~]# docker run -it --network=container:my-apache-app ubuntu:net /bin/bash
#使用命令去訪問my-apache-app容器中的web頁面
[email protected]:/# curl 127.0.0.1

技術分享圖片
此時我們發現訪問成功!原因是:我們分別查看著兩個容器的IP:
Ubuntu:
技術分享圖片
http:
技術分享圖片
我們發現兩個容器的網卡 mac 地址與 IP 完全一樣,它們共享了相同的網絡棧。所以Ubuntu容器可以使用127.0.0.1直接訪問http容器的web服務。

(4) 補充

docker run 命令的參數介紹:

    -h 運行容器時指定主機名,這樣我們可以使用主機名去與容器通信。
    --link=容器名 別名  ,這樣使用--link連接的容器間就可以使用主機名進行通信。
    -p host_port:container_port 端口映射,容器的服務端口映射到宿主機。
    -P  container_port    端口映射,映射到宿主機的任意空閑端口。

容器的訪問控制
容器訪問外部網絡:兩種方法:
  - sysctl -w net.ipv4.ip_forward=1 (設置宿主機的開啟數據轉發)
  - 啟動Docker服務的時候設定--ip-forward=true,docker會自動打開宿主機系統的轉發服務
外部訪問容器:這裏很簡單,通過docker run -h hostname -p 端口映射,來實現外部訪問容器。

3.跨主機間的容器通信

(1)Docker網橋實現跨主機容器連接

  在同一宿主機下docker容器之間是可以相同連通的。這是因為默認的docker容器在同一宿主機下,所有容器分配的IP處於同一個地址段的,相互之間可以ping通;當我們使用ifconfig命令查看IP時會發現,其中有一個docker0的網橋,docker容器通過docker0 網橋實現同一主機間中,容器的IP地址分配和訪問,這就保證了所有的容器在同一地址段。
  雖然這些IP地址在同一宿主機中是處於同一網段並且相互之間可以通信,但是如果在不同宿主機之間,如果網橋的網段不同,容器之間還是不可能實現跨住進的通信,那麽我們可以將每個主機下的容器的網段都處於同一網段,這樣,就可以實現跨主機的訪問啦,這也是Docker容器默認跨主機之間的連接方法的第一種:網橋實現。
技術分享圖片
  上圖就是網橋方式實現跨主機的連接,但是缺點也很明顯,宿主機和容器的IP處於同一網段,如果在局域網下,IP地址是有限的,那麽一個容器占據一個IP地址,IP地址很快就會被用光,這就是個不友好的現象,所以這種方式僅僅只用來學習測試使用。
實戰操作:
實驗環境:

主機名 IP Gateway Netmask
Host1 192.168.130.130 192.168.130.2 255.255.255.0
Host2 192.168.130.131 192.168.130.2 255.255.255.0

① 下載網橋管理工具

yum install -y bridge-utils

② 分別在docker主機上建立網橋

Host1: $ sudo brctl addbr br0
Host2: $ sudo brctl addbr br0

③ 為網橋分配一個同網段IP

Host1: $ sudo ifconfig br0 192.168.130.10 netmask 255.255.255.0
Host2: $ sudo ifconfig br0 192.168.130.20 netmask 255.255.255.0

④ 橋接本地網卡

Host1: $ brctl addif br0 eth0
Host2: $ brctl addif br0 eth0

⑤ 修改docker配置文件

$ Host1 vim /etc/default/docker
$ Host2 vim /etc/default/docker

改成:Host1: DOCKER_OPTS=” -b=br0 –fixed-cidr=‘192.168.130.64/26“
Host2: DOCKER_OPTS=” -b=br1 –fixed-cidr=‘192.168.130.128/26“
這裏的:
-b :用來指定容器連接的網橋的名字。
--fixed-cidr :用來限定容器分配的IP地址的範圍。
⑥重啟docker

$ Host1 systemctl daemon-reload
$ Host1 systemctl restart docker 
$ Host2 systemctl daemon-reload
$ Host2 systemctl restart docker

⑦ 測試
這裏在host1和host2中各啟動一個容器,然後相互ping對方容器IP,如果可以ping桶表示配置成功。

(2)Open vSwitch 實現跨主機容器通信

  Open vSwitch是一個高質量、多層虛擬交換機。使用Apache2.0許可協議,旨在通過編程擴展,使龐大的網絡自動化(配置、管理、維護),同時還支持標準的管理接口和協議。
技術分享圖片
實戰操作:

實驗環境:

主機名 IP Gateway Netmask
Host1 192.168.130.130 192.168.130.2 255.255.255.0
Host2 192.168.130.131 192.168.130.2 255.255.255.0

虛擬機網段:

主機名 網段
Host1 192.168.1.1
Host2 192.168.2.1

操作步驟:

  • 在虛擬機中建立ovs網橋
  • 添加gre連接
  • 配置docker容器虛擬網橋接
  • 為虛擬網橋添加ovs接口
  • 添加不同Docker容器網段路由
    ① 安裝Open vSwitch並啟動

    [[email protected] Host1~]#yum install -y openvswitch.x86_64
    [[email protected] Host1~]#systemctl start openvswitch

② 安裝網橋

[[email protected] Host1~]# yum install -y bridge-utils

③ 建立ovs網橋並添加GRE接口

[[email protected] Host1~]# ovs-vsctl add-br obr0
[[email protected] Host1~]# ovs-vsctl add-port obr0 gre0

④ 設置遠程的網橋連接

[[email protected] Host1~]#ovs-vsctl set interface gre0 type=gre options:remote_ip=192.168.130.131
#查看osv網橋配置
[[email protected] Host1~]#ovs-vsctl show

⑤ 設置docker的虛擬網橋

[[email protected] Host1~]#brctl addbr br0
[[email protected] Host1~]#ifconfig br0 192.168.1.1 netmask 255.255.255.0
[[email protected] Host1~]#brctl addif br0 obr0
[[email protected] Host1~]#brctl show

⑥ 設置路由規則

[[email protected] Host1~]#ip route add 192.168.2.0/24 via 192.168.130.131 dev ens33

同理host2也需要按照上述方式配置。最後兩個容器之間就可以通信。

(3)Weave實現跨主機容器通信

   Weave是由weaveworks公司開發的解決Docker跨主機網絡的解決方案,它能夠創建一個虛擬網絡,用於連接部署在多臺主機上的Docker容器,這樣容器就像被接入了同一個網絡交換機,那些使用網絡的應用程序不必去配置端口映射和鏈接等信息。
  外部設備能夠訪問Weave網絡上的應用程序容器所提供的服務,同時已有的內部系統也能夠暴露到應用程序容器上。Weave能夠穿透防火墻並運行在部分連接的網絡上,另外,Weave的通信支持加密,所以用戶可以從一個不受信任的網絡連接到主機。
原理:

技術分享圖片
  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連接構成,這些連接大部分都會加密。這些連接都是全雙工的,並且可以穿越防火墻。
實戰操作:
實驗環境:

主機名 IP Gateway Netmask
Host1 192.168.130.130 192.168.130.2 255.255.255.0
Host2 192.168.130.131 192.168.130.2 255.255.255.0

① 下載復制weave二進制執行文件

[[email protected] Host1~]#git clone https://github.com/weaveworks/weave
[[email protected] Host1~]#cp -p /root/weave/weave  /usr/bin/
[[email protected] Host1~]#cd /usr/bin/
#查看weave版本
[[email protected] Host1~]#weave version

技術分享圖片
② 啟動weave服務

[[email protected] Host1~]# weave launch --no-detect-tls  #註意第一次啟動會在docker中拉取相應的鏡像

③ 運行一個容器

[[email protected] Host1~]#docker run -it ubuntu:net /bin/bash  

然後Ctrl+p+q退出容器,並且讓容器後臺運行
④ 進入容器

[[email protected] Host1~]#weave attach 192.168.2.1/24 c45932ef7da4

註意:這裏的192.168.2.1/24 是默認的給當前容器分配的一個weaveIP
技術分享圖片
之後再host2宿主機中也執行以上的命令,並且在“weave attach 192.168.2.1/24 容器ID” 這裏分配一相同網段的不同IP。
技術分享圖片
此時通過這個ethwe中的IP,去相同ping對方容器,這裏就可以相同訪問:
技術分享圖片

docker基礎篇(一)補