05-docker单主机容器通讯

本文深入探讨Docker的五种网络模式:bridge、host、none、容器间共享网络及自定义网络,解析每种模式的工作原理、优缺点,并通过实例展示自定义网络的创建与使用。

1. 概述

基于对net namespace的控制,docker可以为在容器创建隔离的网络环境,在隔离的网络环境下,容器具有完全独立的网络栈,与宿主机隔离,也可以使容器共享主机或者其他容器的网络命名空间,基本可以满足开发者在各种场景下的需要。按docker官方的说法,docker容器的网络有五种模式:

  • bridge:docker默认的网络模式,为容器创建独立的网络命名空间,容器具有独立的网卡等所有单独的网络栈,是最常用的使用方式。
  • host:直接使用容器宿主机的网络命名空间。
  • none:为容器创建独立网络命名空间,但不为它做任何网络配置,容器中只有lo,用户可以在此基础上,对容器网络做任意定制。
  • 其他容器:与host模式类似,只是容器将与指定的容器共享网络命名空间。
  • 用户自定义:docker 1.9版本以后新增的特性,允许容器使用第三方的网络实现或者创建单独的bridge网络,提供网络隔离能力。
1.1 bridge模式

bridge模式是docker默认的,也是开发者最常使用的网络模式。在这种模式下,docker为容器创建独立的网络栈,保证容器内的进程使用独立的网络环境,实现容器之间、容器与宿主机之间的网络栈隔离。同时,通过宿主机上的docker0网桥,容器可以与宿主机乃至外界进行网络通信。其网络模型可以参考下图:

在这里插入图片描述
从该网络模型可以看出,容器从原理上是可以与宿主机乃至外界的其他机器通信的。同一宿主机上,容器之间都是连接到docker0这个网桥上的,它可以作为虚拟交换机使容器可以相互通信。然而,由于宿主机的IP地址与容器veth pair的 IP地址均不在同一个网段,故仅仅依靠veth pair和namespace的技术,还不足以使宿主机以外的网络主动发现容器的存在。为了使外界可以方位容器中的进程,docker采用了端口绑定的方式,也就是通过iptables的NAT,将宿主机上的端口端口流量转发到容器内的端口上

很明显,bridge模式的容器与外界通信时,必定会占用宿主机上的端口,从而与宿主机竞争端口资源,对宿主机端口的管理会是一个比较大的问题。同时,由于容器与外界通信是基于三层上iptables NAT,性能和效率上的损耗是可以预见的。

1.2 host模式

由于容器和宿主机共享同一个网络命名空间,换言之,容器的IP地址即为宿主机的IP地址。所以容器可以和宿主机一样,使用宿主机的任意网卡,实现和外界的通信。其网络模型可以参照下图:

在这里插入图片描述

采用host模式的容器,可以直接使用宿主机的IP地址与外界进行通信,若宿主机具有公有IP,那么容器也拥有这个公有IP。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行NAT转换,而且由于容器通信时,不再需要通过linux bridge等方式转发或者数据包的拆封,性能上有很大优势。当然,这种模式有优势,也就有劣势,主要包括以下几个方面:

  • 最明显的就是容器不再拥有隔离、独立的网络栈。容器会与宿主机竞争网络栈的使用,并且容器的崩溃就可能导致宿主机崩溃,在生产环境中,这种问题可能是不被允许的。
  • 容器内部将不再拥有所有的端口资源,因为一些端口已经被宿主机服务、bridge模式的容器端口绑定等其他服务占用掉了。
1.3 none模式

在这种模式下,容器有独立的网络栈,但不包含任何网络配置,只具有lo这个loopback网卡用于进程通信。也就是说,none模式为容器做了最少的网络设置,但是俗话说得好“少即是多”,在没有网络配置的情况下,通过第三方工具或者手工的方式,开发这任意定制容器的网络,提供了最高的灵活性。

用处:避免主机生成的任何密码或随机值被其他主机窃取,用于安全、生成随机码

1.4 其他容器

