docker网络模型

docker网络模型

docker四种单机网络模型

​ docker共有4种网络模型:分别是:封闭式网络、桥接式网络、联邦式网络、开放式网络;网络安全性依次减弱,因为网络对外的开放性依次加强

本地查看网络模式:

[root@reg harbor]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
c551b2c85d8b        bridge              bridge              local
ca84b629148b        host                host                local
cab24ad22074        none                null                local

# 安装docker后,默认具有3个网络,none,host,和bridge
# docker run --network ,运行容器时,可以指定其所运行的网络,默认是bridge,桥接到docker0上;

[root@reg harbor]# ifconfig docker0
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:51:02:79:1c  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

image-20201103180136028

封闭网络:none-container

​ 该网络中容器,只有一个环回接口,不进行网络通信与外界;适合执行一次性job的容器;

实验

1、运行一个none网络的容器;

[root@reg harbor]# docker run --name b1 --rm -it --network none busybox
/ # ifconfig 
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface

# 可见,只有一个lo口,没有任何路由,无法网络通信;

none模型图

​ none网络下的容器,只有一个lo口,无法和宿主机及其其他容器进行通信;适合无需网络通信的容器;

image-20201103194913607

桥接网络:bridge-container

参考:https://docs.docker.com/network/network-tutorial-standalone/

​ 该网络中容器,桥接到宿主机上docker0网络,默认是172.17.0.0.0/16网段,容器通过nat形式借助宿主机网络与外面网络通信;

实验

1、运行一个bridge网络的busybox镜像

# 默认即为bridge网络,可不加--network bridge

[root@reg harbor]# docker run --name b1 -it --network bridge busybox
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:12 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:1016 (1016.0 B)  TX bytes:0 (0.0 B)

# 默认2条路由,一是同连在docker0上的其他容器同172.17网段的路由;
# 二是以docker0为默认网关,借助docker0,eth0出去;

/ # 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

# 可以访问宿主机,以及宿主机同网段的其他ip;

/ # ping 192.168.80.101
PING 192.168.80.101 (192.168.80.101): 56 data bytes
64 bytes from 192.168.80.101: seq=0 ttl=64 time=0.174 ms
^C
--- 192.168.80.101 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.174/0.174/0.174 ms
/ # ping 192.168.80.102
PING 192.168.80.102 (192.168.80.102): 56 data bytes
64 bytes from 192.168.80.102: seq=0 ttl=63 time=0.890 ms
64 bytes from 192.168.80.102: seq=1 ttl=63 time=0.662 ms

2、查看生成一个一对网卡

[root@reg harbor]# yum install -y bridge-utils

[root@reg harbor]# brctl show
bridge name	bridge id		STP enabled	interfaces
br-97c0b3d84ade		8000.0242418a7b64	no		
# 该网卡即为容器b1的eth0的另一半,接在了docker0上;

docker0		8000.02425102791c	no	

bridge模型图

描述:

​ docker的桥接模型下,每创建一个容器,都会生成一对网卡,一头接在容器上,为容器的eth0;一头接在docker0上,为vethxx开头的网卡,docker的行为类似交换机,与外界通信时,借助docker和宿主机的eth0网卡,经过nat通信

image-20201103190536782

user-defined-network

​ 在单机桥接网络的基础之上,可以定义用户需要的网络,即再定义另外网段的桥接网络,官方介绍,如默认是172.17.0.0/16网段,用户可以自定义172.18.0.0/16网段,构成2个局域网,

# 创建一个名为alpine-net的网络;
docker network create --driver bridge alpine-net
# 自动被分配为172.18网段;
docker network inspect alpine-net

