单机多容器互通

方式1

  • docler 1.10开始,内嵌了一个DNS server
  • dns解析共呢个必须在自定义网络中使用 docker network create
  • 启动日工时用 --name  参数指定容器名称
[root@localhost ~]# docker network create --subnet 172.18.0.0/16 mynetwork  #模式是bridge模式,可以 -d指定类型,macvlan,host,none等类型
af4fa989039a30ac098a18a5259b1c74f445188db20afae9189a55dbfecfff84
[root@localhost ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
72618157442d        bridge              bridge              local
c21cf229ce4d        host                host                local
af4fa989039a        mynetwork           bridge              local
0b7d39b3b42a        none                null                local
[root@localhost ~]# docker run -it --name a1 --network mynetwork -d docker.io/centos:latest
4f8b5e9fbbc4742671a5ffcd3f68d30f21608a761f72843e70c583865dab9522
[root@localhost ~]# docker run -it --name a2 --network mynetwork -d docker.io/centos:latest
06527ad89c4c973acbd4a118833a2f668287cb1317474e06748ad572acaa1a6e
[root@localhost ~]# docker run -it --name a1 --network mynetwork -d 
[root@localhost ~]# docker exec -it 4f8b5e9fbbc47426 ping a1
PING a1 (172.18.0.2) 56(84) bytes of data.
64 bytes from 4f8b5e9fbbc4 (172.18.0.2): icmp_seq=1 ttl=64 time=0.016 ms
^C
--- a1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.016/0.016/0.016/0.000 ms
[root@localhost ~]# docker exec -it 4f8b5e9fbbc47426 ping a2
PING a2 (172.18.0.3) 56(84) bytes of data.
64 bytes from a2.mynetwork (172.18.0.3): icmp_seq=1 ttl=64 time=0.056 ms
^C
--- a2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.056/0.056/0.056/0.000 ms
[root@localhost ~]# 

方式2 

  • joined容器一种较为特别的网络模式
  • 在容器创建时使用--network=container:vm1指定(vm1指定的是运行的容器名)
  • joined容器类似于之前的host模式,host模式是容器与宿主机共享网络栈,而这里是容器与容器之间之间共享网络栈,其他还是隔离的,只有net namespace共享。

在这里插入图片描述

[root@localhost ~]# docker run -it --name a1 --network mynetwork -d docker.io/centos:latest
bf44c47d94975b1229d8c6dbb2bb5f0ffa0e4e9cffd7a8531a2a0c4dbd5f5020
[root@localhost ~]# docker run -it --name a2  --network container:a1 -d docker.io/centos:latest
26ca032cfe326a52b8208c7c6adb7b547913df6c5a826c1f84ffc7a2575d1053
[root@localhost ~]# docker exec -it bf44c47d949 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    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
26: eth0@if27: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe12:2/64 scope link 
       valid_lft forever preferred_lft forever
[root@localhost ~]# docker exec -it 26ca032cfe3 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    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
26: eth0@if27: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe12:2/64 scope link 
       valid_lft forever preferred_lft forever

方式3

  • --link 可以链接2个容器
  • 格式 --link <name or id>:alias 解释:name or id 是原容器,alias是原容器在link下的别名,其实ping真实名和别名都可以ping通:
[root@localhost ~]# docker run -it --name a1 -d docker.io/centos:latest
d22770ead1bf38054d9a87dac109ed56350f915a7641f656861fe08ebcd73d27
[root@localhost ~]# docker run -it --name a2  --link a1:wubo -d docker.io/centos:latest
0845fa63c8a39b1103a610ce82f27f20357a82464c8fe108c8c0ea4e7c8f726d
[root@localhost ~]# docker exec -it 0845fa63c cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.2	wubo d22770ead1bf a1
172.17.0.3	0845fa63c8a3
[root@localhost ~]# docker exec -it 0845fa63c ping wubo
PING wubo (172.17.0.2) 56(84) bytes of data.
64 bytes from wubo (172.17.0.2): icmp_seq=1 ttl=64 time=0.056 ms
^C
--- wubo ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.056/0.056/0.056/0.000 ms
[root@localhost ~]# docker exec -it 0845fa63c ping a1
PING wubo (172.17.0.2) 56(84) bytes of data.
64 bytes from wubo (172.17.0.2): icmp_seq=1 ttl=64 time=0.046 ms
^C
--- wubo ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.046/0.046/0.046/0.000 ms

 在这里插入图片描述

在这里插入图片描述

 

在这里插入图片描述

 

 

跨主机多容器互通

方案:

  • 跨主机容器间网络解决方案
    • docker 原生的overlay和macvlan
    • 通过iptable prerouting,postrouting,dnat,snat和ip route/route
    • 第三方的flannel,weave,calico
  • 众多网络方案是如何与docker集成在一起的
    • libnetwork docker容器网络库
    • CNM(Co'ntainer Network Model)这个模型对容器网络进行了抽象
  • CNM分三类组件
    • Sandbox:容器网络栈。包含容器接口,dns,路由表,namespace
    • Endpoint:作用是将Sandbox接入network(veth pair 虚拟网络)
    • Network:包含一组Endpoint,同一个network的Endpoint可以通信
  • 在这里插入图片描述

 

实现:macvlan

  • docker 原生的overlay和macvlan
    • Linux kernel 提供的一种网卡虚拟技术
    • 无需Linux bridge,直接使用物理接口,性能极好(其实macvlan内置了bridge【虚拟交换机】)
  • 打开混杂模式
[root@localhost ~]# ip link set dev ens33 promisc on
[root@localhost ~]# ip l
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:f9:78:c3 brd ff:ff:ff:ff:ff:ff
3: ens37: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:f9:78:cd brd ff:ff:ff:ff:ff:ff
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default 
    link/ether 02:42:88:95:65:19 brd ff:ff:ff:ff:ff:ff
[root@localhost ~]#
  • 在2台docker主机个各创建macvlan网络 
[root@localhost ~]# docker network create -d macvlan --subnet 172.20.0.0/24 --gateway 172.20.0.1 -o parent=ens33 macvlan1
b82a55b4a08b833a1b3b53df9f3ec7c26d9540498318e6a725317336142ac743
[root@localhost ~]# docker network create -d macvlan --subnet 172.20.0.0/24 --gateway 172.20.0.1 -o parent=ens38 macvlan1
2aea05f669cb37f2cffef89fa17bfba08acde31821e1eb9919a6ec9e09a409a3

 

  • 手动指定Ip(前提:之前需要设置了subnet gateway参数)
    
    [root@localhost ~]# docker run -it --name vm1 --network macvlan1 --ip 172.20.0.10 -d docker.io/centos:latest
    7643bacf68b78462e0d8e9d6fe2b951feebb073b1f17d974176de90f63b1667d
    [root@localhost ~]# docker exec -it 7643bacf ip a s
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        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
    32: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default 
        link/ether 02:42:ac:14:00:0a brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 172.20.0.10/24 scope global eth0
           valid_lft forever preferred_lft forever
        inet6 fe80::42:acff:fe14:a/64 scope link 
           valid_lft forever preferred_lft forever

    手动设置ip(不能与server1的ip一样,否则会冲突) 在第二台host中配置相同网段的网络(相当于交换机,只在二层进行交换,所以需要设置为相同的网段)

    
    [root@localhost ~]# docker run -it --name a1 --name vm1 --network macvlan1 --ip 172.20.0.11 -d docker.io/centos:latest
    e5098bfd3d804860d4d80a4cd936e145ae877306c2fff57b72428a6aa9d0c76f
    [root@localhost ~]# docker exec -it e5098bfd3d8 ip a s
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        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
    22: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default 
        link/ether 02:42:ac:14:00:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 172.20.0.11/24 scope global eth0
           valid_lft forever preferred_lft forever
        inet6 fe80::42:acff:fe14:b/64 scope link 
           valid_lft forever preferred_lft forever

     

  • macvlan网络分析
    • 没有新建linux bridge
      [root@localhost ~]# brctl show
      bridge name	bridge id		STP enabled	interfaces
      docker0		8000.024288956519	no		
      [root@localhost ~]#
      [root@localhost ~]# brctl show
      bridge name	bridge id		STP enabled	interfaces
      docker0		8000.0242cb5b632f	no		
      [root@localhost ~]# 

       

  • 容器的接口直接与主机网卡链接,无需NAT或端口映射。

测试

  • 此时两台机器可以互通:
    [root@localhost ~]# docker exec -it 7643bacf ping 172.20.0.11
    PING 172.20.0.11 (172.20.0.11) 56(84) bytes of data.
    64 bytes from 172.20.0.11: icmp_seq=1 ttl=64 time=0.904 ms
    64 bytes from 172.20.0.11: icmp_seq=2 ttl=64 time=0.445 ms
    64 bytes from 172.20.0.11: icmp_seq=3 ttl=64 time=1.25 ms
    64 bytes from 172.20.0.11: icmp_seq=4 ttl=64 time=0.515 ms
    ^C
    --- 172.20.0.11 ping statistics ---
    4 packets transmitted, 4 received, 0% packet loss, time 6ms
    rtt min/avg/max/mdev = 0.445/0.778/1.251/0.325 ms
    [root@localhost ~]# docker exec -it 7643bacf ping 172.20.0.1
    PING 172.20.0.1 (172.20.0.1) 56(84) bytes of data.
    ^C
    --- 172.20.0.1 ping statistics ---
    3 packets transmitted, 0 received, 100% packet loss, time 2ms

    此方法的缺陷:在企业中,即使创建多个网卡仍然不够用,并且机器真实的物理网卡有限。解决方案参考https://blog.csdn.net/Michaelwubo/article/details/110483589就是创建vlan子接口的方式实现多macvlan。vlan在二层最多(vlan id 1-4096)个逻辑网络

  • 在这里插入图片描述

  • 在这里插入图片描述

参考https://blog.csdn.net/weixin_44791884/article/details/105441016

 

实现:通过iptable prerouting,postrouting,dnat,snat和ip route/route

一、Docker网络基本原理

直观上看,要实现网络通信,机器需要至少一个网络接口(物理接口或虚拟接口)与外界相通,并可以收发数据包;此外,如果不同子网之间要进行通信,需要额外的路由机制。

Docker中的网络接口默认都是虚拟的接口。虚拟接口的最大优势就是转发效率极高。这是因为Linux通过在内核中进行数据复制来实现虚拟接口之间的数据转发,即发送接口的发送缓存中的数据包将被直接复制到接收接口的接收缓存中,而无需通过外部物理网络设备进行交换。对于本地系统和容器内系统来看,虚拟接口跟一个正常的以太网卡相比并无区别,只是它速度要快得多。

Docker容器网络就很好地利用了Linux虚拟网络技术,在本地主机和容器内分别创建一个虚拟接口,并让它们彼此连通(这样的一对接口叫做veth pair)。

一般情况下,Docker创建一个容器的时候,会具体执行如下操作:

1.创建一对虚拟接口,分别放到本地主机和新容器的命名空间中;

2.本地主机一端的虚拟接口连接到默认的docker0网桥或指定网桥上,并具有一个以veth开头的唯一名字,如veth1234;

3.容器一端的虚拟接口将放到新创建的容器中,并修改名字作为eth0。这个接口只在容器的命名空间可见;

4.从网桥可用地址段中获取一个空闲地址分配给容器的eth0(例如172.17.0.2/16),并配置默认路由网关为docker0网卡的内部接口docker0的IP地址(例如172.17.42.1/16)。

完成这些之后,容器就可以使用它所能看到的eth0虚拟网卡来连接其他容器和访问外部网络。用户也可以通过docker network命令来手动管理网络

二、Docker网络默认模式

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

1)bridge模式,--net=bridge(默认)
这是dokcer网络的默认设置,为容器创建独立的网络命名空间,容器具有独立的网卡等所有单独的网络栈,是最常用的使用方式。
在docker run启动容器的时候,如果不加--net参数,就默认采用这种网络模式。安装完docker,系统会自动添加一个供docker使用的网桥docker0,我们创建一个新的容器时,
容器通过DHCP获取一个与docker0同网段的IP地址,并默认连接到docker0网桥,以此实现容器与宿主机的网络互通。
 
2)host模式,--net=host
这个模式下创建出来的容器,直接使用容器宿主机的网络命名空间,除了网络不隔离其他namespace还是隔离的。
将不拥有自己独立的Network Namespace,即没有独立的网络环境。它使用宿主机的ip和端口。
 