其他网络模式是docker中一种较为特别的网络的模式。在这个模式下的容器,会使用其他容器的网络命名空间,其网络隔离性会处于bridge桥接模式与host模式之间。当容器共享其他容器的网络命名空间,则在这两个容器之间不存在网络隔离,而她们又与宿主机以及除此之外其他的容器存在网络隔离。其网络模型可以参考下图:
在这里插入图片描述
在这种模式下的容器可以通过localhost来同一网络命名空间下的其他容器,传输效率较高。而且这种模式还节约了一定数量的网络资源,但它并没有改变容器与外界通信的方式。在一些特殊的场景中非常有用,例如,kubernetes的pod,kubernetes为pod创建一个基础设施容器,同一pod下的其他容器都以其他容器模式共享这个基础设施容器的网络命名空间,相互之间以localhost访问,构成一个统一的整体。

# docker run -itd --name web1 httpd
# docker run -it --network container:web1 httpd
1.5 自定义网络

在用户定义网络模式下,开发者可以使用任何docker支持的第三方网络driver来定制容器的网络。并且,docker 1.9以上的版本默认自带了bridge和overlay两种类型的自定义网络driver。可以用于集成calico、weave、openvswitch等第三方厂商的网络实现。

除了docker自带的bridge driver,其他的几种driver都可以实现容器的跨主机通信。而基于bdrige driver的网络,docker会自动为其创建iptables规则,保证与其他网络之间、与docker0之间的网络隔离。

bridge driver的所有行为都和默认的bridge模式完全一致。而overlay及其他driver,则可以实现容器的跨主机通信。

2. 操作部分:单主机网络—>bridge的默认设置与自定义

2.1 认识默认的docker网络
[root@localhost ~]# docker pull busybox
Using default tag: latest
latest: Pulling from library/busybox
ff5eadacfa0b: Pull complete 
Digest: sha256:6dce4a9c1635c4c9b6a2b645e6613fa0238182fe13929808ee2258370d0f3497
Status: Downloaded newer image for busybox:latest
[root@localhost ~]# docker run -itd --name box1 busybox
8f2742fe263767f550558751a04691d1d09c8a880133b16e79c69fabadc15a64
[root@localhost ~]# docker exec -it box1 /bin/sh
/ # ip a
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
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

# 这里的6和7为全局网卡编号,可以看出容器的eth0网卡连接主机的7号网卡
# 我们退会主机查看一下7号

