docker overlay网络跨主机通信——使用flannel来打通网络

介绍:
     Flannel:一种结合了路由机制与隧道技术。
     原理:每个主机配置一个IP段和子网个数。例如:可以配置一个覆盖网络使用用 10.100.0.0/16段,每个主机/24 个子网。因此主机 a 可以接受 10.100.5.0/24,主机 B 可以接受 10.100.18.0/24的包。flannel 使用 etcd 来维护分配的子网到实际的 ip 地址之间的映射。对于数据路径,flannel使用 udp 来封装 ip 数据报,转发到远程主机。选择 UDP 作为转发协议是因为他能穿透防火墙。例如,AWS Classic 无法转发 IPoIP or GRE 网络包,是因为它的安全组仅仅支持 TCP/UDP/ICMP。
     总之就是将一个大网段再进行细分,它的功能就是让集群中不同节点主机创建的docker容器都具有全集群唯一的虚拟IP地址。
     Flannel的设计目的就是为集群中的所有节点重新规划IP地址的使用规则,从而使得不同节点上的容器能够获得“同属一个内网”且“不重复的”IP地址。并让属于不同节点上的容器能够直接通过内网IP通信。
直接上图:
docker overlay网络跨主机通信——使用flannel来打通网络_第1张图片
对上图简单解释:
     1. 数据从源容器中发出后,经由所在主机的docker0虚拟网卡转发到flannel0虚拟网卡,这是个P2P的虚拟网卡,flanneld服务监听在网卡的另外一端。
     2. Flannel通过Etcd服务维护了一张节点间的路由表
    3. 源主机的flanneld服务将原本的数据内容UDP封装后根据自己的路由表投递给目的节点的flanneld服务,数据到达以后被解包,然后直接进入目的节点的flannel0虚拟网卡,然后被转发到目的主机的docker0虚拟网卡,也就与本机容器完成了通信。

三个问题:
1、UDP封装是什么回事?
     在UDP的数据内容部分其实是另一个ICMP(也就是ping命令)的数据包。原始数据是在起始节点的Flannel服务上进行UDP封装的,投递到目的节点后就被另一端的Flannel服务还原成了原始的数据包,两边的Docker服务都感觉不到这个过程的存在。
2、为什么每个节点上的Docker会使用不同的IP地址段?
    因为Flannel通过Etcd分配了每个节点可用的IP地址段后,偷偷的修改了Docker的启动参数。在运行了Flannel服务的节点上可以查看到Docker服务进程运行参数(ps aux|grep docker|grep “bip”),例如“–bip=182.48.56.1/24”这个参数,它限制了所在节点容器获得的IP范围。这个IP范围是由Flannel自动分配的,由Flannel通过保存在Etcd服务中的记录确保它们不会重复。
3、 为什么在发送节点上的数据会从docker0路由到flannel0虚拟网卡,在目的节点会从flannel0路由到docker0虚拟网卡?
    例如现在有一个数据包要从IP为172.17.3.2的容器发到IP为172.17.18.2的容器。根据数据发送节点的路由表,它只与172.17.0.0/16匹配这条记录匹配,因此数据从docker0出来以后就被投递到了flannel0。同理在目标节点,由于投递的地址是一个容器,因此目的地址一定会落在docker0对于的172.17.18.0/24这个记录上,自然的被投递到了docker0网卡。
环境准备:
三台centos7机器
一台用来部署etcd,flannel安装在两台docker机器上。
etcd:118.190.140.12
flannel:192.168.0.124、192.168.0.121
搭建:
建议搭建之前将之前做过的实验全部清理干净。该实验两个容器地址可以相同。

1、部署etcd。地址:118.190.140.12

yum install etcd -y

2、启动etcd服务前修改配置文件,默认值监听本地回环地址

vim /etc/etcd/etcd.conf

docker overlay网络跨主机通信——使用flannel来打通网络_第2张图片

systemctl start etcd

3、添加一条网络配置的记录,这个配置用于flannel分配给每个docker的虚拟IP地址段。

[root@aliyun ~]# etcdctl set /atomic.io/network/config '{"Network":"172.17.0.0/16", "SubnetMin": "172.17.1.0", "SubnetMax": "172.17.254.0"}'

4、部署flannel,两台docker机器部署。

yum install flannel -y

5、设置etcd的地址,两台docker机器部署。

[root@localhost ~]# vim /etc/sysconfig/flanneld
FLANNEL_ETCD_ENDPOINTS="http://118.190.140.12:2379"

6、启动flannel,正常情况下,执行ip a可以看到flannel0桥接网卡了。

[root@localhost ~]# systemctl start flanneld

7、查看flannel申请的网段。etcd上查看。

[root@aliyun ~]# etcdctl ls /atomic.io/network/subnets
/atomic.io/network/subnets/172.17.59.0-24
/atomic.io/network/subnets/172.17.18.0-24

上述两个地址均是随机分配的,几个主机就分配几个段
8、修改docker的启动参数,因为要使docker使用flannel的网络传递参数,要修改一些启动参数,通过下面的脚本可以看到生成了一些docker参数。放到/run/docker_opts.env文件中,将这些参数加入到docker的启动参数即可。

到生成了一些docker参数。放到/run/docker_opts.env文件中,将这些参数加入到docker的启动参数即可。

[root@localhost ~]# /usr/libexec/flannel/mk-docker-opts.sh -i
[root@localhost ~]# cat /run/flannel/subnet.env
FLANNEL_NETWORK=172.17.0.0/16
FLANNEL_SUBNET=172.17.18.1/24
FLANNEL_MTU=1472
FLANNEL_IPMASQ=false
#加入到启动参数
vim /etc/docker/daemon.json
  "bip":"172.17.18.1/24",
    "mtu":1472,
    "ip-masq":true

另一台机器加入另一个子网段。
9、重启docker服务。
10、创建容器进行测试:

docke run -it --rm busybox
eth0@if51:  mtu 1472 qdisc noqueue
    link/ether 02:42:ac:11:12:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.18.2/24 brd 172.17.18.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping 172.17.59.2
PING 172.17.59.2 (172.17.59.2): 56 data bytes
64 bytes from 172.17.59.2: seq=0 ttl=60 time=2.335 ms
64 bytes from 172.17.59.2: seq=1 ttl=60 time=0.519 ms
docke run -it --rm busybox
eth0@if51:  mtu 1472 qdisc noqueue
    link/ether 02:42:ac:11:12:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.18.2/24 brd 172.17.18.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping 172.17.59.2
PING 172.17.59.2 (172.17.59.2): 56 data bytes
64 bytes from 172.17.59.2: seq=0 ttl=60 time=2.335 ms
64 bytes from 172.17.59.2: seq=1 ttl=60 time=0.519 ms

你可能感兴趣的:(docker)