3)none模式,--net=none ovs时候使用openswitch(目前docker 原生还不支持openswit创建的网桥,需要手动给容器加虚拟网卡)
为容器创建独立网络命名空间,但不为它做任何网络配置,容器中只有lo,用户可以在此基础上,对容器网络做任意定制。
这个模式下,dokcer不为容器进行任何网络配置。需要我们自己为容器添加网卡,配置IP。
因此,若想使用pipework或ovs配置docker容器的ip地址,必须要在none模式下才可以。
 
4)其他容器模式(即container模式),--net=container:NAME_or_ID
与host模式类似,只是容器将与指定的容器共享网络命名空间。除了网络不隔离其他namespace还是隔离的。
这个模式就是指定一个已有的容器,共享该容器的IP和端口。除了网络方面两个容器共享,其他的如文件系统,进程等还是隔离开的。
 
5)用户自定义:docker 1.9版本以后新增的特性,允许容器使用第三方的网络实现或者创建单独的bridge网络,提供网络隔离能力。

bridge模式

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

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

举一个简单的例子,使用下面的命令创建容器,并将宿主机的3306端口绑定到容器的3306端口:
[root@localhost ~]# docker run -it --name a1 -p 9999:8888 -d docker.io/centos:latest
 
在宿主机上,可以通过iptables -t nat -L -n,查到一条DNAT规则: #因为是外面叫进到docker里面所以是DNAT 对目标地址和端口做替换

DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:9999 to:172.17.0.2:8888
 
[root@localhost ~]# iptables -t nat -L -n
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  tcp  --  172.17.0.2           172.17.0.2           tcp dpt:8888

Chain DOCKER (0 references)
target     prot opt source               destination         
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:9999 to:172.17.0.2:8888

上面的172.17.0.2即为bridge模式下,创建的容器IP。
 
很明显,bridge模式的容器与外界通信时,必定会占用宿主机上的端口,从而与宿主机竞争端口资源,对宿主机端口的管理会是一个比较大的问题。同时,由于容器与外界通信是基于三层上iptables NAT,性能和效率上的损耗是可以预见的。和macvlan比那个效率高,只考虑效率,不考虑macvlan占用一个物理网卡的问题

 

三、方案介绍

概述

就目前Docker自身默认的网络来说,单台主机上的不同Docker容器可以借助docker0网桥直接通信,这没毛病,而不同主机上的Docker容器之间只能通过在主机上用映射端口的方法来进行通信,有时这种方式会很不方便,甚至达不到我们的要求,因此位于不同物理机上的Docker容器之间直接使用本身的IP地址进行通信很有必要。再者说,如果将Docker容器起在不同的物理主机上,我们不可避免的会遭遇到Docker容器的跨主机通信问题。本文就来尝试一下。