[
    {
        "Name": "alpine-net",
        "Id": "e9261a8c9a19eabf2bf1488bf5f208b99b1608f330cff585c273d39481c9b0ec",
        "Created": "2017-09-25T21:38:12.620046142Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]
# 创建容器时通过alpine-net加入该自定义网络
docker run -dit --name alpine1 --network alpine-net alpine ash
$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
e9261a8c9a19        alpine-net          bridge              local
17e324f45964        bridge              bridge              local
6ed54d316334        host                host                local
7092879f2cc8        none                null                local

联邦网络:joined-container

​ 该网络中容器,多个容器共享一个tcp/ip协议栈,一般适用于边车模式捆绑一起运行的容器,其主容器和辅助容器公用一套协议栈;联盟网络是基于bridge网络;

​ 也叫container模型,创建容器时,通过container:一个已经运行的容器名或id来加入其网络;

实验

1、创建第一个容器b1

[root@reg harbor]# docker run --name b1 --rm -it busybox

/ # echo joined-containers > /tmp/index.html

/ # httpd -h /tmp/
/ # netstat -nlt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 :::80                   :::*                    LISTEN      

/ # wget -O - -q 127.0.0.1
joined-containers
/ # ifconfig -a
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:648 (648.0 B)  TX bytes:0 (0.0 B)

2、创建容器b2,指明公用b1的网络

# 新开一个窗口,利用参数--network container:b1 指明公用b1的网络;
# 可以看到,b2和b1的网卡一样,监听的服务和端口一样,因为是同一个net namespace

[root@reg ~]# docker run --name b2 --rm -it --network container:b1 busybox
/ # netstat -nlt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 :::80                   :::*                    LISTEN      

/ # wget -O - -q 127.0.0.1
joined-containers
/ # ifconfig -a
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:648 (648.0 B)  TX bytes:0 (0.0 B)

# 看到,文件系统不共享;只是服务共享;
/ # ls /tmp/

joined模型图

​ 联邦网络模式其实还是bridge模型;联邦网络模型之下,2个以及以上的容器公用一个net namespace,但文件系统,user,等仍为隔离的;创建方法:先创建一个容器,然后在此容器基础之上,再创建容器时,指明网络为公用第一个容器的网络即可;

image-20201103193734153

主机网络:host-container

​ 该网络中容器,容器借用宿主机的网络,和宿主机公用一个tcp/ip协议栈;

实验

1、运行一个host网络的容器

# 从容器中看,可以发现监听的端口,网卡都是和宿主机一模一样;
# host网络的容器,不需要-p映射其中的服务,但是注意,和宿主机端口不能冲突;

[root@reg harbor]# docker run --name b1 --rm -it --network host busybox
/ # ifconfig 
br-97c0b3d84ade Link encap:Ethernet  HWaddr 02:42:41:8A:7B:64  
          inet addr:172.18.0.1  Bcast:172.18.255.255  Mask:255.255.0.0
          inet6 addr: fe80::42:41ff:fe8a:7b64/64 Scope:Link
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:79 errors:0 dropped:0 overruns:0 frame:0
          TX packets:94 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:3980 (3.8 KiB)  TX bytes:19082 (18.6 KiB)

docker0   Link encap:Ethernet  HWaddr 02:42:51:02:79:1C  
          inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
          inet6 addr: fe80::42:51ff:fe02:791c/64 Scope:Link
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:5 errors:0 dropped:0 overruns:0 frame:0
          TX packets:13 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:308 (308.0 B)  TX bytes:1026 (1.0 KiB)

eth0      Link encap:Ethernet  HWaddr 00:0C:29:2D:5D:7C  
          inet addr:192.168.80.101  Bcast:192.168.80.255  Mask:255.255.255.0
          inet6 addr: fe80::eb02:a6b5:be84:952/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:2382 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1278 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1054246 (1.0 MiB)  TX bytes:155717 (152.0 KiB)

eth1      Link encap:Ethernet  HWaddr 00:0C:29:2D:5D:86  
          inet addr:192.168.10.101  Bcast:192.168.10.255  Mask:255.255.255.0
          inet6 addr: fe80::7822:f591:feb0:47ea/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:48 errors:0 dropped:0 overruns:0 frame:0
          TX packets:14 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:4338 (4.2 KiB)  TX bytes:1040 (1.0 KiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:352 errors:0 dropped:0 overruns:0 frame:0
          TX packets:352 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:34827 (34.0 KiB)  TX bytes:34827 (34.0 KiB)


/ # netstat -nlt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      
tcp        0      0 :::22                   :::*                    LISTEN      
tcp        0      0 ::1:25                  :::*                    LISTEN   

2、host模式运行一个nginx容器


host模型图

​ host网络模型下,所有运行在该模式的容器,都不会获得单独的net namespace,而是公用宿主机的tcp/ip协议栈;

image-20201103191838447

docker两种跨主机网络模型

​ 以上四种网络模型,均为单机情况下,docker提供的网络模型;且生产主机不可能只有单主机;

​ 在多宿主机互联的情况下,docker另外提供了2种网络模型,分别是macvlan和overlay网络,

  • macvlan
  • overlay

实验:跨主机容器间通信(overlay)

实验环境:

host2:192.168.80.101
	docker0为172.17.10.1/24
host3:192.168.80.102
	docker0为172.17.20.1/24

防火墙和selinux全部关闭
2个宿主机的桥接网段不能在同一个网段,所以需要对默认的172.17.0.0/16做修改
  1. 修改2台宿主机的docker0网段

  2. 2台宿主机分别启动一个桥接网络的容器

  3. 2台宿主机分别添加一条静态路由,指向对方的物理网卡的ip

  4. 其中一台宿主机的物理网卡开启抓包

  5. 2容器间互ping测试

  6. 修改2台宿主机的docker0网段

    [root@host2 ~]# vim /usr/lib/systemd/system/docker.service 
    [Service]
    Type=notify
    # the default is not to use systemd for cgroups because the delegate issues still
    # exists and systemd currently does not support the cgroup feature set required
    # for containers run by docker
    ExecStart=/usr/bin/dockerd --bip=172.17.10.1/24
       
    # 在末尾加了--bip=172.17.10.1/24,指定了docker0上网卡地址,以及其网段;
       
    [root@host2 ~]# systemctl daemon-reload
    [root@host2 ~]# systemctl restart docker
       
    [root@host2 ~]# ifconfig docker0
    docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
            inet 172.17.10.1  netmask 255.255.255.0  broadcast 172.17.10.255
       
       
    ---
    同理,host2也对应修改
    [root@host3 ~]# grep bip !$ 
    grep bip /usr/lib/systemd/system/docker.service 
    ExecStart=/usr/bin/dockerd  --bip=172.17.20.1/24
       
    [root@host3 ~]# systemctl daemon-reload
    [root@host3 ~]# systemctl restart docker
       
    [root@host3 ~]# ifconfig docker0
    docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
            inet 172.17.20.1  netmask 255.255.255.0  broadcast 172.17.20.255
    
  7. 2台宿主机分别启动一个桥接网络的容器

    host2:

    [root@host2 ~]# docker run --name b1 -it busybox
    / # ifconfig 
    eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:0A:02  
              inet addr:172.17.10.2  Bcast:172.17.10.255  Mask:255.255.255.0
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:10 errors:0 dropped:0 overruns:0 frame:0
              TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0 
              RX bytes:836 (836.0 B)  TX bytes:0 (0.0 B)
       
    # 此时还无法ping通host3上的启停容器
    / # ping 172.17.20.2
    PING 172.17.20.2 (172.17.20.2): 56 data bytes
    ^C
    --- 172.17.20.2 ping statistics ---
    2 packets transmitted, 0 packets received, 100% packet loss
    / # route -n
    Kernel IP routing table
    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
    0.0.0.0         172.17.10.1     0.0.0.0         UG    0      0        0 eth0
    172.17.10.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
    

    host3:

    [root@host3 ~]# docker run --name b2 -it busybox
    / # ifconfig 
    eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:14:02  
              inet addr:172.17.20.2  Bcast:172.17.20.255  Mask:255.255.255.0
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:12 errors:0 dropped:0 overruns:0 frame:0
              TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0 
              RX bytes:1016 (1016.0 B)  TX bytes:0 (0.0 B)
       
    
  8. 2台宿主机分别添加一条静态路由,指向对方的物理网卡的ip

    host2:

    [root@host2 ~]# route add -net 172.17.20.0/24 gw 192.168.80.102
    [root@host2 ~]# route -n
    Kernel IP routing table
    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
    172.17.20.0     192.168.80.102  255.255.255.0   UG    0      0        0 eth0
       
    [root@host2 ~]# iptables -A FORWARD -s 192.168.80.0/24 -j ACCEPT
       
    

    host3:

    [root@host3 ~]# route add -net 172.17.10.0/24 gw 192.168.80.101
    [root@host3 ~]# route -n
    Kernel IP routing table
    172.17.10.0     192.168.80.101  255.255.255.0   UG    0      0        0 eth0
       
       
    [root@host3 ~]# iptables -A FORWARD -s 192.168.80.0/24 -j ACCEPT
       
    
  9. 其中一台宿主机的物理网卡开启抓包

    [root@host3 ~]# tcpdump -i eth0 -vnn icmp
    tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
    14:30:14.550012 IP (tos 0x0, ttl 63, id 6477, offset 0, flags [DF], proto ICMP (1), length 84)
        192.168.80.101 > 172.17.20.2: ICMP echo request, id 2816, seq 0, length 64
    14:30:14.550099 IP (tos 0x0, ttl 63, id 50101, offset 0, flags [none], proto ICMP (1), length 84)
        172.17.20.2 > 192.168.80.101: ICMP echo reply, id 2816, seq 0, length 64
    14:30:15.551182 IP (tos 0x0, ttl 63, id 6764, offset 0, flags [DF], proto ICMP (1), length 84)
       
    # 2台宿主机没配置上面接受来源是192.168.80.0/24的iptable规则时,是无法ping通,ping包有去无回,因为被宿主机过滤掉了
    # 添加后正常ping通,可以看出在host3的eth0上来看,来源ip是host2的物理网卡80.101,访问的是容器的桥接网段,反之亦然,因为是overlay叠加网络,数据包封装了2层ip头部,对于数据包的接收方来说,宿主机接收到之后,进到容器网段之前,看到的只是发送方容器所在宿主机的物理网卡的ip,即外层ip;
    
  10. 2容器间互ping测试

    / # ping 172.17.20.2
    PING 172.17.20.2 (172.17.20.2): 56 data bytes
    64 bytes from 172.17.20.2: seq=0 ttl=62 time=0.571 ms
    64 bytes from 172.17.20.2: seq=1 ttl=62 time=2.233 ms
       
    可以ping通;
    

dokcer网络模型总结

  • none无网络
  • host共享主机网络
  • bridge,也叫standlone网络,(默认网络)
    • 延伸1:joined-container联盟网络
  • overlay
  • macvlan

利用容器名通信

  1. 启动2个容器,正常启动

    [root@host2 ~]# docker run --name b1 --rm -it busybox
    / # ifconfig 
    eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:0A:02  
              inet addr:172.17.10.2  Bcast:172.17.10.255  Mask:255.255.255.0
       
       
    / # cat /etc/hosts
    127.0.0.1	localhost
    ::1	localhost ip6-localhost ip6-loopback
    fe00::0	ip6-localnet
    ff00::0	ip6-mcastprefix
    ff02::1	ip6-allnodes
    ff02::2	ip6-allrouters
    172.17.10.2	397b8c9382f4
       
    [root@host2 ~]# docker run --name b2 --rm -it busybox
    / # ifconfig 
    eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:0A:03  
              inet addr:172.17.10.3  Bcast:172.17.10.255  Mask:255.255.255.0
       
       
    / # cat /etc/hosts
    127.0.0.1	localhost
    ::1	localhost ip6-localhost ip6-loopback
    fe00::0	ip6-localnet
    ff00::0	ip6-mcastprefix
    ff02::1	ip6-allnodes
    ff02::2	ip6-allrouters
    172.17.10.3	50e37004077e
    / # ping 172.17.10.2
    PING 172.17.10.2 (172.17.10.2): 56 data bytes
    64 bytes from 172.17.10.2: seq=0 ttl=64 time=0.210 ms
       
    # 启动的2个容器,可以通过ip互相ping通,但是无法通过主机名,容器名,容器id实现互通,
    # 因为一hosts文件没有对应记录,二没有dns服务
    
  2. 启动第3个容器,加入--link参数

    [root@host2 ~]# docker run --name b3 --rm -it --link b1 --link b2 busybox
    / # cat /etc/hosts 
    127.0.0.1	localhost
    ::1	localhost ip6-localhost ip6-loopback
    fe00::0	ip6-localnet
    ff00::0	ip6-mcastprefix
    ff02::1	ip6-allnodes
    ff02::2	ip6-allrouters
    172.17.10.2	b1 397b8c9382f4
    172.17.10.3	b2 50e37004077e
    172.17.10.4	b629dc90c558
    # --link后跟,已经存在的容器名,可以在hosts文件中加入一条记录,从而实现利用主机名通信;
       
       
    / # ping b1
    PING b1 (172.17.10.2): 56 data bytes
    64 bytes from 172.17.10.2: seq=0 ttl=64 time=0.123 ms
    ^C
    --- b1 ping statistics ---
    1 packets transmitted, 1 packets received, 0% packet loss
    round-trip min/avg/max = 0.123/0.123/0.123 ms
    / # ping b2
    PING b2 (172.17.10.3): 56 data bytes
    64 bytes from 172.17.10.3: seq=0 ttl=64 time=0.107 ms
    ^C
    --- b2 ping statistics ---
    1 packets transmitted, 1 packets received, 0% packet loss
    round-trip min/avg/max = 0.107/0.107/0.107 ms
    

reference

updatedupdated2020-11-052020-11-05
加载评论