docker紀錄篇2-docker容器網絡互連

一 。同主機容器互連html

 1》網絡模式簡介
nginx

同一宿主機的網絡模型分爲四種模式
  》》Bridge模式git

    當Docker進程啓動時,會在主機上建立一個名爲docker0的虛擬網橋,此主機上啓動的Docker容器會鏈接到這個虛擬網橋上。虛擬網橋的工做方式和物理交換機相似,這樣主機上的全部容器就經過交換機連在了一個二層網絡中。
從docker0子網中分配一個IP給容器使用,並設置docker0的IP地址爲容器的默認網關。在主機上建立一對虛擬網卡veth pair設備,Docker將veth pair設備的一端放在新建立的容器中,並命名爲eth0(容器的網卡),另外一端放在主機中,以vethxxx這樣相似的名字命名,並將這個網絡設備加入到docker0網橋中。能夠經過brctl show命令查看。
bridge模式是docker的默認網絡模式,不寫--net參數,就是bridge模式。使用docker run -p時,docker實際是在iptables作了DNAT規則,實現端口轉發功能。可使用iptables -t nat -vnL查看。
bridge模式以下圖所示:  


建立容器

github

[root@cdh2 ~]# docker run -tid --net=bridge --name c1 centos
5958da9979269f1a7f4bfdb5c2ce9169e530445efa330a0e3e54deb9bb3db261
[root@cdh2 ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
5958da997926        centos              "/bin/bash"         8 seconds ago       Up 7 seconds                            c1
查看宿主機自動 生成veth docker0的網橋ip是 172.17.0.1
[root@cdh2 ~]# ip addr
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:42:c1:eb:b7 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:42ff:fec1:ebb7/64 scope link 
       valid_lft forever preferred_lft forever
45: vetha4a973c@if44: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP 
    link/ether 02:5e:3f:c8:aa:c0 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::5e:3fff:fec8:aac0/64 scope link 
       valid_lft forever preferred_lft forever
查看ip地址(docker inspect查詢的json格式能夠用 {{.根節點.子節點.....}}獲取對應值) 或者直接用 docker inspect c1 | grep IP
[root@cdh2 ~]# docker inspect -f '{{.Name}} - {{.NetworkSettings.IPAddress }}' c1
/c1 - 172.17.0.2
進入shell命令 安裝net-tools
[root@cdh2 ~]# docker exec -it c1 /bin/bash                                      
[root@0441ad51a806 /]# yum -y install net-tools
查看ip地址和網關地址(應該是網橋的ip 172.17.0.1)
[root@0441ad51a806 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 0.0.0.0
        inet6 fe80::42:acff:fe11:2  prefixlen 64  scopeid 0x20<link>
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 2336  bytes 9346632 (8.9 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1716  bytes 96631 (94.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
網關(全部ip 走的網關是 172.17.0.1)
[root@0441ad51a806 /]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.17.0.1      0.0.0.0         UG    0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth0

橋接方式默認的網關是172.17.0.1 能夠經過編輯/etc/docker/daemon.json文件,web

添加內容 "bip": "ip/netmask" [ 切勿與宿主機同網段 ] 好比docker

[root@localhost /]# vi /etc/docker/daemon.json  
{"bip":"192.168.55.1/24"}

網橋方式容器的ip是自動分配的 每次啓動容器都會從新分配ip地址 能夠修改成 link模式 設置主機名方式

使用link方式進行通訊
docker的link機制能夠經過一個name(主機名)來和另外一個容器通訊,link機制方便了容器去發現其它的容器而且能夠安全的傳遞一些鏈接信息給其它的容器(環境變量)
shell

   啓動第一個nginx容器
json

[root@cdh2 ~]# docker run --name n1 -d -e MYID=1 nginx
   啓動第二個nginx容器 而且link了n1 給n1取一個主機名myn1
root@cdh2 ~]# docker run --name n2 -d --link n1:myn1 nginx 
5d1e40750b78e8546723f60ad589da6f1a76b37ee1f70319b087066b9223e608
此時n2容器連接了n1 進入n2容器 查看全部環境變量
[root@cdh2 ~]# docker exec -it n2 /bin/bash
root@5d1e40750b78:/# env                                                                                                                                                                                                                   
MYN1_ENV_NJS_VERSION=1.13.3.0.1.11-1~stretch
MYN1_ENV_NGINX_VERSION=1.13.3-1~stretch
MYN1_PORT_80_TCP_ADDR=172.17.0.2
HOSTNAME=5d1e40750b78
NJS_VERSION=1.13.3.0.1.11-1~stretch
NGINX_VERSION=1.13.3-1~stretch
MYN1_PORT_80_TCP_PORT=80
MYN1_ENV_MYID=1
PWD=/
HOME=/root
MYN1_NAME=/n2/myn1
SHLVL=1
MYN1_PORT=tcp://172.17.0.2:80
MYN1_PORT_80_TCP_PROTO=tcp
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MYN1_PORT_80_TCP=tcp://172.17.0.2:80
_=/usr/bin/env
發現n1設置的環境變量 MYID出如今了n2的環境變量中命令 主機名_ENV_變量名
上面的變量被分紅了五個部分:
  • 第一個部分是web容器自身提供的一些環境變量,如NGINX_VERSION,HOSTNAME,HOME,PATH等.
  • 第二個部分則是MYN1_ENV開頭的變量,這些都是從source container中導入的,變量來源於Dockerfile中使用ENV命令定義的變量,或者是docker run的時候經過-e 添加的環境變量。
  • 第三個部分是MYN1_NAME 這個變量,這變量記錄了link的兩個容器的組合,這裏就是/web/db
  • 第四個部分就是MYN1_PORT開頭的一系列變量,這些變量會有很組,每組變量的命名格式以下
<alias>_PORT_<port>_<protocol>
<alias>_PORT_<port>_<protocol>_PORT
<alias>_PORT_<port>_<protocol>_PROTO
<alias>_PORT_<port>_<protocol>_ADDR
其中<port>是在Dockerfile中使用EXPOSE導出的端口,還有docker run 的時候使用-p導出的端口。<protocol>則是這些端口對應的協議。

  • 第五個部分就是MYN1_PORT這個變量,這個變量是EXPOSE導出端口中的第一個端口對應的鏈接url, 若是有EXPOSE導出的端口,還有docker run -p指定導出的端口,那麼經過-p指定的端口是第一個被導出的端口
在容器n2中 可使用myn1來直接訪問 n1這臺主機了 每次啓動主機 docker自動將myn1對應到n2的ip地址 咱們只須要關注這個hostname便可

  》》Host模式
centos

若是啓動容器的時候使用host模式,那麼這個容器將不會得到一個獨立的Network Namespace,而是和宿主機共用一個Network Namespace。容器將不會虛擬出本身的網卡,配置本身的IP等,而是使用宿主機的IP和端口。可是,容器的其餘方面,如文件系統、進程列表等仍是和宿主機隔離的。
瀏覽器

建立 host模式容器查看ip和路由發現和宿主機是如出一轍

#docker run -tid --net=host --name c2 centos
#docker exec -it c2 /bin/bash
進入後發現主機名都和宿主機同樣
[root@cdh2 ~]# docker exec -it c2 /bin/bash
[root@cdh2 /]# ip adr
使用ifconfig和route -n也是同樣 
  》》 Containner模式
這個模式指定新建立的容器和已經存在的一個容器共享一個 Network Namespace,而不是和宿主機共享。新建立的容器不會建立本身的網卡,配置本身的 IP,而是和一個指定的容器共享 IP、端口範圍等。一樣,兩個容器除了網絡方面,其餘的如文件系統、進程列表等仍是隔離的。兩個容器的進程能夠經過 lo 網卡設備通訊。
Container模式示意圖:


嘗試將新建立的容器c3 綁定到 c1的網絡上 共享網絡 ip地址應該都是相同

[root@cdh2 ~]# docker run -tid --net=container:c1 --name=c3 centos
a01bd6386e89d62ebc807fbff0a30f09f9f4ac864a3eb04a259938930e71ee1c
[root@cdh2 ~]# docker exec -it c3 /bin/bash
[root@0441ad51a806 /]# yum -y install net-tools
[root@0441ad51a806 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 0.0.0.0
        inet6 fe80::42:acff:fe11:2  prefixlen 64  scopeid 0x20<link>
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 6118  bytes 18457579 (17.6 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 4210  bytes 234903 (229.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
[root@0441ad51a806 /]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.17.0.1      0.0.0.0         UG    0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth0
 》》 NONE模式
     使用none模式,Docker容器擁有本身的Network Namespace,可是,並不爲Docker容器進行任何網絡配置。也就是說,這個Docker容器沒有網卡、IP、路由等信息。須要咱們本身爲Docker容器添加網卡、配置IP等。

 

[root@cdh2 ~]# docker run -tid --net=none --name=c3 centos

二。跨主機容器互連

 1》端口映射

  宿主機能夠將容器對應局域網的訪問nat出去實現訪問外部網絡 可是外部網絡主機沒法訪問容器資源  能夠在宿主機上開啓端口

若是來自外部對該端口的訪問 docker經過代理自動路由到綁定的容器端口  好比:

容器啓動nginx 獲取ip地址

[root@cdh2 ~]# docker inspect n1 | grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.2",
                    "IPAddress": "172.17.0.2",
此時宿主機ip地址是(58.144):
2: eno16777736: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:90:75:c5 brd ff:ff:ff:ff:ff:ff
    inet 192.168.58.144/24 brd 192.168.58.255 scope global dynamic eno16777736
       valid_lft 1421sec preferred_lft 1421sec
    inet6 fe80::20c:29ff:fe90:75c5/64 scope link 
       valid_lft forever preferred_lft forever
經過另一個局域網主機 (58.1) 來直接訪問172.17.0.2 是沒法訪問的
C:\Users\jiaozi>ping 172.17.0.2
正在 Ping 172.17.0.2 具備 32 字節的數據:

58.1僅僅能夠訪問宿主機 58.144 只能在58.144啓動容器是綁定一個端口到容器

docker run --name n3 -p 80:80 -d nginx
經過58.1瀏覽器訪問 發現

2》直接路由

  經過在Docker宿主機上添加靜態路由實現跨宿主機通訊
 模擬環境 主機1(192.168.58.144) 設置docker0 網關 (172.17.0.1/16)
                主機2(192.168.58.145) 設置docker0 網關 (172.18.0.1/16)
   修改方式 編輯 /etc/docker/daemon.json修改以下 兩臺主機分別設置不同網關

{"bip":"172.18.0.1/16"}
重啓docker
 
service docker restart
使用ifconfig查看docker0的ip是否修改
分別在兩個主機上啓動1個容器
docker run -itd --name s1  centos
分別查看ip 是不是 172.17.0.2和172.18.0.1
[root@cdh3 ~]# docker inspect s1 | grep IPA
            "SecondaryIPAddresses": null,
            "IPAddress": "172.18.0.2",
                    "IPAMConfig": null,
                    "IPAddress": "172.18.0.2",
在主機144上 要求能訪問 172.18段 添加路由
route add -net 172.18.0.0 netmask 255.255.0.0 gw 192.168.58.145
在主機145上 要求能訪問 172.17段 添加路由
route add -net 172.17.0.0 netmask 255.255.0.0 gw 192.168.58.145
主機兩臺主機的 ip_forward功能必須開啓 不然不會在網卡間轉發
[root@cdh2 ~]# sysctl -a | grep net.ipv4.ip_forward
net.ipv4.ip_forward = 1
若是值不是 1 修改 /etc/sysctl.conf 添加一行
net.ipv4.ip_forward = 1
執行命令 sysctl -p 生效便可  成功後 互相ping對方的docker容器的ip發現成功
模擬環境圖:


3》Pipework指定靜態ip

Pipework是一個簡單易用的Docker容器網絡配置工具。由200多行shell腳本實現。經過使用ip、brctl、ovs-vsctl等命令來爲Docker容器配置自定義的網橋、網卡、路由等。
使用新建的bri0網橋代替缺省的docker0網橋
bri0網橋與缺省的docker0網橋的區別:bri0和主機網卡之間是也是veth pair 能夠爲容器分配和主機相同的網段靜態ip
模擬環境圖
  

該方式建立的容器 使用none的網絡模式 本身定義網橋和網卡等 啓動容器時能夠經過--net=none指定容器網絡模式。

安裝網橋

yum install -y bridge-utils
查看全部網橋
[root@cdh2 ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.0242027435aa       no

修改網絡文件/etc/sysconfig/network-scripts/ifcfg-eno16777736

[root@cdh2 network-scripts]# more ifcfg-eno16777736
TYPE=Ethernet
#BOOTPROTO=dhcp
BOOTPROTO=none
#IPADDR=192.168.58.144
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
NAME=eno16777736
UUID=1c2310e2-e82e-4ce7-a1aa-60d05aa47f1e
DEVICE=eno16777736
ONBOOT=yes
PEERDNS=yes
PEERROUTES=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
BRIDGE="br-ex"
將靜態ip相關注釋 添加 BRIDGE=設備名稱  添加一個新的網卡文件ifcfg-br-ex 內容
[root@cdh2 network-scripts]# more ifcfg-br-ex
TYPE=Bridge
BOOTPROTO=static
IPADDR=192.168.58.144
NETMASK=255.255.255.0
GATEWAY=192.168.58.2
PREFIX=24
DNS1=192.168.58.2
NAME=br-ex
ONBOOT=yes
DEVICE=br-ex
重啓網卡後 查看網絡和網橋
root@cdh2 network-scripts]# ifconfig
br-ex: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.58.144  netmask 255.255.255.0  broadcast 192.168.58.255
        inet6 fe80::20c:29ff:fe90:75c5  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:90:75:c5  txqueuelen 0  (Ethernet)
        RX packets 268  bytes 24407 (23.8 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 136  bytes 17574 (17.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
[root@cdh2 network-scripts]# brctl show
bridge name     bridge id               STP enabled     interfaces
br-ex           8000.000c299075c5       no              eno16777736
docker0         8000.0242027435aa       no
下載pipework腳本
[root@cdh2 ~]# git clone https://github.com/jpetazzo/pipework.git
進入查看 其中有個文件pipework就是腳本
[root@cdh2 ~]# cd pipework
[root@cdh2 pipework]# ll
total 60
-rw-r--r-- 1 root root    75 Jun  6 11:28 docker-compose.yml
drwxr-xr-x 2 root root    23 Jun  6 11:28 doctoc
-rw-r--r-- 1 root root 11358 Jun  6 11:28 LICENSE
-rwxr-xr-x 1 root root 14698 Jun  6 11:28 pipework
-rw-r--r-- 1 root root   827 Jun  6 11:28 pipework.spec
-rw-r--r-- 1 root root 22328 Jun  6 11:28 README.md
將該腳本拷貝到/usr/local/bin目錄 方便執行
[root@cdh2 pipework]# cp -rp pipework /usr/local/bin

分別添加容器 指定 none網絡模式

docker run -itd --net none --name s1  centos

給容器制定固定ip

[root@cdh2 pipework]# pipework br-ex s1 192.168.58.142/24@192.168.58.144
[root@cdh2 pipework]# ping 192.168.58.142
PING 192.168.58.142 (192.168.58.142) 56(84) bytes of data.
64 bytes from 192.168.58.142: icmp_seq=1 ttl=64 time=0.249 ms
piepework參數 pipework 網橋名稱 容器名稱 容器固定ip/24@網橋ip 其餘機器上ping  192.168.58.142發現成功 主機2配置同上便可
相關文章
相關標籤/搜索