情景构造

如下图所示,我们有两个物理主机1和主机2,我们在各自宿主机上启动一个centos容器,启动成功之后,两个容器分别运行在两个宿主机之上,默认的IP地址分配如图所示,这也是Docker自身默认的网络。

 

此时两台主机上的Docker容器如何直接通过IP地址进行通信?

一种直接想到的方案便是通过分别在各自主机中 添加路由 来实现两个centos容器之间的直接通信。我们来试试吧

 

方案原理分析

由于使用容器的IP进行路由,就需要避免不同主机上的容器使用了相同的IP,为此我们应该为不同的主机分配不同的子网来保证。于是我们构造一下两个容器之间通信的路由方案,如下图所示。

 

各项配置如下:

  • 主机1的IP地址为:10.10.1.216
  • 主机2的IP地址为:10.10.1.219
  • 为主机1上的Docker容器分配的子网:172.17.0.2/16
  • 为主机2上的Docker容器分配的子网:172.18.0.2/16

这样配置之后,两个主机上的Docker容器就肯定不会使用相同的IP地址从而避免了IP冲突。

我们接下来 定义两条路由规则 即可:

  • 所有目的地址为172.17.0.2/24的包都被转发到主机1(10.10.1.216)上
  • 所有目的地址为172.18.0.2/24的包都被转发到主机2(10.10.1.219)上

综上所述,数据包在两个容器间的传递过程如下:

  • 从container1 发往 container2 的数据包,首先发往container1的“网关”docker0,然后通过查找主机1的路由得知需要将数据包发给主机2,数据包到达主机2后再转发给主机2的docker0,最后由其将数据包转到container2中;反向原理相同,不再赘述。

我们心里方案想的是这样,接下来实践一下看看是否可行。

四、实际试验

环境介绍

操作系统服务器地址Dockerd地址
CentOS Linux release 7.8.2003 (Core)10.10.1.216172.17.0.2
CentOS Linux release 7.8.2003 (Core)10.10.1.219172.18.0.2

 

 

 

docker的版本为 :# docker --version
Docker version 1.13.1, build 0be3e21/1.13.1

比如主机1,我需要运行一个docker镜像,要求它的网段必须是 172.17.0.0/24 ,怎么设置呢?

有2个办法:

1. 修改docker0的网段

2. 创建一个docker网桥

这里为了快速实现,选用第一种方案。直接修改/etc/sysconfig/docker 文件,添加--bip 参数即可

[root@localhost ~]# cat /etc/sysconfig/docker
# /etc/sysconfig/docker

# Modify these options if you want to change the way the docker daemon runs
OPTIONS='--selinux-enabled --log-driver=journald --signature-verification=false --bip 172.17.0.1/16'

特别注意,OPTIONS参数后面必须有引号。--bip后面的ip就是docker0的ip地址,也即是bridge ip ,docker0这个网桥的ip,一般从第一个ip开始!

查看主机1上docker0的ip地址

[root@localhost ~]# ip a s docker0
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:88:95:65:19 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:88ff:fe95:6519/64 scope link 
       valid_lft forever preferred_lft forever

查看主机2上docker0的ip地址 

[root@localhost ~]# ip a s docker0
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:cb:5b:63:2f brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:cbff:fe5b:632f/64 scope link 
       valid_lft forever preferred_lft forever

发现默认的网段已经改变了!

添加路由规则

主机1

查看路由表

