docker 网络

作者: 赵阳_c149 | 来源:发表于2019-10-24 14:09 被阅读0次

    docker容器功能强大,部分原因是容器可以通过网络连接到其他容器和非容器的实体。在网络通讯的过程中,对于docker容器上的部署的应用来说,部署在docker环境中还是部署在非docker环境中,是没有任何区别的。

    docker容器的网络通常有以下几种模式

    1. bridge

    bridge:-net=bridge, 默认网络,Docker启动或创建一个docker0网桥,默认创建的容器也是添加到这个网桥中。

    ifconfig
    
    docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
            inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
            inet6 fe80::42:92ff:fe3a:7063  prefixlen 64  scopeid 0x20<link>
            ether 02:42:92:3a:70:63  txqueuelen 0  (Ethernet)
            RX packets 42  bytes 7456 (7.2 KiB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 1989  bytes 209250 (204.3 KiB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    

    可以看到docker0是docker容器的默认网关,网关ip为172.17.0.1。
    创建一个容器

    docker run -it 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:7 errors:0 dropped:1 overruns:0 frame:0
              TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0 
              RX bytes:755 (755.0 B)  TX bytes:0 (0.0 B)
    
    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:0 
              RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
    
    

    可以看到,默认情况下,docker为容器创建了一个网卡接口eth0。容器通过这个接口和宿主机进行网络通讯。

    2. Host

    -net=host 容器不会获得一个独立的network namespace,而是与宿主机共用一个。这就意味着容器不会有自己的网卡信息,而是使用宿主机的。容器除了网络,其他都是隔离的。

    尝试以host的模式创建容器,然后进入容器,查看网络配置:

    docker run -it --net=host busybox
    docker0   Link encap:Ethernet  HWaddr 02:42:92:3A:70:63  
              inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
              inet6 addr: fe80::42:92ff:fe3a:7063/64 Scope:Link
              UP BROADCAST MULTICAST  MTU:1500  Metric:1
              RX packets:42 errors:0 dropped:0 overruns:0 frame:0
              TX packets:1991 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0 
              RX bytes:7456 (7.2 KiB)  TX bytes:209502 (204.5 KiB)
    
    eth0      Link encap:Ethernet  HWaddr 00:21:F6:15:86:04  
              inet addr:10.245.253.136  Bcast:10.245.255.255  Mask:255.255.248.0
              inet6 addr: 2606:b400:2010:6863:221:f6ff:fe15:8604/64 Scope:Global
              inet6 addr: fe80::221:f6ff:fe15:8604/64 Scope:Link
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:255654103 errors:0 dropped:0 overruns:0 frame:0
              TX packets:6224902 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:1000 
              RX bytes:24689037382 (22.9 GiB)  TX bytes:925742378 (882.8 MiB)
    
    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:114432 errors:0 dropped:0 overruns:0 frame:0
              TX packets:114432 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0 
              RX bytes:26104761 (24.8 MiB)  TX bytes:26104761 (24.8 MiB)
    

    此时显示的网络配置和宿主机一样。

    3.None

    -net=none 获取独立的network namespace,但不为容器进行任何网络配置,需要我们手动配置。

    尝试以None的模式创建容器,然后进入容器,查看网络配置:

    docker run -it --net=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:0 
              RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
    

    此时,ip和namespace都需要自定义配置。

    4. Container

    -net=container:Name/ID 与指定的容器使用同一个network namespace,具有同样的网络配置信息,两个容器除了网络,其他都是隔离的。

    尝试以默认的模式创建容器:

    docker run -d --name nginx01 --net nginx
    

    因为该容器并没有暴露端口,在容器外无法访问。

    现在创建另外一个容器,并暴露端口:

    docker run -itd --name bs -p 99:80 busybox
    

    重新创建nginx容器,并设置网络为container模式:

    docker run -d --name nginx01 --net container:bs nginx
    

    现在,nginx01容器是可以在容器外面访问的:

    curl 172.17.0.2:80
    

    进入容器bs:

    docker exec -it bs sh
    

    查看监听短端口,发现80端口已经在容器bs上被监听了。

    netstat -antp
    Active Internet connections (servers and established)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -
    tcp        0      0 :::16385                :::*                    LISTEN      -
    
    5. 自定义

    与默认的bridge原理一样,但自定义网络具备内部DNS发现,可以通过容器名或者主机名容器之间网络通信。

    创建两个容器:

    docker run -itd --name bs1 busybox
    docker run -itd --name bs2 busybox
    

    分别进入并查看网络配置:

    docker exec -it bs1 sh
    
    ifconfig
    eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:03  
              inet addr:172.17.0.3  Bcast:172.17.255.255  Mask:255.255.0.0
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:14 errors:0 dropped:2 overruns:0 frame:0
              TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0 
              RX bytes:1910 (1.8 KiB)  TX bytes:434 (434.0 B)
    
    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:0 
              RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
    
    docker exec -it bs2 sh
    
    / # ifconfig
    eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:04  
              inet addr:172.17.0.4  Bcast:172.17.255.255  Mask:255.255.0.0
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:16 errors:0 dropped:6 overruns:0 frame:0
              TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0 
              RX bytes:2298 (2.2 KiB)  TX bytes:0 (0.0 B)
    
    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:0 
              RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
    

    在两个容器中,互相无法ping通:

    ping bs1
    ping: bad address 'bs1'
    
    ping bs2
    ping: bad address 'bs2'
    

    创建网络:

    docker network create bs-test
    

    用新创建的网络重新创建容器

    docker run -it --name bs3 --net=bs-test busybox
    docker run -it --name bs4 --net=bs-test busybox
    

    进入容器之后,可以看到ping ps3 和ping ps4成功了。

    6. overlay

    一个可以跨宿主机的bridge network。常用于docker swarm集群。用户可以选择对容器之间的网络通讯进行加密。Docker swarm和K8S都是容器编排工具。K8S 支持复杂度更高的需求,主要用于生产环境。而docker swarm主要提供一个易于入手的解决方案,部署简单而快速。因此在现实的工作中,容器编排主要通过K8S实现。随着k8s的普及,已经很少有人用了【1】,所以就不再详细介绍。

    docker网络通讯原理

    由于docker网络通讯的原理较为复杂,本文仅以最基本的bridge0为例简单介绍。更多说明请参照官方文档【2】。

    这是Docker网络的默认选项,docker启动后创建一个docker0网桥,所有默认创建的容器将自动加入这个网络命名空间。Bridge顾名思义,就是网桥,工作于数据链路层,是一个虚拟的二层交换机。在网桥内,有一个表,存储着MAC地址和IP地址间的映射。同时,网桥还可以对传输数据进行校验。区别router,router主要用于不同网路之间的通讯,如以太网和ATM网,以IP为操作对象;区别集线器,集线器主要用于信号加强,以广播的形式传递数据。关于docker是如何操作iptable的规则以实现网络隔离的细节,可以参考官方文档【3】【4】

    宿主机和容器之间的网络通信是通过一对网络接口实现的。

    • 在宿主机上就是veth
    • 在容器内部就是eth0


      docker_nw.png

    具体来说,宿主机和容器之间的网络通讯形式又有两种:


    network.png
    1. 从容器到外界: 容器的eth0->veth1(虚拟网桥bridge0的容器端接口veth6eb0c0d)->docker0(SNAT源地址转换)->宿主机eth0->外界

    2. 从外界到容器:外界 ->宿主机(DNAT目标地址转换)->docker0->eth0veth1(虚拟网桥bridge0的容器端接口veth6eb0c0d)->容器的eth0

    宿主机主要网络配置

    1. 虚拟网桥:docker0
    2. 自定义网桥:br-fe392ff4421e
    3. 宿主机对外接口:eth0
    4. 虚拟网桥在宿主机端的接口:veth6eb0c0d
    ifconfig
    br-fe392ff4421e: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
            inet 172.18.0.1  netmask 255.255.0.0  broadcast 172.18.255.255
            inet6 fe80::42:4cff:fe16:b709  prefixlen 64  scopeid 0x20<link>
            ether 02:42:4c:16:b7:09  txqueuelen 0  (Ethernet)
            RX packets 71  bytes 10542 (10.2 KiB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 2978  bytes 313242 (305.9 KiB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
            inet6 fe80::42:92ff:fe3a:7063  prefixlen 64  scopeid 0x20<link>
            ether 02:42:92:3a:70:63  txqueuelen 0  (Ethernet)
            RX packets 71  bytes 10542 (10.2 KiB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 2978  bytes 313242 (305.9 KiB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 10.245.253.136  netmask 255.255.248.0  broadcast 10.245.255.255
            inet6 2606:b400:2010:6863:221:f6ff:fe15:8604  prefixlen 64  scopeid 0x0<global>
            inet6 fe80::221:f6ff:fe15:8604  prefixlen 64  scopeid 0x20<link>
            ether 00:21:f6:15:86:04  txqueuelen 1000  (Ethernet)
            RX packets 260560943  bytes 25092797886 (23.3 GiB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 6330084  bytes 941913458 (898.2 MiB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
            inet 127.0.0.1  netmask 255.0.0.0
            inet6 ::1  prefixlen 128  scopeid 0x10<host>
            loop  txqueuelen 0  (Local Loopback)
            RX packets 116380  bytes 26552635 (25.3 MiB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 116380  bytes 26552635 (25.3 MiB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    veth6eb0c0d: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet6 fe80::506c:dcff:fe3a:d609  prefixlen 64  scopeid 0x20<link>
            ether 52:6c:dc:3a:d6:09  txqueuelen 0  (Ethernet)
            RX packets 6  bytes 434 (434.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 68  bytes 14075 (13.7 KiB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    

    【1】Docker swarm vs kubernetes
    【2】docker network
    【3】iptables
    【4】networking

    相关文章

      网友评论

        本文标题:docker 网络

        本文链接:https://www.haomeiwen.com/subject/bkwrvctx.html