[root@localhost ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:a8:ff:a8 brd ff:ff:ff:ff:ff:ff
    inet 192.168.20.121/24 brd 192.168.20.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fea8:ffa8/64 scope link 
       valid_lft forever preferred_lft forever
7: veth6431297@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP 
    link/ether b2:69:41:f1:1c:cf brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::b069:41ff:fef1:1ccf/64 scope link 
       valid_lft forever preferred_lft forever

#查看主机的网卡信息,也可以看出来7号连接6号 且7号的网卡名是veth6431297
# 接下来我们看下,veth的这块网卡连接谁

[root@localhost ~]# brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.0242645ced6f	no		veth6431297
virbr0		8000.5254002dca20	yes		virbr0-nic

# 可以看出veth连接的是docker0网桥,这与前边我们讲的理论相吻合

整体逻辑:整体逻辑 容器网卡eth0 连接 网络命名空间 veth6431297,命名空间连接docker0
2.2 自建docker网络

细心的同学已经看到,在刚才的容器里,采用的是桥接网络,ip是172.17.0.2/16,我们也可以自己建立一个bridge网络,自己家里的bridge,如果没有指定网段,默认会在原来的网段上+1,变成172.18.0.0/16这个网段的ip

[root@localhost ~]# docker network create --driver bridge br1
5665c2db709020175ce8aa1c9e82e5fc00e4a9eee5663f24c9f3e33245b1be37
[root@localhost ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
5665c2db7090        br1                 bridge              local
0628284ab55f        bridge              bridge              local
11133ab29281        host                host                local
30e06b21eaad        none                null                local
[root@localhost ~]# brctl show
bridge name	bridge id		STP enabled	interfaces
br-5665c2db7090		8000.0242e18bb37b	no		
docker0		8000.0242645ced6f	no		veth6431297
virbr0		8000.5254002dca20	yes		virbr0-nic

#可以看出,新添加的名字是br1的网卡,id编号是5665c2db7090,下边我们来看一下它的详细信息

[root@localhost ~]# docker network inspect 5665c2db7090
[
    {
        "Name": "br1",
        "Id": "5665c2db709020175ce8aa1c9e82e5fc00e4a9eee5663f24c9f3e33245b1be37",
        "Created": "2019-06-14T09:35:46.932806841+08:00",
        "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,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

可以看到subnet字段:      "Subnet": "172.18.0.0/16", 与我们说的相同
下边我们来看一下,容器如何使用这个新定义的网络

[root@localhost ~]# docker run -itd --name box2 --network br1 busybox
426d726c423ab8b8aeeece1e0887a900a77b483e158937f81fb94214e8106716
[root@localhost ~]# docker exec -it box2 /bin/sh
/ # ip a
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
9: eth0@if10: <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 eth0
       valid_lft forever preferred_lft forever
/ # exit
[root@localhost ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:a8:ff:a8 brd ff:ff:ff:ff:ff:ff
    inet 192.168.20.121/24 brd 192.168.20.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fea8:ffa8/64 scope link 
       valid_lft forever preferred_lft forever
      ······
10: veth92a8542@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-5665c2db7090 state UP 
    link/ether 26:7c:3b:18:ba:7d brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::247c:3bff:fe18:ba7d/64 scope link 
       valid_lft forever preferred_lft forever
[root@localhost ~]# brctl show
bridge name	bridge id		STP enabled	interfaces
br-5665c2db7090		8000.0242e18bb37b	no		veth92a8542
docker0		8000.0242645ced6f	no		veth6431297
virbr0		8000.5254002dca20	yes		virbr0-nic

这里的表示方法br-5665c2db7090 前边的br表示是桥接网络,也就是bridge,后边的编号就是我们
之前通过docker network ls查看到的br1的network id
2.3 自定义网段的bridge网络
1) 自动分配容器ip
[root@localhost ~]# docker network create --driver bridge --subnet 182.16.23.2/24 --gateway 182.16.23.1 br3
50f8e1974b393a00f6fad8579d638707a87ee575eb17765ec74356212a517d04
[root@localhost ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
5665c2db7090        br1                 bridge              local
76f956a053a2        br2                 bridge              local
50f8e1974b39        br3                 bridge              local
0628284ab55f        bridge              bridge              local
11133ab29281        host                host                local
30e06b21eaad        none                null                local
[root@localhost ~]# brctl show
bridge name	bridge id		STP enabled	interfaces
br-50f8e1974b39		8000.024238623b3a	no		#此处没有连接的veth网卡
br-5665c2db7090		8000.0242e18bb37b	no		veth92a8542
br-76f956a053a2		8000.0242fbebe518	no		veth2932623
docker0		8000.0242645ced6f	no		veth6431297
virbr0		8000.5254002dca20	yes		virbr0-nic
[root@localhost ~]# docker run -itd --name box4 --network br3 busybox
ae565251a3e297cd2b99eaeb619138f980a7f3ea173b2a437340397e049ea714
[root@localhost ~]# docker exec -it box4 /bin/sh
/ # ip a
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
15: eth0@if16: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:b6:10:17:02 brd ff:ff:ff:ff:ff:ff
    inet 182.16.23.2/24 brd 182.16.23.255 scope global eth0
       valid_lft forever preferred_lft forever
2)手动指定容器ip
[root@localhost ~]# docker run -itd --name box5 --network br3 --ip 182.16.23.22 busybox
73d2c2cf69b1f8ebd2f06f073816975acd6277cf0915873d80aa6b4ffe5aac9a
[root@localhost ~]# docker exec -it box5 /bin/sh
/ # ip a
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
17: eth0@if18: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:b6:10:17:16 brd ff:ff:ff:ff:ff:ff
    inet 182.16.23.22/24 brd 182.16.23.255 scope global eth0
       valid_lft forever preferred_lft forever
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值