[root@localhost ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.10.1.1       0.0.0.0         UG    0      0        0 ens33
10.10.1.0       0.0.0.0         255.255.255.0   U     0      0        0 ens33
169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 ens33
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0

 默认只有自己本身的路由,如果需要访问 172.18.0.0/24 网段,需要添加路由

 

主机1上添加路由规则如下:

[root@localhost ~]# route add -net 172.18.0.0/24 gw 10.10.1.219 dev ens33
或
[root@localhost ~]# ip route add 172.18.0.0/24 via 10.10.1.219 dev ens33
意思是去往172.18.0.0网络通过ens33网卡出去,吓一跳的地址是10.10.1.219,此时要求在ens33网卡上能ping通10.10.1.219的ip  ping -I ens33 10.10.1.219 或ping -I 10.10.1.216 10.10.1.219
gw 表示下一跳地址,这里的地址就是主机2的ip地址
再次查看路由,发现已经添加上了
[root@localhost ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.10.1.1       0.0.0.0         UG    0      0        0 ens33
10.10.1.0       0.0.0.0         255.255.255.0   U     0      0        0 ens33
169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 ens33
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.18.0.0      10.10.1.219     255.255.255.0   UG    0      0        0 ens33

主机2上添加路由规则如下: 

[root@localhost ~]# ip route add 172.17.0.0/24 via 10.10.1.216 dev ens38
[root@localhost ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.10.1.1       0.0.0.0         UG    0      0        0 ens38
10.10.1.0       0.0.0.0         255.255.255.0   U     0      0        0 ens38
172.17.0.0      10.10.1.216     255.255.255.0   UG    0      0        0 ens38
172.18.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.13.0    0.0.0.0         255.255.255.0   U     0      0        0 ens39

在主机1上,ping主机2的docker0地址

[root@localhost ~]# ping 172.18.0.1
PING 172.18.0.1 (172.18.0.1) 56(84) bytes of data.
64 bytes from 172.18.0.1: icmp_seq=1 ttl=64 time=0.505 ms
64 bytes from 172.18.0.1: icmp_seq=2 ttl=64 time=0.453 ms
64 bytes from 172.18.0.1: icmp_seq=3 ttl=64 time=0.417 ms
^C
--- 172.18.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 0.417/0.458/0.505/0.040 ms

在主机2上,ping主机1的docker0地址

[root@localhost ~]# ping 172.17.0.1
PING 172.17.0.1 (172.17.0.1) 56(84) bytes of data.
64 bytes from 172.17.0.1: icmp_seq=1 ttl=64 time=0.561 ms
64 bytes from 172.17.0.1: icmp_seq=2 ttl=64 time=0.353 ms
^C
--- 172.17.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.353/0.457/0.561/0.104 ms

ok,既然docker0都通了,那么起一个docker容器,会不会也是通的的呢?测试一下吧

在主机1上面启动一个容器,这里选用centos镜像,它只有4.5M,并且自带ping命令!

先查看ip地址

root@localhost ~]# docker run -it --name a1 -d docker.io/centos:latest
7fc75f8c87dc8c07dcb487070d52326d16343998ea2ccd2b3feb15025f962d78
[root@localhost ~]# docker exec -it 7fc75f8c ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    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
41: eth0@if42: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:2/64 scope link 
       valid_lft forever preferred_lft forever

它的ip地址为 172.17.0.2 ,由于docker0占用了第一个ip地址。所以容器启动时,ip地址从第二个开始分配!

在主机2上面启动一个容器

[root@localhost ~]# docker run -it --name a2 -d docker.io/centos:latest
7b82b6bce81a9978c74fafe609244778f951efa63ed0eb18fa485303581f795c
[root@localhost ~]# docker exec -it 7b82b6bce ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    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
23: eth0@if24: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe12:2/64 scope link 
       valid_lft forever preferred_lft forever

在主机1上的容器中 ping 主机2中的容器

先来ping 主机2的docker0,再ping 主机2中的容器

[root@localhost ~]# docker exec -it 7fc75f8c87dc ping 172.18.0.1
\PING 172.18.0.1 (172.18.0.1) 56(84) bytes of data.
64 bytes from 172.18.0.1: icmp_seq=1 ttl=63 time=0.423 ms
\64 bytes from 172.18.0.1: icmp_seq=2 ttl=63 time=1.05 ms
^C
--- 172.18.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 2ms
rtt min/avg/max/mdev = 0.423/0.734/1.045/0.311 ms
[root@localhost ~]# docker exec -it 7fc75f8c87dc ping 172.18.0.2
PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data.
^C
--- 172.18.0.2 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1ms

[root@localhost ~]# docker exec -it 7fc75f8c87dc ping 10.10.1.216
PING 10.10.1.216 (10.10.1.216) 56(84) bytes of data.
64 bytes from 10.10.1.216: icmp_seq=1 ttl=64 time=0.038 ms
64 bytes from 10.10.1.216: icmp_seq=2 ttl=64 time=0.114 ms
^C
--- 10.10.1.216 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.038/0.076/0.114/0.038 ms
[root@localhost ~]# docker exec -it 7fc75f8c87dc ping 10.10.1.1
PING 10.10.1.1 (10.10.1.1) 56(84) bytes of data.
64 bytes from 10.10.1.1: icmp_seq=1 ttl=253 time=1.45 ms
64 bytes from 10.10.1.1: icmp_seq=2 ttl=253 time=1.73 ms


[root@localhost ~]# docker exec -it 7fc75f8c87dc ping www.baidu.com
PING www.a.shifen.com (182.61.200.7) 56(84) bytes of data.
64 bytes from 182.61.200.7 (182.61.200.7): icmp_seq=1 ttl=54 time=4.76 ms
64 bytes from 182.61.200.7 (182.61.200.7): icmp_seq=2 ttl=54 time=5.48 ms
^C
--- www.a.shifen.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 3ms

从结果中,可以发现。docker0是通的,但是主机2中的容器是不通的,为什么呢?

Docker Bridge创建创建过程

1)首先宿主机上创建一对虚拟网卡veth pair设备,veth设备总是成对出现的,形成一个通信通道,数据传输就是基于这个链路的,veth设备常用来连接两个网络设备

2)Docker将veth pair设备的一端放在容器中,并命名为eth0,然后将另一端加入docker0网桥中,可以通过brctl show命令查看

3)从docker0网卡中分配一个IP到给容器使用,并设置docker0的IP地址为容器默认网关

