主页

索引

模块索引

搜索页面

跨主机容器通信

备注

host 网络驱动程序仅适用于 Linux 主机,在 Docker Desktop for Mac、Docker Desktop for Windows 或 Docker EE for Windows Server 上不受支持。

早期的跨主机通信方案

  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网络:

    按隧道类型来说,不同的公司或者组织有不同的实现方案。
      a. docker原生的overlay网络就是基于vxlan隧道实现的。
      b. ovn则需要通过geneve或者stt隧道来实现的。
      c. flannel最新版本也开始默认基于vxlan实现overlay网络。
    
  2. 基于包封装的overlay网络:

    基于UDP封装等数据包包装方式,在docker集群上实现跨主机网络。
    典型实现方案有Weave、Flannel的早期版本。
    
  3. 基于三层实现SDN网络:

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

操作命令

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

->  如果docker0不存在则创建
->  搜索一个与当前路由不冲突的ip段
->  在确定的范围中选择 ip
->  绑定ip到 docker0

列出当前主机网桥:

[root@localhost ~]# brctl show
bridge name    bridge id           STP enabled   interfaces
docker0        8000.02426f15541e   no            vethe833b02

查看当前 docker0 ip:

[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网段
[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路由转发功能一定要打开,否则所创建的容器无法联网:

[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  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不通~

主页

索引

模块索引

搜索页面