zoukankan      html  css  js  c++  java
  • docker系列(三) docker的网络模式之内部通信

    简介

    关于docker的安装文档,请参照上篇文章<docker系列二在宿主机上的安装和卸载>,本文主要针对docker中容器间的通信方式之内部通信进行说明。

    容器间的通信

    自从docker容器出现,容器的网络通信一直是众人关注的焦点,而容器的网络方案又可以分为两大部分:

    1. 单主机的容器间通信;
    2. 跨主机的容器间通信。

    单主机Docker网络通信

    我们在使用docker run创建 Docker 容器时,可以使用--network=选项指定容器的网络模式,Docker 有以下 4 种网络模式:

    • host 模式,使用--network=host指定,不支持多主机;
    • bridge 模式,使用--network=bridge指定,默认设置,不支持多主机;
    • container 模式,使用--network=container:NAME_or_ID指定,即joiner 容器,不支持多主机;
    • none 模式,使用--network=none指定,不支持多主机。

    bridge模式

    bridge之使用默认网桥

    当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。从docker0子网中分配一个 IP 给容器使用,并设置 docker0 的 IP 地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker 将 veth pair 设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到 docker0 网桥中。可以通过brctl show命令查看。安装brctl命令:

    yum install -y bridge-utils 
    [root@linux-node4 ~]# brctl show
    bridge name     bridge id               STP enabled     interfaces
    docker0         8000.0242d84b7159       no
    

    bridge模式是 docker 的默认网络模式,不写–net参数,就是bridge模式。使用docker run -p时,docker 实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。bridge模式如下图所示:

    实验过程如下:

    • 步骤一:创建两个容器
      docker run   --name docker1      nginx:1.13.12
      docker run -d --name docker2 nginx:1.13.12
      
    • 步骤二:查看机器上多了两个veth虚拟网卡,查看网络地址如我们之前说的一样
    [root@linux-node4 ~]# 
    [root@linux-node4 ~]# brctl show
    bridge name     bridge id               STP enabled     interfaces
    docker0         8000.0242d84b7159       no              veth8c72f4a
                                                            vethf15e034
                             [root@linux-node4 ~]# docker ps
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
    75539117a127        nginx:1.13.12       "nginx -g 'daemon of…"   About an hour ago   Up About an hour    80/tcp              docker2
    69f1c16d206c        nginx:1.13.12       "nginx -g 'daemon of…"   About an hour ago   Up About an hour    80/tcp              docker1    
    [root@linux-node4 ~]# docker inspect 75539117a127 |grep 172.17
                "Gateway": "172.17.0.1",
                "IPAddress": "172.17.0.3",
                        "Gateway": "172.17.0.1",
                        "IPAddress": "172.17.0.3",
    

    bridge之使用自定义网桥

    使用自定义的网桥

     docker network create -d bridge my-net4  --subnet=192.168.100.1/24
    

    创建一个自定义网桥-d指定模式为bridge,也可以为overlay,--subnet指定子网范围;
    创建两个容器,并连接到我们自建的网桥:

    [root@linux-node4 ~]# docker run -d --name=my_test1  --network my-net4 nginx:1.13.12
    ffc47de3992c52730ff2590b4b3903fe737521b9c713170d19b747fa2941c8b1
    

    查看容器的网络地址,验证其ip地址是否是我们自定义的网络。

    [root@linux-node4 ~]# docker inspect ffc47de3992 |grep 192
                        "Gateway": "192.168.100.1",
                        "IPAddress": "192.168.100.2",
    

    注意同一个网桥内的网络是相互可以通信的,本篇不做过多说明。

    host模式

    如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个 Network Namespace。容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。 Host模式如下图所示:

    验证步骤如下:

    创建一个网络类型为host的容器
    docker run  -d --net=host --name=my_host1  nginx:1.13.12 
    

    因为nginx容器本身的端口号是80,所以我们直接使用本地的接口来访问宿主机的ip和端口号。

    [root@linux-node4 ~]# !curl
    curl http://127.0.0.1:80 
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
        body {
             35em;
            margin: 0 auto;
            font-family: Tahoma, Verdana, Arial, sans-serif;
        }
    </style>
    </head>
    <body>
    <h1>Welcome to nginx!</h1>
    <p>If you see this page, the nginx web server is successfully installed and
    working. Further configuration is required.</p>
    
    <p>For online documentation and support please refer to
    <a href="http://nginx.org/">nginx.org</a>.<br/>
    Commercial support is available at
    <a href="http://nginx.com/">nginx.com</a>.</p>
    
    <p><em>Thank you for using nginx.</em></p>
    </body>
    </html>
    

    如果使用这种网络模式的时候注意不要一个容器启动多个实例,会引起端口冲突不能起来,这种网络模型是无法使用nat转化的。
    host模式有利也有弊,主要包括以下缺点:

    • 容器没有隔离、独立的网络栈:容器因为与宿主机共享网络而争抢资源,并且容易崩溃也可能导致主机崩溃,这在生产环境是不允许发生的;
    • 端口资源:docker host上已经使用的端口就不能再使用了
      host模式的优点如下:
    • 可以直接使用宿主机ip与外界通信,无需额外进行nat转换,由于容器与外部通信,不再需要使用bridge等方式转发或者进行数据包的封装,性能上有很大优势。

    container模式

    这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。 Container模式示意图:

    我们还是通过实验来验证这个结论吧,上文我们已经创建了一个自定义网桥的容器,链接到这个容器里面即可

    [root@linux-node4 ~]#  docker run -d --name docker_con3 --net=container:ffc47de3992c busybox sleep 6000 
    933dd7fce1a67883869a6235c3a4f7835c983e079592087734715d05f6bd755e
    
    进入容器内部验证网络是否跟预期一致:
    [root@linux-node4 ~]# docker exec -it  933dd7fce1a6 sh     
    / # ip addr
    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
    33: eth0@if34: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
        link/ether 02:42:c0:a8:64:02 brd ff:ff:ff:ff:ff:ff
        inet 192.168.100.2/24 brd 192.168.100.255 scope global eth0
           valid_lft forever preferred_lft forever
    / # route -n 
    Kernel IP routing table
    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
    0.0.0.0         192.168.100.1   0.0.0.0         UG    0      0        0 eth0
    192.168.100.0   0.0.0.0         255.255.255.0   U     0      0        0 eth0
    

    None模式

    使用none模式,Docker 容器拥有自己的 Network Namespace,但是,并不为Docker 容器进行任何网络配置。也就是说,这个 Docker 容器没有网卡、IP、路由等信息。需要我们自己为 Docker 容器添加网卡、配置 IP 等。 None模式示意图:

    [root@linux-node4 ~]#  docker run -d  --net=none  --name docker_none2  busybox  sleep 6000    
    247fb9eace8b5dedcb47b7f2015eb06f18d4eb67eb323560dcfaaf7ef1069773
    网络情况验证:
    [root@linux-node4 ~]# docker exec -it  247fb9eace8b  /bin/sh 
    / # ip addr
    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
    / # route -n 
    Kernel IP routing table
    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
    / # 
    
  • 相关阅读:
    powerdesigner设置主键为自增字段,设置非主键为唯一键并作为表的外键
    关于window.event.srcElement 和 window.event.target(触发事件的对象)
    JS遍历Table的所有单元格内容
    创Wcf案例数据服务
    jstack和线程dump分析
    Chromium Graphics: GPUclient的原理和实现分析之间的同步机制-Part II
    oracle11g导出空表
    java序列化是什么和反序列化和hadoop序列化
    【leetcode列】3Sum
    【POJ1741】Tree 树分而治之 模板略?
  • 原文地址:https://www.cnblogs.com/chenxiba/p/11327933.html
Copyright © 2011-2022 走看看