4)此时容器IP与宿主机是可以通信的,宿主机也可以访问容器中的ip地址,在bridge模式下,连接同一网桥的容器之间可以相互通信,同时容器可以访问外网,但是其他物理机不能访问docker容器IP,需要通过NAT将容器的IP的port映射为宿主机的IP和port;

[root@localhost ~]# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:f9:78:c3 brd ff:ff:ff:ff:ff:ff
3: ens37: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:f9:78:cd brd ff:ff:ff:ff:ff:ff
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default 
    link/ether 02:42:88:95:65:19 brd ff:ff:ff:ff:ff:ff
42: veth0d73285@if41: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default 
    link/ether d2:c7:4e:13:71:30 brd ff:ff:ff:ff:ff:ff link-netnsid 0

会发现有一个 veth077daec 的网卡设备。咦,这是个啥?

当运行docker容器后,再次执行ifconfig命令可以看到会多出个网卡驱动veth开头的名字,所以补充下veth。

veth

Linux container 中用到一个叫做veth的东西,这是一种新的设备,专门为 container 所建。veth 从名字上来看是 Virtual ETHernet 的缩写,它的作用很简单,就是要把从一个 network namespace 发出的数据包转发到另一个 namespace。veth 设备是成对的,一个是 container 之中,另一个在 container 之外,即在真实机器上能看到的。
VETH设备总是成对出现,一端请求发送的数据总是从另一端以请求接受的形式出现。创建并配置正确后,向其一端输入数据,VETH会改变数据的方向并将其送入内核网络子系统,完成数据的注入,而在另一端则能读到此数据。(Namespace,其中往veth设备上任意一端上RX到的数据,都会在另一端上以TX的方式发送出去)veth工作在L2数据链路层,veth-pair设备在转发数据包过程中并不串改数据包内容。

成数据的注入,而在另一端则能读到此数据。(Namespace,其中往veth设备上任意一端上RX到的数据,都会在另一端上以TX的方式发送出去)veth工作在L2数据链路层,veth-pair设备在转发数据包过程中并不串改数据包内容。
显然,仅有veth-pair设备,容器是无法访问网络的。因为容器发出的数据包,实质上直接进入了veth1设备的协议栈里。如果容器需要访问网络,需要使用bridge等技术,将veth1接收到的数据包通过某种方式转发出去 。
veth参考链接

https://blog.csdn.net/Michaelwubo/article/details/110198072

https://blog.csdn.net/Michaelwubo/article/details/110224269

因此,如果要多台主机之间的docker通信,需要使用NAT转换。那么接下来,就是设置iptables规则了

配置iptables规则

主机1

在主机1上查看默认的nat 规则

[root@localhost ~]# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  anywhere            !loopback/8           ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  172.17.0.0/16        anywhere            

Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere            
[root@localhost ~]# 

这些nat规则,都是docker帮你做的。

增加一条规则 prerouting 就是DNAT操作,把进来(也就是外面近容器里面)的目标公网地址和端口(也就是ens33网卡的地址)转换到内网地址和端口(也即是容器里面的ip和端口)

[root@localhost ~]# iptables -t nat -I PREROUTING -s 172.17.0.0/16 -d 172.18.0.0/16 -j DNAT --to  172.17.0.1
[root@localhost ~]# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DNAT       all  --  172.17.0.0/16        172.18.0.0/16        to:172.17.0.1
DOCKER     all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  anywhere            !loopback/8           ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  172.17.0.0/16        anywhere            

Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere

PREROUTING:可以在这里定义进行目的NAT的规则,因为路由器进行路由时只检查数据包的目的ip地址,所以为了使数据包得以正确路由,我们必须在路由之前就进行目的NAT;

 

上面那一条路由规则是啥意思呢?就是当源地址为172.17.0.0/16网段 访问 172.18.0.0/16 时,在路由之前,将ip转换为172.17.0.1。

注意:一定要加-d参数。如果不加,虽然docker之间可以互通,但是不能访问网站,比如百度,qq之类的!

为什么呢?访问172.18.0.024 时,通过docker0网卡出去的。但是访问百度,还是通过docker0,就出不去了!

真正连接外网的是ens33网卡,必须通过它才行!因此必须要指定-d参数!

[root@localhost ~]# docker exec -it 7fc75f8c87dc ping 172.18.0.2
PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data.
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.037 ms
64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.120 ms
64 bytes from 172.18.0.2: icmp_seq=3 ttl=64 time=0.045 ms
^C
--- 172.18.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 3ms
rtt min/avg/max/mdev = 0.037/0.067/0.120/0.037 ms

是可以通讯的!

注意:iptables必须在 PREROUTING 上面做,而不是常规的 POSTROUTING。我测试在POSTROUTING做规则,始终无法通讯!POSTROUTING是出去的是容器访问外面的也就是内网转公网的时候用https://blog.csdn.net/Michaelwubo/article/details/109451475iptable 相关

 

主机2

主机2上添加如下规则:

[root@localhost ~]#  iptables -t nat -I PREROUTING -s 172.18.0.0/16 -d 172.17.0.0/16 -j DNAT --to  172.18.0.1
[root@localhost ~]# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         



