精华内容
下载资源
问答
  • DOCKER容器宿主机同网段互相通信

    千次阅读 2020-08-23 17:06:16
    Docker容器时间与宿主机同步 使用Docker搭建WordPress博客 Docker私有仓库搭建及镜像删除 Docker镜像的导入导出 在Docker上部署Ambari 博主最近在解决docker与宿主机同网段通信的问题,写此文章记录一下整个过程。...

    相关阅读:

    Docker容器时间与宿主机同步

    使用Docker搭建WordPress博客

    Docker私有仓库搭建及镜像删除

    Docker镜像的导入和导出

    在Docker上部署Ambari


    博主最近在解决docker与宿主机同网段通信的问题,写此文章记录一下整个过程。

     

     

    遇到的问题

    博主用两台docker容器做datanode,当时配置Docker网络时,使用了Bridge模式,docker0网段(172.0.1.x),宿主机网段(192.1.1.x),使用外部客户端请求下载HDFS文件,去指定的datanode上拉去数据时,外部客户端无法连接到内部的docker容器,抛出的等待超时异常,并重试下载,更换请求的下载地址为可连接的宿主机datanode后, 才成功下载数据。

    于是,想要对docker的网络配置进行修改,将docker容器的IP地址设置成与宿主机同网段,并且相互连通。

     

     


    这里先要来说一下docker网络的四种方式:

    1.Host模式:

    Host 模式并没有为容器创建一个隔离的网络环境。

    该模式下的Docker 容器会和Host宿主机共享同一个网络namespace, Docker Container可以和宿主机一样,使用宿主机的eth0,实现和外界的通信。

    Host模式特点包括:

    • 容器没有隔离的 network namespace
    • 容器的 IP 地址同 Docker host 的 IP 地址
    • 注意:容器中服务端口号不能与Host宿主机上已经使用的端口号相冲突
    • host 模式能够和其它模式共存

    2.Container模式

    Container网络模式是 Docker 中一种较为特别的网络的模式。处于这个模式下的 Docker 容器会共享其他容器的网络环境,因此,至少这两个容器之间不存在网络隔离,而这两个容器又与宿主机以及除此之外其他的容器存在网络隔离。

    3.None模式

    None 网络就是什么都没有的网络。挂在这个网络下的容器除了 lo,没有其他任何网卡。需要我们自行去配置。

    4.Bridge模式

    Docker 容器默认使用Bridge模式的网络。

    Docker的Bridge模式和VM虚拟机的Bridge模式不同,虽然也叫Bridge,但实质上类似于VM的NAT模式。

    原理是在宿主机上虚出一块网卡bridge0,然后所有容器会桥接在这块网卡的网段上。默认情况下容器能访问外部网络,但外部网络无法访问容器,需要通过暴露容器端口的方式(docker run -p)让外部网络访问容器内的服务。

     


    看完了上面的介绍,当前使用的Bridge模式不适合场景,修改网络配置。

    写一下曾经试过的几种方法:

    注意:

    如果你需要宿主机与Docker容器互通,前面两种办法不要试!!!不好使!!!

    如果你仅需要Docker容器与宿主机网段相同,容器与其他同网段节点相互通信,不与宿主机进行通信,可以使用第一种方法!!

    第一种办法:

    创建docker  macvlan

    Docker官方在1.12版本之后引入了macvlan网络驱动,可以更简单的为容器配置桥接网络

    介绍一下macvlan:

    macvlan的原理是在宿主机物理网卡上虚拟出多个子网卡,通过不同的MAC地址在数据链路层进行网络数据转发的,它是比较新的网络虚拟化技术,需要较新的内核支持(Linux kernel v3.9–3.19 and 4.0+)

     

     

    参数说明:

    -d macvlan  创建macvlan网络,使用macvlan网络驱动

    –subnet 指定宿主机所在网段

    –gateway 指定宿主机所在网段网关

     

    -o parent 继承指定网段的网卡

    测试一下:运行容器

     

     

    使用宿主机去ping 192.168.1.100,这时,问题出现了

     

     

    目的地址不可达,使用别的机器去ping 192.168.1.100,ping通了,进入容器内,也ping不同宿主机。

    使用macVLAN模式的容器,无法ping通宿主机,宿主机也无法ping通该容器,对其他同网段的服务器和容器都可以联通。

    第二种办法:

    在网上找到的另一种办法,编辑网卡配置文件

     

     

    重启网络的时候,整个网络都down了,需要去机房弄服务器接显示器修改,查找相关资料的时候,帖子大多是复制粘贴的,不知道该他们真正的试过了没有,此方法并不靠谱。

     

    第三种办法

    使用pipework为docker容器配置独立IP

    安装pipework

     

     

    创建两个容器实例,并不需要默认docker0网桥分配的172.17.0.1网段,设置为–net=none

    docker run -itd –name test1 –net=none  -h test1 centos /bin/bash    

    docker run -itd –name test1 –net=none  -h test2 centos /bin/bash

    接下来,使用pipework命令为容器设置固定IP

     

     

    pipework包含了200多行的shell脚本

    通过network namespace,veth pair以及linux bridge完成容器网络的设置,执行过程大概包括:

    查看主机是否包含br0网桥,如果不存在就创建,向容器实例test1添加一块网卡,并配置固定IP:192.168.1.53,若test1已经有默认的路由,则删除掉,将@后面的192.168.1.1设置为默认路由的网关,将test1容器实例连接到创建的br0上。

     

    进入test1容器中,测试与test2容器和网关的连通性

     

     

     

     

    说明上面的配置没有问题

    但是这时,还没有完,宿主机是ping不同容器的

    宿主机有两个网卡,em1和em2,em1作为管理口192.168.1.50,em2没有使用,现在,我们只需要将宿主机的em2网卡添加到br0网桥即可

     

     

    然后再进行相关的测试

    使用宿主机去ping 52/53

     

     

     

     

    进入容器去ping宿主机

     

     
     

    再使用window主机去测试

     

     
     

    到这里,问题总算解决了,在ambari上添加两台新配置的容器节点,并分配datanode角色,将原有的bridge网络节点删除即可,外部客户端请求下载HDFS文件不再抛出异常

    注意:pipework目前还有缺陷,容器重启后IP设置会自动消失,需要重新设置。

     

    展开全文
  • 在练习docker运行spring cloud项目的时候,我打算用两个容器运行eurekaconfig服务,使用docker-compose运行镜像,配置文件如下 version: '3' services: eureka: image: eureka # restart: always tty: true ...

    问题1

    在练习docker运行spring cloud项目的时候,我打算用两个容器运行eureka和config服务,使用docker-compose运行镜像,配置文件如下

    
    version: '3'
    services:
      eureka:
        image: eureka
    #    restart: always
        tty: true
        container_name: eureka
        network_mode: "host"
        environment:
          - TZ=Asia/Shanghai
      config:
        container_name: config
        image: config
        #    restart: always
        tty: true
        network_mode: "host"
        environment:
          - TZ=Asia/Shanghai
          - eureka.host=eureka
        depends_on:
          - eureka
    

    network_mode使用host模式,和宿主机共用网络,所以不需要指定端口映射。但是实际情况是宿主机无法访问,
    使用命令docker network inspect host 查看host网桥的配置,发现eureka和config服务确实在其中。

    后来查资料发现,因为我是在Windows环境安装的docker,docker实际上是安装在和Windows隔离的一个虚拟环境,host网络实际上那个虚拟环境的网络,所以Windows无法访问。

    解决办法:
    修改docker-compose.yml文件

    version: '3'
    services:
      eureka:
        image: eureka
    #    restart: always
        tty: true
        container_name: eureka
        network_mode:
        networks:
          - spring-cloud-demo
        environment:
          - TZ=Asia/Shanghai
        ports:
          - "20000:20000"
      config:
        container_name: config
        image: config
        #    restart: always
        tty: true
        networks:
          - spring-cloud-demo
        environment:
          - TZ=Asia/Shanghai
          - eureka.host=eureka
        ports:
          - "20004:20004"
        depends_on:
          - eureka
    networks:
      spring-cloud-demo:
        driver: bridge
    

    更换网桥,同时为了保证两个服务的通信,将服务置于同一个网桥下,暴露端口。

    问题2

    宿主机安装了MySQL,容器内部访问宿主机无法连接

    配置IP host.docker.internal为宿主机IP地址

    展开全文
  • docker容器间跨宿主机通信-基于overlayoverlay网络解析环境介绍consul安装配置创建overlay网络网络测试 overlay网络解析 内置跨主机的网络通信一直是Docker备受期待的功能,在1.9版本之前,社区中就已经有许多第三方...

    overlay网络解析

    内置跨主机的网络通信一直是Docker备受期待的功能,在1.9版本之前,社区中就已经有许多第三方的工具或方法尝试解决这个问题,例如Macvlan、Pipework、Flannel、Weave等。

    虽然这些方案在实现细节上存在很多差异,但其思路无非分为两种: 二层VLAN网络和Overlay网络

    简单来说,二层VLAN网络解决跨主机通信的思路是把原先的网络架构改造为互通的大二层网络,通过特定网络设备直接路由,实现容器点到点的之间通信。这种方案在传输效率上比Overlay网络占优,然而它也存在一些固有的问题。

    这种方法需要二层网络设备支持,通用性和灵活性不如后者。

    由于通常交换机可用的VLAN数量都在4000个左右,这会对容器集群规模造成限制,远远不能满足公有云或大型私有云的部署需求; 大型数据中心部署VLAN,会导致任何一个VLAN的广播数据会在整个数据中心内泛滥,大量消耗网络带宽,带来维护的困难。

    相比之下,Overlay网络是指在不改变现有网络基础设施的前提下,通过某种约定通信协议,把二层报文封装在IP报文之上的新的数据格式。这样不但能够充分利用成熟的IP路由协议进程数据分发;而且在Overlay技术中采用扩展的隔离标识位数,能够突破VLAN的4000数量限制支持高达16M的用户,并在必要时可将广播流量转化为组播流量,避免广播数据泛滥。

    因此,Overlay网络实际上是目前最主流的容器跨节点数据传输和路由方案。

    容器在两个跨主机进行通信的时候,是使用overlay network这个网络模式进行通信;如果使用host也可以实现跨主机进行通信,直接使用这个物理的ip地址就可以进行通信。overlay它会虚拟出一个网络比如10.0.2.3这个ip地址。在这个overlay网络模式里面,有类似于服务网关的地址,然后把这个包转发到物理服务器这个地址,最终通过路由和交换,到达另一个服务器的ip地址。
    1.png

    环境介绍

    hostname ip 系统版本
    cdh1 10.30.10.111 centos7
    cdh2 10.30.10.112 centos7

    consul安装配置

    要实现overlay网络,我们会有一个服务发现。比如说consul,会定义一个ip地址池,比如10.0.2.0/24之类的。上面会有容器,容器的ip地址会从上面去获取。获取完了后,会通过ens33来进行通信,这样就可以实现跨主机的通信。
    在这里插入图片描述
    consul通过docker部署在cdh1,首先需要修改cdh1中的docker配置并重启

    [root@cdh1 /]# vim /etc/docker/daemon.json
    //添加以下配置
    "live-restore":true
    [root@cdh1 /]# systemctl restart docker
    

    “live-restore”:true 此配置的作用为在docker守护程序停止或重启的时候,容器依然可以保持运行

    在cdh1下载consul镜像并启动

    [root@cdh1 /]# docker pull consul
    [root@cdh1 /]# docker run -d -p 8500:8500 -h consul --name consul consul
    

    修改cdh1中的docker配置并重启

    [root@cdh1 /]# vim /etc/docker/daemon.json
    # 添加以下两行配置
    "cluster-store": "consul://10.30.10.111:8500"
    "cluster-advertise": "10.30.10.111:2375"
    [root@cdh1 /]# systemctl restart docker
    

    修改cdh2中的docker配置并重启

    [root@cdh2 /]# vim /etc/docker/daemon.json
    # 添加以下两行配置
    "cluster-store": "consul://10.30.10.111:8500"
    "cluster-advertise": "10.30.10.112:2375"
    [root@cdh2 /]# systemctl restart docker
    

    cluster-store指定的是consul服务地址,因为consul服务运行在cdh1的8500端口,所以两台机器的cluster-store值均为consul://10.30.10.111:8500
    cluster-advertise指定本机与consul的通信端口,所以指定为本机的2375端口

    此时可以通过http://10.30.10.111:8500/访问consul地址
    Key/Value菜单中的docker-nodes目录中可以看到cdh1和cdh2两个docker节点,代表consul配置成功。
    在这里插入图片描述

    创建overlay网络

    此时我们可以创建overlay网络,首先查看目前节点中已有的网络类型

    [root@cdh1 /]# docker network ls
    NETWORK ID          NAME                DRIVER              SCOPE
    ab0f335423a1        bridge              bridge              local
    b12e70a8c4e3        host                host                local
    0dd357f3ecae        none                null                local
    

    然后在cdh1的docker节点创建overlay网络,因为此时consul服务发现已经正常运行,且cdh1和cdh2的docker服务已经接入,所以此时overlay网络是全局创建的,在任何一台宿主机创建一次即可。

    [root@cdh1 /]#  docker network create -d overlay my_overlay
    cafa97c5cf9d30dd6cef08a5e9710074c828cea3fdd72edb45315fb4b1bfd84c
    [root@cdh1 /]# docker network ls
    NETWORK ID          NAME                DRIVER              SCOPE
    ab0f335423a1        bridge              bridge              local
    b12e70a8c4e3        host                host                local
    cafa97c5cf9d        my_overlay          overlay             global
    0dd357f3ecae        none                null                local
    

    此时可以看到,创建的overlay网络,标识为golbal。我们可以查看cdh2的网络,可以发现overlay网络也已经创建完毕。

    [root@cdh2 ~]# docker network ls
    NETWORK ID          NAME                DRIVER              SCOPE
    90d99658ee8f        bridge              bridge              local
    19f844200737        host                host                local
    cafa97c5cf9d        my_overlay          overlay             global
    3986fe51b271        none                null                local
    

    网络测试

    创建完成后,我们可以在cdh1和cdh2中指定overlay网络创建docker容器,并进行测试,查看是否可以跨宿主机通信。

    在cdh1中创建名称为master的容器,并查看其IP

    [root@cdh1 /]# docker run -itd -h master --name master --network my_overlay centos7_update /bin/bash
    [root@cdh1 /]# docker inspect -f "{{ .NetworkSettings.Networks.my_overlay.IPAddress}}"  master
    10.0.0.2
    

    在cdh1中创建名称为slaver的容器,并查看其IP

    [root@cdh2 ~]# docker run -itd -h slaver --name slaver --network my_overlay centos7_update /bin/bash
    [root@cdh2 ~]# docker inspect -f "{{ .NetworkSettings.Networks.my_overlay.IPAddress}}"  slaver
    10.0.0.3
    

    此时进入两台容器中,互相ping对方的IP,查看是否成功通信

    [root@cdh1 ~]# docker exec -it master /bin/bash
    [root@master /]# ping 10.0.0.3
    PING 10.0.0.3 (10.0.0.3) 56(84) bytes of data.
    64 bytes from 10.0.0.3: icmp_seq=1 ttl=64 time=0.587 ms
    64 bytes from 10.0.0.3: icmp_seq=2 ttl=64 time=0.511 ms
    64 bytes from 10.0.0.3: icmp_seq=3 ttl=64 time=0.431 ms
    64 bytes from 10.0.0.3: icmp_seq=4 ttl=64 time=0.551 ms
    64 bytes from 10.0.0.3: icmp_seq=5 ttl=64 time=0.424 ms
    ^C
    --- 10.0.0.3 ping statistics ---
    5 packets transmitted, 5 received, 0% packet loss, time 4000ms
    rtt min/avg/max/mdev = 0.424/0.500/0.587/0.070 ms
    
    
    [root@cdh2 ~]# docker exec -it slaver /bin/bash
    [root@slaver /]# ping 10.0.0.2
    PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
    64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.499 ms
    64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.500 ms
    64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.410 ms
    64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=0.370 ms
    ^C
    --- 10.0.0.2 ping statistics ---
    4 packets transmitted, 4 received, 0% packet loss, time 3000ms
    rtt min/avg/max/mdev = 0.370/0.444/0.500/0.062 ms
    

    成功通信!

    展开全文
  • 自从Docker容器出现以来,容器的网络通信就一直是被关注的焦点,也是生产环境的迫切需求。容器的网络通信又可以分为两大方面:单主机容器上的相互通信主机的容器相互通信。   一、端口映射(局域网,外网此...

    自从Docker容器出现以来,容器的网络通信就一直是被关注的焦点,也是生产环境的迫切需求。容器的网络通信又可以分为两大方面:单主机容器上的相互通信,和跨主机的容器相互通信。

     

    一、端口映射(局域网,外网此方式均可)。

    此种方式是将容器的某个端口映射到宿主机的某个端口,其它主机访问容器提供的服务需要通过宿主机的IP进行访问:

    docker run -p 9000:8000 --name centos1_py2 -itd --privileged=true dockerstorage/centos_py2:latest /usr/sbin/init

    这种方式是在通过镜像创建容器的时候指定的,如图所示,加入我们在容器centos1_py2中用8000端口运行一个项目,通过此项配置就可以将容器的8000端口映射到宿主机的9000端口,那么其它主机就可以通过    宿主机的ip:9000来访问运行在容器中的项目了。

    注:

    • 容器有自己的内部网络和 ip 地址(使用 docker inspect 可以获取所有的变量,Docker 还可以有一个可变的网络配置。)
    • -p 标记可以多次使用来绑定多个端口 如:
    • docker run -p 9000:8000 -p 10000:80 --name centos1_py2 -itd --privileged=true dockerstorage/centos_py2:latest /usr/sbin/init

    注:也可以使用指定网络方式为host,这个模式下创建出来的容器,直接使用容器宿主机的网络命名空间。

    docker run  --name centos1_py2 -itd --privileged=true  --net=host dockerstorage/centos_py2:latest /usr/sbin/init

    这样在容器中运行程序就和在主机中运行的一样,访问主机的ip就可以访问运行的应用

    二、容器的IP可以被宿主机以及其它主机直接访问(局域网)。

     

    docker单主机容器通信

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    基于对net namespace的控制,docker可以为在容器创建隔离的网络环境,在隔离的网络环境下,容器具有完全独立的网络栈,与宿主机隔离,

    也可以使容器共享主机或者其他容器的网络命名空间,基本可以满足开发者在各种场景下的需要。

     

    按docker官方的说法,docker容器的网络有五种模式:

    1)bridge模式,--net=bridge(默认)

    这是dokcer网络的默认设置,为容器创建独立的网络命名空间,容器具有独立的网卡等所有单独的网络栈,是最常用的使用方式。

    在docker run启动容器的时候,如果不加--net参数,就默认采用这种网络模式。安装完docker,系统会自动添加一个供docker使用的网桥docker0,我们创建一个新的容器时,

    容器通过DHCP获取一个与docker0同网段的IP地址,并默认连接到docker0网桥,以此实现容器与宿主机的网络互通。

     

    2)host模式,--net=host

    这个模式下创建出来的容器,直接使用容器宿主机的网络命名空间。

    将不拥有自己独立的Network Namespace,即没有独立的网络环境。它使用宿主机的ip和端口。

     

    3)none模式,--net=none

    为容器创建独立网络命名空间,但不为它做任何网络配置,容器中只有lo,用户可以在此基础上,对容器网络做任意定制。

    这个模式下,dokcer不为容器进行任何网络配置。需要我们自己为容器添加网卡,配置IP。

    因此,若想使用pipework配置docker容器的ip地址,必须要在none模式下才可以。

     

    4)其他容器模式(即container模式),--net=container:NAME_or_ID

    与host模式类似,只是容器将与指定的容器共享网络命名空间。

    这个模式就是指定一个已有的容器,共享该容器的IP和端口。除了网络方面两个容器共享,其他的如文件系统,进程等还是隔离开的。

     

    5)用户自定义:docker 1.9版本以后新增的特性,允许容器使用第三方的网络实现或者创建单独的bridge网络,提供网络隔离能力。

    这些网络模式在相互网络通信方面的对比如下所示:

    南北向通信指容器与宿主机外界的访问机制,东西向流量指同一宿主机上,与其他容器相互访问的机制。

    host模式

    1

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

    1

    2

    3

    4

    5

    采用host模式的容器,可以直接使用宿主机的IP地址与外界进行通信,若宿主机具有公有IP,那么容器也拥有这个公有IP。同时容器内服务的端口也可以使用宿主机的端口,

    无需额外进行NAT转换,而且由于容器通信时,不再需要通过linuxbridge等方式转发或者数据包的拆封,性能上有很大优势。

    当然,这种模式有优势,也就有劣势,主要包括以下几个方面:

    1)最明显的就是容器不再拥有隔离、独立的网络栈。容器会与宿主机竞争网络栈的使用,并且容器的崩溃就可能导致宿主机崩溃,在生产环境中,这种问题可能是不被允许的。

    2)容器内部将不再拥有所有的端口资源,因为一些端口已经被宿主机服务、bridge模式的容器端口绑定等其他服务占用掉了。

    bridge模式

    1

    2

    3

    bridge模式是docker默认的,也是开发者最常使用的网络模式。在这种模式下,docker为容器创建独立的网络栈,保证容器内的进程使用独立的网络环境,

    实现容器之间、容器与宿主机之间的网络栈隔离。同时,通过宿主机上的docker0网桥,容器可以与宿主机乃至外界进行网络通信。

    其网络模型可以参考下图:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    从上面的网络模型可以看出,容器从原理上是可以与宿主机乃至外界的其他机器通信的。同一宿主机上,容器之间都是连接掉docker0这个网桥上的,它可以作为虚拟交换机使容器可以相互通信。

    然而,由于宿主机的IP地址与容器veth pair的 IP地址均不在同一个网段,故仅仅依靠veth pair和namespace的技术,还不足以使宿主机以外的网络主动发现容器的存在。为了使外界可以方位容器中的进程,docker采用了端口绑定的方式,也就是通过iptables的NAT,将宿主机上的端口

    端口流量转发到容器内的端口上。

     

    举一个简单的例子,使用下面的命令创建容器,并将宿主机的3306端口绑定到容器的3306端口:

    docker run -tid --name db -p 3306:3306 MySQL

     

    在宿主机上,可以通过iptables -t nat -L -n,查到一条DNAT规则:

     

    DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:3306 to:172.17.0.5:3306

     

    上面的172.17.0.5即为bridge模式下,创建的容器IP。

     

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

    none模式

    1

    2

    在这种模式下,容器有独立的网络栈,但不包含任何网络配置,只具有lo这个loopback网卡用于进程通信。也就是说,none模式为容器做了最少的网络设置,

    但是俗话说得好“少即是多”,在没有网络配置的情况下,通过第三方工具或者手工的方式,开发这任意定制容器的网络,提供了最高的灵活性

    其他容器(container)模式

    1

    2

    其他网络模式是docker中一种较为特别的网络的模式。在这个模式下的容器,会使用其他容器的网络命名空间,其网络隔离性会处于bridge桥接模式与host模式之间。

    当容器共享其他容器的网络命名空间,则在这两个容器之间不存在网络隔离,而她们又与宿主机以及除此之外其他的容器存在网络隔离。其网络模型可以参考下图:

    1

    2

    3

    在这种模式下的容器可以通过localhost来同一网络命名空间下的其他容器,传输效率较高。而且这种模式还节约了一定数量的网络资源,但它并没有改变容器与外界通信的方式。

    在一些特殊的场景中非常有用,例如,kubernetes的pod,kubernetes为pod创建一个基础设施容器,同一pod下的其他容器都以其他容器模式共享这个基础设施容器的网络命名空间,

    相互之间以localhost访问,构成一个统一的整体。

    用户定义网络模式

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

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

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

    保证与其他网络之间、与docker0之间的网络隔离。

    例如,使用下面的命令创建一个基于bridge driver的自定义网络:

     

    docker network create bri1

     

    则docker会自动生成如下的iptables规则,保证不同网络上的容器无法互相通信。

     

    -A DOCKER-ISOLATION -i br-8dba6df70456 -o docker0 -j DROP

    -A DOCKER-ISOLATION -i docker0 -o br-8dba6df70456 -j DROP

     

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

    docker跨主机容器通信

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    早期大家的跨主机通信方案主要有以下几种:

    1)容器使用host模式:容器直接使用宿主机的网络,这样天生就可以支持跨主机通信。虽然可以解决跨主机通信问题,但这种方式应用场景很有限,容易出现端口冲突,也无法做到隔离网络环境,

    一个容器崩溃很可能引起整个宿主机的崩溃。

     

    2)端口绑定:通过绑定容器端口到宿主机端口,跨主机通信时,使用主机IP+端口的方式访问容器中的服务。显而易见,这种方式仅能支持网络栈的四层及以上的应用,并且容器与宿主机紧耦合,

    很难灵活的处理,可扩展性不佳。

     

    3)docker外定制容器网络:在容器通过docker创建完成后,然后再通过修改容器的网络命名空间来定义容器网络。典型的就是很久以前的pipework,容器以none模式创建,pipework通过进入容器

    的网络命名空间为容器重新配置网络,这样容器网络可以是静态IP、vxlan网络等各种方式,非常灵活,容器启动的一段时间内会没有IP,明显无法在大规模场景下使用,只能在实验室中测试使用。

     

    4)第三方SDN定义容器网络:使用Open vSwitch或Flannel等第三方SDN工具,为容器构建可以跨主机通信的网络环境。这些方案一般要求各个主机上的docker0网桥的cidr不同,以避免出现IP冲突

    的问题,限制了容器在宿主机上的可获取IP范围。并且在容器需要对集群外提供服务时,需要比较复杂的配置,对部署实施人员的网络技能要求比较高。

     

     

    上面这些方案有各种各样的缺陷,同时也因为跨主机通信的迫切需求,docker 1.9版本时,官方提出了基于vxlan的overlay网络实现,原生支持容器的跨主机通信。同时,还支持通过libnetwork的

    plugin机制扩展各种第三方实现,从而以不同的方式实现跨主机通信。就目前社区比较流行的方案来说,跨主机通信的基本实现方案有以下几种:

    1)基于隧道的overlay网络:按隧道类型来说,不同的公司或者组织有不同的实现方案。docker原生的overlay网络就是基于vxlan隧道实现的。ovn则需要通过geneve或者stt隧道来实现的。flannel

    最新版本也开始默认基于vxlan实现overlay网络。

     

    2)基于包封装的overlay网络:基于UDP封装等数据包包装方式,在docker集群上实现跨主机网络。典型实现方案有weave、flannel的早期版本。

     

    3)基于三层实现SDN网络:基于三层协议和路由,直接在三层上实现跨主机网络,并且通过iptables实现网络的安全隔离。典型的方案为Project Calico。同时对不支持三层路由的环境,Project Calico还提供了基于IPIP封装的跨主机网络实现

    Dokcer通过使用Linux桥接提供容器之间的通信,docker0桥接接口的目的就是方便Docker管理。当Docker daemon启动时需要做以下操作

    1

    2

    3

    4

    a)如果docker0不存在则创建

    b)搜索一个与当前路由不冲突的ip段

    c)在确定的范围中选择 ip

    d)绑定ip到 docker0

    列出当前主机网桥

    1

    2

    3

    [root@localhost ~]# brctl show

    bridge name    bridge id           STP enabled   interfaces

    docker0        8000.02426f15541e   no            vethe833b02

    查看当前 docker0 ip

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    [root@localhost ~]# ifconfig

    docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500

            inet 172.17.0.1  netmask 255.255.0.0  broadcast 0.0.0.0

            inet6 fe80::42:6fff:fe15:541e  prefixlen 64  scopeid 0x20<link>

            ether 02:42:6f:15:54:1e  txqueuelen 0  (Ethernet)

            RX packets 120315  bytes 828868638 (790.4 MiB)

            RX errors 0  dropped 0  overruns 0  frame 0

            TX packets 132565  bytes 100884398 (96.2 MiB)

            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

    ................

    在容器运行时,每个容器都会分配一个特定的虚拟机口并桥接到docker0。每个容器都会配置同docker0 ip相同网段的专用ip 地址,docker0的IP地址被用于所有容器的默认网关。
    一般启动的容器中ip默认是172.17.0.1/24网段的。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    [root@linux-node2 ~]# docker images

    REPOSITORY                   TAG                 IMAGE ID            CREATED             SIZE

    centos                       latest              67591570dd29        3 months ago        191.8 MB

     

    [root@linux-node2 ~]# docker run -t -i --name my-test centos /bin/bash

    [root@c5217f7bd44c /]#

     

    [root@linux-node2 ~]# docker ps

    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES

    c5217f7bd44c        centos              "/bin/bash"         10 seconds ago      Up 10 seconds                                my-test

    [root@linux-node2 ~]# docker inspect c5217f7bd44c|grep IPAddress

                "SecondaryIPAddresses": null,

                "IPAddress""172.17.0.2",

                        "IPAddress""172.17.0.2",

    那么能不能在创建容器的时候指定特定的ip呢?这是当然可以实现的!

    注意:宿主机的ip路由转发功能一定要打开,否则所创建的容器无法联网!

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    [root@localhost ~]# cat /proc/sys/net/ipv4/ip_forward

    1

    [root@localhost ~]#

    [root@localhost ~]# docker ps

    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

    6e64eade06d1        docker.io/centos    "/bin/bash"         10 seconds ago      Up 9 seconds                            my-centos

    [root@localhost ~]# docker run -itd --net=none --name=container1 docker.io/centos

    5e5bdbc4d9977e6bcfa40e0a9c3be10806323c9bf5a60569775903d345869b09

    [root@localhost ~]# docker attach container1

    [root@5e5bdbc4d997 /]# ping www.baidu.com

    PING www.a.shifen.com (61.135.169.121) 56(84) bytes of data.

    64 bytes from 61.135.169.121 (61.135.169.121): icmp_seq=1 ttl=53 time=2.09 ms

    64 bytes from 61.135.169.121 (61.135.169.121): icmp_seq=2 ttl=53 time=2.09 ms

     

    关闭ip路由转发功能,容器即不能联网

    [root@localhost ~]# echo 0 > /proc/sys/net/ipv4/ip_forward

    [root@localhost ~]# cat /proc/sys/net/ipv4/ip_forward

    0

    [root@5e5bdbc4d997 /]# ping www.baidu.com        //ping不通~

    一、创建容器使用特定范围的IP

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    Docker 会尝试寻找没有被主机使用的ip段,尽管它适用于大多数情况下,但是它不是万能的,有时候我们还是需要对ip进一步规划。

    Docker允许你管理docker0桥接或者通过-b选项自定义桥接网卡,需要安装bridge-utils软件包。操作流程如下:

    a)确保docker的进程是停止的

    b)创建自定义网桥

    c)给网桥分配特定的ip

    d)以-b的方式指定网桥

      

    具体操作过程如下(比如创建容器的时候,指定ip为192.168.5.1/24网段的):

    [root@localhost ~]# service docker stop

    [root@localhost ~]# ip link set dev docker0 down

    [root@localhost ~]# brctl delbr docker0

    [root@localhost ~]# brctl addbr bridge0

    [root@localhost ~]# ip addr add 192.168.5.1/24 dev bridge0      //注意,这个192.168.5.1就是所建容器的网关地址。通过docker inspect container_id能查看到

    [root@localhost ~]# ip link set dev bridge0 up

    [root@localhost ~]# ip addr show bridge0

    [root@localhost ~]# vim /etc/sysconfig/docker      //即将虚拟的桥接口由默认的docker0改为bridge0

    OPTIONS='--selinux-enabled --log-driver=journald'

    改为

    OPTIONS='--selinux-enabled --log-driver=journald -b=bridge0'    //即添加-b=bridge0

      

    [root@localhost ~]# service docker restart

      

    --------------------------------------------------------------------------------------

    上面是centos7下的操作步骤,下面提供下ubuntu下的操作步骤:

    sudo service docker stop

    sudo ip link set dev docker0 down

    sudo brctl delbr docker0

    sudo brctl addbr bridge0

    sudo ip addr add 192.168.5.1/24 dev bridge0

    sudo ip link set dev bridge0 up

    $ ip addr show bridge0

    echo 'DOCKER_OPTS="-b=bridge0"' >> /etc/default/docker

    sudo service docker start

    --------------------------------------------------------------------------------------

      

    然后创建容器,查看下容器ip是否为设定的192.168.5.1/24网段的

    [root@localhost ~]# docker images

    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

    docker.io/ubuntu    latest              0ef2e08ed3fa        2 weeks ago         130 MB

    centos7             7.3.1611            d5ebea14da54        3 weeks ago         311 MB

      

    [root@localhost ~]# docker run -t -i --name test2 centos7:7.3.1611 /bin/bash

    [root@224facf8e054 /]#

      

    [root@localhost ~]# docker run -t -i --name test1 docker.io/ubuntu /bin/bash

    root@f5b1bfc2811a:/#

      

    [root@localhost ~]# docker ps

    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

    224facf8e054        centos7:7.3.1611    "/bin/bash"         46 minutes ago      Up 46 minutes                           test2

    f5b1bfc2811a        docker.io/ubuntu    "/bin/bash"         47 minutes ago      Up 5 minutes                            test1

    [root@localhost ~]# docker inspect --format='{{.NetworkSettings.IPAddress}}' f5b1bfc2811a

    192.168.5.2

    [root@localhost ~]# docker inspect --format='{{.NetworkSettings.IPAddress}}' 224facf8e054

    192.168.5.3

     

    [root@localhost ~]# brctl show

    bridge name   bridge id           STP enabled     interfaces

    bridge0       8000.ba141fa20c91   no              vethe7e227b

                                                      vethf382771

    使用pipework给容器设置一个固定的ip

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    可以利用pipework为容器指定一个固定的ip,操作方法非常简单,如下:

    [root@node1 ~]# brctl addbr br0

    [root@node1 ~]# ip link set dev br0 up

    [root@node1 ~]# ip addr add 192.168.114.1/24 dev br0                        //这个ip相当于br0网桥的网关ip,可以随意设定。

    [root@node1 ~]# docker run -ti -d --net=none --name=my-test1 docker.io/nginx /bin/bash

    [root@node1 ~]# pipework br0 -i eth0 my-test1 192.168.114.100/24@192.168.114.1

     

    [root@node1 ~]# docker exec -ti my-test1 /bin/bash

    root@cf370a090f63:/# ip addr

    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default

        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

    57: eth0@if58: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000

        link/ether b2:c1:8d:92:33:e2 brd ff:ff:ff:ff:ff:ff link-netnsid 0

        inet 192.168.114.100/24 brd 192.168.114.255 scope global eth0

           valid_lft forever preferred_lft forever

        inet6 fe80::b0c1:8dff:fe92:33e2/64 scope link

           valid_lft forever preferred_lft forever

     

     

    再启动一个容器

    [root@node1 ~]# docker run -ti -d --net=none --name=my-test2 docker.io/nginx /bin/bash

    [root@node1 ~]# pipework br0 -i eth0 my-test12 192.168.114.200/24@192.168.114.1

    [root@node1 ~]# pipework br0 -i eth0 my-test2 192.168.114.200/24@192.168.114.1

     

    这样,my-test1容器和my-test2容器在同一个宿主机上,所以它们固定后的ip是可以相互ping通的,如果是在不同的宿主机上,则就无法ping通!

     

    所以说:

    这样使用pipework指定固定ip的容器,在同一个宿主机下的容器间的ip是可以相互ping通的,但是跨主机的容器通过这种方式固定ip后就不能ping通了。

    跨主机的容器间的通信可以看下面的介绍。

    二、不同主机间的容器通信(pipework  config docker container ip)

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    69

    70

    71

    72

    73

    74

    75

    76

    77

    78

    79

    80

    81

    82

    83

    84

    85

    86

    87

    88

    89

    90

    91

    92

    93

    94

    95

    96

    97

    98

    99

    100

    101

    102

    103

    104

    105

    106

    107

    108

    109

    110

    111

    112

    113

    114

    115

    116

    117

    118

    119

    我的centos7测试机上的docker是yum安装的,默认自带pipework工具,所以就不用在另行安装它了。

    -----------------------------------------------------------------------------------------------

    如果没有pipework工具,可以安装下面步骤进行安装:

    # git clone https://github.com/jpetazzo/pipework.git

    # sudo cp -rp pipework/pipework /usr/local/bin/

          

    安装相应依赖软件(网桥)

    #sudo apt-get install iputils-arping bridge-utils -y

    -----------------------------------------------------------------------------------------------

         

    查看Docker宿主机上的桥接网络

    [root@linux-node2 ~]# brctl show

    bridge name   bridge id           STP enabled   interfaces

    docker0       8000.02426f15541e   no            veth92d132f

        

    有两种方式做法:

    1)可以选择删除docker0,直接把docker的桥接指定为br0;

    2)也可以选择保留使用默认docker0的配置,这样单主机容器之间的通信可以通过docker0;

       跨主机不同容器之间通过pipework将容器的网卡桥接到br0上,这样跨主机容器之间就可以通信了。

        

    如果保留了docker0,则容器启动时不加--net=none参数,那么本机容器启动后就是默认的docker0自动分配的ip(默认是172.17.1.0/24网段),它们之间是可以通信的;

    跨宿主机的容器创建时要加--net=none参数,待容器启动后通过pipework给容器指定ip,这样跨宿主机的容器ip是在同一网段内的同网段地址,因此可以通信。

       

    一般来说:最好在创建容器的时候加上--net=none,防止自动分配的IP在局域网中有冲突。若是容器创建后自动获取ip,下次容器启动会ip有变化,可能会和物理网段中的ip冲突

      

    ---------------------------------------------------------------------------------------------------

    实例说明如下:

    宿主机信息

    ip:192.168.1.23          (网卡设备为eth0)

    gateway:192.168.1.1

    netmask:255.255.255.0

     

    1)删除虚拟桥接卡docker0的配置

    [root@localhost ~]# service docker stop

    [root@localhost ~]# ip link set dev docker0 down

    [root@localhost ~]# brctl delbr docker0

    [root@localhost ~]# brctl addbr br0

    [root@localhost ~]# ip link set dev br0 up      

    [root@localhost ~]# ip addr del 192.168.1.23/24 dev eth0       //删除宿主机网卡的IP(如果是使用这个地址进行的远程连接,这一步操作后就会断掉;如果是使用外网地址连接的话,就不会断开)

    [root@localhost ~]# ip addr add 192.168.1.23/24 dev br0        //将宿主主机的ip设置到br0

    [root@localhost ~]# brctl addif br0 eth0                        //将宿主机网卡挂到br0上

    [root@localhost ~]# ip route del default                       //删除默认的原路由,其实就是eth0上使用的原路由192.168.1.1(这步小心,注意删除后要保证机器能远程连接上,最好是通过外网ip远程连的。别删除路由后,远程连接不上,中断了)

    [root@localhost ~]# ip route add default via 192.168.1.1 dev br0      //为br0设置路由

    [root@localhost ~]# vim /etc/sysconfig/docker                 //即将虚拟的桥接口由默认的docker0改为bridge0

    OPTIONS='--selinux-enabled --log-driver=journald'

    改为

    OPTIONS='--selinux-enabled --log-driver=journald -b=br0'    //即添加-b=br0

       

    [root@localhost ~]# service docker start

      

      

    启动一个手动设置网络的容器

    [root@localhost ~]# docker ps

    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

    6e64eade06d1        docker.io/centos    "/bin/bash"         10 seconds ago      Up 9 seconds                            my-centos

    [root@localhost ~]# docker run -itd --net=none --name=my-test1 docker.io/centos

       

    为my-test1容器设置一个与桥接物理网络同地址段的ip(如下,"ip@gateway"

    默认不指定网卡设备名,则默认添加为eth0。可以通过-i参数添加网卡设备名

    [root@localhost ~]# pipework br0 -i eth0 my-test1 192.168.1.190/24@192.168.1.1

      

    同理,在其他机器上启动容器,并类似上面用pipework设置一个同网段类的ip,这样跨主机的容器就可以相互ping通了!

      

    --------------------------------------------------------------------------------------------------

    2)保留默认虚拟桥接卡docker0的配置

    [root@localhost ~]# cd /etc/sysconfig/network-scripts/

    [root@localhost network-scripts]# cp ifcfg-eth0 ifcfg-eth0.bak

    [root@localhost network-scripts]# cp ifcfg-eth0 ifcfg-br0

    [root@localhost network-scripts]# vim ifcfg-eth0            //增加BRIDGE=br0,删除IPADDR,NETMASK,GATEWAY,DNS的设置

    ......

    BRIDGE=br0

    [root@localhost network-scripts]# vim ifcfg-br0            //修改DEVICE为br0,Type为Bridge,把eth0的网络设置设置到这里来(里面应该有ip,网关,子网掩码或DNS设置)

    ......

    TYPE=Bridge

    DEVICE=br0

         

    [root@localhost network-scripts]# service network restart

         

    [root@localhost network-scripts]# service docker restart

         

    开启一个容器并指定网络模式为none(这样,创建的容器就不会通过docker0自动分配ip了,而是根据pipework工具自定ip指定)

    [root@localhost network-scripts]# docker images

    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

    docker.io/centos    latest              67591570dd29        3 months ago        191.8 MB

    [root@localhost network-scripts]# docker run -itd --net=none --name=my-centos docker.io/centos /bin/bash

    6e64eade06d1eb20be3bd22ece2f79174cd033b59182933f7bbbb502bef9cb0f

      

    接着给容器配置网络

    [root@localhost network-scripts]# pipework br0 -i eth0 my-centos 192.168.1.150/24@192.168.1.1

    [root@localhost network-scripts]# docker attach 6e64eade06d1

    [root@6e64eade06d1 /]# ifconfig eth0                 //若没有ifconfig命令,可以yum安装net-tools工具

    eth0      Link encap:Ethernet  HWaddr 86:b6:6b:e8:2e:4d

              inet addr:192.168.1.150  Bcast:0.0.0.0  Mask:255.255.255.0

              inet6 addr: fe80::84b6:6bff:fee8:2e4d/64 Scope:Link

              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

              RX packets:8 errors:0 dropped:0 overruns:0 frame:0

              TX packets:9 errors:0 dropped:0 overruns:0 carrier:0

              collisions:0 txqueuelen:1000

              RX bytes:648 (648.0 B)  TX bytes:690 (690.0 B)

     

    [root@6e64eade06d1 /]# route -n

    Kernel IP routing table

    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface

    0.0.0.0         192.168.1.1     0.0.0.0         UG    0      0        0 eth0

    192.168.115.0   0.0.0.0         255.255.255.0   U     0      0        0 eth0

         

    另外pipework不能添加静态路由,如果有需求则可以在run的时候加上--privileged=true 权限在容器中手动添加,但这种方法安全性有缺陷。

    除此之外,可以通过ip netns(--help参考帮助)添加静态路由,以避免创建容器使用--privileged=true选项造成一些不必要的安全问题:

         

    如下获取指定容器的pid

    [root@localhost network-scripts]# docker inspect --format="{{ .State.Pid }}" 6e64eade06d1

    7852

    [root@localhost network-scripts]# ln -s /proc/7852/ns/net /var/run/netns/7852

    [root@localhost network-scripts]# ip netns exec 7852 ip route add 192.168.0.0/16 dev eth0 via 192.168.1.1

    [root@localhost network-scripts]# ip netns exec 7852 ip route    //添加成功

    192.168.0.0/16 via 192.168.1.1 dev eth0

         

    同理,在其它宿主机进行相应的配置,新建容器并使用pipework添加虚拟网卡桥接到br0,如此创建的容器间就可以相互通信了。

    -----------------------------------------------几个报错出来---------------------------------------------

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    1)重启网卡报错如下:

    # systemctl restart network

    ......

    Nov 23 22:09:08 hdcoe02 systemd[1]: network.service: control process exited, code=exited status=1 

    Nov 23 22:09:08 hdcoe02 systemd[1]: Failed to start LSB: Bring up/down networking. 

    Nov 23 22:09:08 hdcoe02 systemd[1]: Unit network.service entered failed state.</span

     

    解决办法:

    # systemctl enable NetworkManager-wait-online.service

    # systemctl stop NetworkManager

    # systemctl  restart network.service

     

    2)创建容器,出现下面告警

    WARNING: IPv4 forwarding is disabled. Networking will not work.

    解决办法:

    #vim /usr/lib/sysctl.d/00-system.conf

    添加如下代码:

    net.ipv4.ip_forward=1

     

    重启network服务

    # systemctl restart network

    -----------------------------------------------------------------------------------------------------------------------------------
    其实除了上面使用的pipework工具还,还可以使用虚拟交换机(Open vSwitch)进行docker容器间的网络通信,废话不多说,下面说下Open vSwitch的使用:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    一、在Server1和Server2上分别安装open vswitch

    [root@Slave1 ~]# # yum -y install wget openssl-devel kernel-devel

    [root@Slave1 ~]# yum groupinstall "Development Tools"

    [root@Slave1 ~]# adduser ovswitch

    [root@Slave1 ~]# su - ovswitch

    [root@Slave1 ~]$ wget http://openvswitch.org/releases/openvswitch-2.3.0.tar.gz

    [root@Slave1 ~]$ tar -zxvpf openvswitch-2.3.0.tar.gz

    [root@Slave1 ~]$ mkdir -p ~/rpmbuild/SOURCES

    [root@Slave1 ~]$ sed 's/openvswitch-kmod, //g' openvswitch-2.3.0/rhel/openvswitch.spec > openvswitch-2.3.0/rhel/openvswitch_no_kmod.spec

    [root@Slave1 ~]$ cp openvswitch-2.3.0.tar.gz rpmbuild/SOURCES/

        

    [root@Slave1 ~]$ rpmbuild -bb --without check ~/openvswitch-2.3.0/rhel/openvswitch_no_kmod.spec

        

    [root@Slave1 ~]$ exit

        

    [root@Slave1 ~]# yum localinstall /home/ovswitch/rpmbuild/RPMS/x86_64/openvswitch-2.3.0-1.x86_64.rpm

    [root@Slave1 ~]# mkdir /etc/openvswitch

    [root@Slave1 ~]# setenforce 0

    [root@Slave1 ~]# systemctl start openvswitch.service

    [root@Slave1 ~]# systemctl  status openvswitch.service -l

      

    二、在Slave1和Slave2上建立OVS Bridge并配置路由

    1)在Slave1宿主机上设置docker容器内网ip网段172.17.1.0/24

    [root@Slave1 ~]# vim /proc/sys/net/ipv4/ip_forward

    1

    [root@Slave1 ~]# ovs-vsctl add-br obr0

    [root@Slave1 ~]# ovs-vsctl add-port obr0 gre0 -- set Interface gre0 type=gre options:remote_ip=192.168.115.5

        

    [root@Slave1 ~]# brctl addbr kbr0

    [root@Slave1 ~]# brctl addif kbr0 obr0

    [root@Slave1 ~]# ip link set dev docker0 down

    [root@Slave1 ~]# ip link del dev docker0

        

    [root@Slave1 ~]# vim /etc/sysconfig/network-scripts/ifcfg-kbr0

    ONBOOT=yes

    BOOTPROTO=static

    IPADDR=172.17.1.1

    NETMASK=255.255.255.0

    GATEWAY=172.17.1.0

    USERCTL=no

    TYPE=Bridge

    IPV6INIT=no

        

    [root@Slave1 ~]# vim /etc/sysconfig/network-scripts/route-ens32

    172.17.2.0/24 via 192.168.115.6 dev ens32

      

    [root@Slave1 ~]# systemctl  restart network.service

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    2)在Slave2宿主机上设置docker容器内网ip网段172.17.2.0/24

    [root@Slave2 ~]# vim /proc/sys/net/ipv4/ip_forward

    1

    [root@Slave2 ~]# ovs-vsctl add-br obr0

    [root@Slave2 ~]# ovs-vsctl add-port obr0 gre0 -- set Interface gre0 type=gre options:remote_ip=192.168.115.6

       

    [root@Slave2 ~]# brctl addbr kbr0

    [root@Slave2 ~]# brctl addif kbr0 obr0

    [root@Slave2 ~]# ip link set dev docker0 down

    [root@Slave2 ~]# ip link del dev docker0

       

    [root@Slave2 ~] vim /etc/sysconfig/network-scripts/ifcfg-kbr0

    ONBOOT=yes

    BOOTPROTO=static

    IPADDR=172.17.2.1

    NETMASK=255.255.255.0

    GATEWAY=172.17.2.0

    USERCTL=no

    TYPE=Bridge

    IPV6INIT=no

       

    [root@Slave2 ~]# vim /etc/sysconfig/network-scripts/route-ens32

    172.17.1.0/24 via 192.168.115.5 dev ens32

       

    [root@Slave2 ~]# systemctl  restart network.service

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    三、启动容器测试

    Server1和Server2上修改docker启动的虚拟网卡绑定为kbr0,重启docker进程

     

    1)在Server1宿主机上启动容器,然后登陆容器内查看ip,就会发现ip是上面设定额172.17.1.0/24网段的

    [root@Slave1 ~]# docker run -idt --name my-server1 daocloud.io/library/centos/bin/bash

     

     

    2)在Server2宿主机上启动容器,然后登陆容器内查看ip,就会发现ip是上面设定额172.17.2.0/24网段的

    [root@Slave2 ~]#docker run -idt --name my-server1 daocloud.io/library/centos /bin/bash

     

    然后在上面启动的容内互ping对方容器,发现是可以ping通的

    本文跨主机通信部分转自:https://www.cnblogs.com/kevingrace/category/839227.html

    展开全文
  • 自从Docker容器出现以来,容器的网络通信就一直是被关注的焦点,也是生产环境的迫切需求。容器的网络通信又可以分为两大方面:单主机容器上的相互通信主机的容器相互通信。 一、端口映射(局域网,外网此...
  • bridge 模式当docker进程启动时,主机上会创建一个名为docker0的虚拟网桥,容器内部会创建一个只能容器内部看到的接口eth0,eth0 和docker0工作方式就像物理二层交换机一样,可以互相通信。 命令执行过程:#docker ...
  • docker容器内访问宿主机的mysql服务

    万次阅读 2018-12-17 20:38:10
    2)当在docker容器内部执行ifconfig后,会获得*.*.*.2,这个ip地址,在宿主机上执行ifconfig,会有docker0这个网桥,宿主机和docker容器就是通过这个docker0网桥进行通信的,宿主机在此网桥上的ip地址为*.*.*.1,...
  • 如果将连接容器的网桥docker0也桥接到宿主机提供的网卡上,将docker0分配的IP地址和宿主机的IP地址设置为同一个网段,就相当于将docker容器和宿主机连接到了一起,这样就可以实现跨主机的docker容器通信。...
  • Nginx容器和php-fpm容器通信 问题焦点 容器如何获取宿主机docker0网卡IP? 通过容器/etc/profile(hosts)文件 下面2条命令是等效的 --add-host host:$(ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+')\ --...
  • 同一个华为云宿主机上, 两个docker容器,分别是djangomysql, django通过公网IP访问mysql,运行正常. 电脑本地 django容器 使用 内部IP 访问 本地服务器上 的docker mysql容器, 运行正常. 本地服务器 虚拟机上,django...
  • 然而如果想同时部署使用多个容器,每个容器不使用127.0.0.1地址,而是各自有ip,如使用172.17.0.x网段,则需要解决从宿主机到各个容器的网络通信。 如果是使用其他Linux系统的用户则不用担心这个问题,Linxu系统...
  • 我的笔记本是window7系统,为了模拟服务器的环境,安装了虚拟机centOS7。 前戏准备 一些操作都需要root权限操作,从... (docker所有的操作,都是基于启动docker服务,不然会报:Cannot connect to the Docker da...
  • 是直接使用宿主机的网卡设备,还是独立创造出自己的网络设备?以及容器如何与外界通信,下面我们通过简单的说明以及示例,讨论下单机模式下docker的网络模式。 docker单机模式下,主要有四种网络模式,可以在创建...
  • Docker Flannel 跨主机容器通信解决方案 方案介绍 Flannel Flannel是 CoreOS 团队针对 Kubernetes 设计的...Flannel通过给每台宿主机分配一个子网的方式为容器提供虚拟网络,它基于Linux TUN/TAP,使用UDP封装IP包来创
  • 在进行网络配置之前,使用docker network命令可以查看一下当前容器的网络,这些都是宿主机安装Docker后自动创建的三个网络(还有一个共享容器的网络没有显示是因为它host模式一样,共享的是谁DRIVER就显示为谁),...
  • 问题:win10环境使用VMware搭建centos系统(网络使用的NAT模式),在centos安装docker后,宿主机无法访问docker中启动的容器宿主机可以ping通docker网段,telnet不通 原因:docker网卡地址冲突。NAT模式下,centos...
  • ocker容器内部端口映射到外部宿主机端口1、启动容器时,选择一个端口映射到容器内部开放端口上2、启动创建时,绑定外部的ip端口(宿主机ip是192.168.10.214)3、容器启动时可以指定通信协议,比如tcp、udp4、查看...
  • joined容器类似于之前的host模式,host模式是容器宿主机共享,而这里是容器容器之间之间共享。 此时可以通过vm2来访问vm1的容器: 其实ping真实名别名都可以ping通: 跨主机容器通信: macvlan...
  • libnetwork(docker容器网络库, 其中CNM (ContainerNetworkModel)是它的核心,它对容器网络进行了抽象) 1.3macvlan网络方案实现(使用的是linux内核虚拟化技术,无需桥接,直接使用物理接口, 性能极好) Macvlan...
  • 宿主机,通俗易懂的意思就是: 物理机是虚拟机的宿主机,虚拟机是容器的宿主机。 一、跨主机网络解决...libnetwork docker容器网络库 CNM (Container Network Model)这个模型对容器网络进行了抽象 二、ma...
  • 使用Docker Swarm实现跨宿主机容器间访问 背景: 在SerA服务器,运行了一个任务...分析下来,是由于ConAConB是跨宿主机容器,无法通信。 网上看到了很多方案,包括Overlay网络、OpenvSwitch、consul方案等,最终
  • Docker官方推荐我们通过端口映射的方式把Docker容器的服务提供给宿主机或者局域网其他容器使用。一般过程是: 1、Docker进程通过监听宿主机的某个端口,将该端口的数据包发送给Docker容器 2、宿主机可以打开防火墙...
  • 文章目录docker container 通信容器之间通信宿主机链接容器的服务容器链接宿主机的服务php容器安装xdebug容器链接宿主机测试通信是否成功参考文章 docker container 通信 容器之间通信 容器之间三种方式通信:...
  • 1. 跨主机容器网络解决方案 ...libnetwork docker容器网络库 CNM (Container Network Model)这个模型对容器网络进行了抽象 2. macvlan容器网络方案的实现 Macvlan是一个新的尝试,是真正的网络虚拟...
  • 1.跨主机网络解决方案 ...libnetwork docker容器网络库 CNM (Container Network Model)这个模型对容器 2.macvlan网络方案的实现 Macvlan是一个新的尝试,是真正的网络虚拟化技术的转折点。 Lin...
  • 1、通过网关暴露至宿主机的端口(可能被转换)进行通信,本例中的:172.17.0.1:8503 2、通过被访问容器ip(可以通过link之类的方便获取)和容器暴露端口通信,本例中的:172.17.0.3:8501 ...

空空如也

空空如也

1 2 3 4 5 ... 12
收藏数 239
精华内容 95
关键字:

docker容器和宿主机通信