DNAT       all  --  172.18.0.0/16        172.17.0.0/16        to:172.18.0.1

参考https://www.cnblogs.com/xiao987334176/p/10049844.html

 

还可以通过lbridge+vxlan实现跨主机容器间通信

参考https://blog.csdn.net/Michaelwubo/article/details/110929884

还可以通过OVS(openvswitch)+GRE|IPIP|SIT实现跨主机容器间通信

 

第三方法:flannel(vxlan(1,原生的VXLAN,即扩展的虚拟LAN。2,Directrouting:直接路由型)|udp|host-gw|)方式,Flannel通过给每台宿主机分配一个子网的方式为容器提供虚拟网络,它基于Linux TUN/TAP,使用UDP/VXLAN封装IP包来创建overlay网络,并借助etcd(也支持kubernetes)维护网络的分配情况。

flannel目前已经支持UDP、VxLAN、host-gw、AWS VPC和GCE路由等多种backend

跨主机通信的一个解决方案是Flannel,由CoreOS推出,支持3种实现:UDP、VXLAN、host-gw
udp模式:使用设备flannel.0进行封包解包,不是内核原生支持,上下文切换较大,性能非常差
vxlan模式:使用flannel.1进行封包解包,内核原生支持,性能较强
host-gw模式:这是一种纯三层网络的方案,性能最高,无需flannel.1这样的中间设备,直接宿主机当作子网的下一跳地址,性能最强,符合SDN(openflow)思想
host-gw的性能损失大约在10%左右,而其他所有基于VXLAN“隧道”机制 的网络方案,性能损失在20%~30%左右

flannel数据转发流程

 

  1. 容器直接使用目标容器的ip访问,默认通过容器内部的eth0发送出去。

  2. 报文通过veth pair被发送到vethXXX。

  3. vethXXX是直接连接到虚拟交换机docker0的,报文通过虚拟bridge docker0发送出去。

  4. 查找路由表,外部容器ip的报文都会转发到flannel0虚拟网卡,这是一个P2P的虚拟网卡,然后报文就被转发到监听在另一端的flanneld。

  5. flanneld通过etcd维护了各个节点之间的路由表,把原来的报文UDP封装一层,通过配置的iface发送出去。

  6. 报文通过主机之间的网络找到目标主机。

  7. 报文继续往上,到传输层,交给监听在8285端口的flanneld程序处理。

  8. 数据被解包,然后发送给flannel0虚拟网卡。

  9. 查找路由表,发现对应容器的报文要交给docker0。

  10. docker0找到连到自己的容器,把报文发送过去

 

https://www.cnblogs.com/breezey/p/9419612.html

https://www.jianshu.com/p/82864baeacac

https://www.cnblogs.com/kevingrace/p/6864804.html

https://www.cnblogs.com/breezey/p/9419612.html

https://blog.csdn.net/myy1066883508/article/details/106494910

https://blog.csdn.net/wuyuchen20/article/details/104515974

https://www.lmlphp.com/user/3182/article/item/383522/

 

  • 环境准备
    • CentOS Linux release 7.8.2003 (Core)
    • 两台机器IP为10.10.1.216和10.10.1.219
  • 两台均配置为这样echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf && sysctl -p

  • 清除iptables底层默认规则,并开启允许转发功能 iptables -P INPUT ACCEPT&&iptables -P FORWARD ACCEPT&&iptables -F&&iptables -L -n

  • 关闭selinux :setenforce 0

  • 需要安装的组件为:1,etcd2,flannel 3,docker

etcd在10.10.1.216节点即可,不做etcd集群。

yum install -y epel-release etcd flannel 
 
  • 首先配置etcd
[root@localhost ~]# cat /etc/etcd/etcd.conf  | grep -v "^#"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379,http://0.0.0.0:4001"
ETCD_NAME="node1"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.10.1.216:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://10.10.1.216:2379"
  • 最后我们启动etcd,systemctl enable etcd --now &&systemctl enable etcd

 

  • 编辑flannel的配置文件,内容如下 
[root@localhost ~]# cat /etc/sysconfig/flanneld | grep -v "^#"

FLANNEL_ETCD_ENDPOINTS="http://10.10.1.216:2379"

FLANNEL_ETCD_PREFIX="/atomic.io/network"
  • 再启动flannel之前需要向etcd内写入子网信息
etcdctl mk /atomic.io/network/config '{"Network":"192.168.0.0/16", "SubnetLen": 24 ,"SubnetMin": "192.168.1.0", "SubnetMax": "192.168.254.0","Backend": {"Type": "vxlan","Directrouting":"true"}}'
  • Network:用于指定Flannel地址池
  • SubnetLen:用于指定分配给单个宿主机的docker0的ip段的子网掩码的长度
  • SubnetMin:用于指定最小能够分配的ip段
  • SudbnetMax:用于指定最大能够分配的ip段,在上面的示例中,表示每个宿主机可以分配一个24位掩码长度的子网,可以分配的子网从 192.168.0.0/16到 192.168.20.0/16,也就意味着在这个网段中,最多只能有20台宿主机
  • Backend:用于指定数据包以什么方式转发,默认为udp模式,host-gw模式性能最好,但不能跨宿主机网络解决方式是vxlan+Directrouting模式。同网络用host-gw模式提高效率从本机的物理接口出去这就是Directrouting;不同网络用vxlan模式则flannel自动降级为VXLAN模式。
  • 上面的/atomic.io/network/和flanneld必须一致,可以自定义但是必须一致,子网范围为 192.168.0.0/16,最小子网开始为192.168.1.0 最大子网结束为192.168.254.0,至此自定义子网信息我们已经写入完毕。
  • 接下来,我们来启动flannel,并设置为开机启动systemctl enable flanneld --now

 

docker

两台都启动后我们来配置docker

可以发现的是在我们先安装flannel和etcd后最后安装docker后我们使用 sysetmctl show docker 将会发现 在安装flannel后自动生成配置

DropInPaths=/usr/lib/systemd/system/docker.service.d/flannel.conf

故在docker的systemd文件中应用对应变量 DOCKER_NETWORK_OPTIONS 即可

[root@localhost ~]# cat  /usr/lib/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=http://docs.docker.com
After=network.target
Wants=docker-storage-setup.service
Requires=docker-cleanup.timer

[Service]
Type=notify
NotifyAccess=main
EnvironmentFile=-/run/containers/registries.conf
EnvironmentFile=-/etc/sysconfig/docker
EnvironmentFile=-/etc/sysconfig/docker-storage
EnvironmentFile=-/etc/sysconfig/docker-network
Environment=GOTRACEBACK=crash
Environment=DOCKER_HTTP_HOST_COMPAT=1
Environment=PATH=/usr/libexec/docker:/usr/bin:/usr/sbin
ExecStart=/usr/bin/dockerd-current $DOCKER_NETWORK_OPTIONS \
          --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current \
          --default-runtime=docker-runc \
          --exec-opt native.cgroupdriver=systemd \
          --userland-proxy-path=/usr/libexec/docker/docker-proxy-current \
          --init-path=/usr/libexec/docker/docker-init-current \
          --seccomp-profile=/etc/docker/seccomp.json \
          $OPTIONS \
          $DOCKER_STORAGE_OPTIONS \
          $DOCKER_NETWORK_OPTIONS \
          $ADD_REGISTRY \
          $BLOCK_REGISTRY \
          $INSECURE_REGISTRY \
	  $REGISTRIES
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=1048576
LimitNPROC=1048576
LimitCORE=infinity
TimeoutStartSec=0
Restart=on-abnormal
KillMode=process

[Install]
WantedBy=multi-user.target

添加上述红色部分即可,引用了flannel的网络

重载配置systemctl daemon-reload&&systemctl restart docker

可以看到docker 0 的网桥已经使用flannel的网络段了

目前两台物理机的docker 0 网络处于同一子网下面的都是使用的flannel的子网,是可以相互ping通的

在node1上,ping node2的docker 0 网桥ip

我们来在容器内部ping下node2的docker 0网桥 IP,是可以ping通的,没问题

容器外部ping容器内部的ip也是通的

需要注意的几点要点:

1,向etcd集群写入子网信息时候务必要注意建立的子网文件夹要和flannel的配置文件内一直。

2,flannel的配置,etcd集群地址写正确,子网文件夹信息要和etcd写入一致

3,系统iptables默认规则一定要清除,并开启允许转发

4,确定下docker的网络是否被flannel接管,我们查看下docker的进程要确认下

  • [root@localhost ~]# ps -ef | grep docker
    root      35905      1  0 16:14 ?        00:00:02 /usr/bin/dockerd-current --bip=192.168.19.1/24 --ip-masq=true --mtu=1472 --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current --default-runtime=docker-runc --exec-opt native.cgroupdriver=systemd --userland-proxy-path=/usr/libexec/docker/docker-proxy-current --init-path=/usr/libexec/docker/docker-init-current --seccomp-profile=/etc/docker/seccomp.json --selinux-enabled --log-driver=journald --signature-verification=false --bip 172.17.0.1/16 --storage-driver overlay2 --bip=192.168.19.1/24 --ip-masq=true --mtu=1472
    root      35911  35905  0 16:14 ?        00:00:01 /usr/bin/docker-containerd-current -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --metrics-interval=0 --start-timeout 2m --state-dir /var/run/docker/libcontainerd/containerd --shim docker-containerd-shim --runtime docker-runc --runtime-args --systemd-cgroup=true
    root      37290  18696  0 16:34 pts/0    00:00:00 grep --color=auto docker

    参考https://www.cnblogs.com/hh2737/p/10168579.html

第四种方式calico 参考https://blog.csdn.net/Michaelwubo/article/details/111285486

总之只要物理主机之间能互通,不管各自物理主机上面是模式虚拟网卡,虚拟网络,通过iptable,ip,route,brctl等相关工具都能实现容器或不同net namespace互通

 

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