学习目的:

1. 容器跨主机通讯

2. 了解flannel的host-gw和vxlan模式的区别

我们之前学习的overlay网络,它是在现有的物理网络层上在附加一层网络,采用的是两块网卡,两个空间的方式,让我们两台不同主机的容器之间可以互相通信,并且创建好自己的网段。。

今天我们学习另外一种方法,不基于我们之前的这种再创建一层覆盖的网络,而是自己来做一个独立的网段和分配,这个就是flannel网络。

flannel网络不是创建一层网络,而是自己做一个独立的网段分配。它给每一个主机分配一个subnet,容器会这个subnet中分配ip,这些ip就可以在我们主机间进行路由,容器之间不需要做任何操作,像之前的nat,端口映射等等,就可以完全实现我们一个跨主机通信的方法。每一个subnet都是从一个更大的ip地址池中进行划分,这里就涉及到子网划分的知识点,这个后期可以学习一下。

flannel在每个主机上运行一个叫做flanneld的进程,相当于agent客户端的功能。

数据包是如何在主机间进行转发的呢,是由一个叫做后端backend,这个backend有两种模式,一个是host-gw,一个是vxlan。

vxlan:必然是建立一个通道,要有自己地址的一个封装。

host-gw:就是把主机地址充当成网关。

简单的来说,flannel就是让集群当中不同的节点当中主机创建的docker容器都具有一个全局唯一的虚拟ip,但是我们知道,在docker中,默认都是跟docker0是同一个网段的,所以在不同主机中就不会得到全局唯一的虚拟网卡ip地址,我们flannel的思路就是强行修改本地桥接卡的地址(docker0),变成唯一的地址段。换句话说,flannel就是集中所有节点,重新规划ip地址池的使用,这样我们所有节点就会同属于一个内网且不会有重复的IP地址。

flannel的工作原理

docker启动flink集群 docker使用flannel_docker启动flink集群

分析:

我们有两个容器container A和container B,然后分别通过veth pair对连接到容器容器外边,我们的flannel会强行修改docker0的网卡地址,然后到我们的flanneld这个客户端的程序,它负责数据的转发,ens33为物理机网卡,通过udp进行转发,如果后端是vxlan,那么转发端口就是8472号。

etcd集群搭建

首先需要搭建一套etcd集群,因为需要存取flannel的数据。

关闭防火墙和selinux,并且开启iptables转发

iptables -P FORWARD ACCEPT

两个主机的IP地址:192.168.64.150和192.168.64.129

先修改etcd的配置文件

docker启动flink集群 docker使用flannel_flannel_02

 然后修改一下etcd的service文件

[root@lee-x86-node01 system]# cat etcd.service 
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
WorkingDirectory=/var/lib/etcd/
EnvironmentFile=-/etc/etcd/etcd.conf
User=etcd
# set GOMAXPROCS to number of processors
ExecStart=/bin/bash -c "GOMAXPROCS=$(nproc) /usr/bin/etcd --name=\"${ETCD_NAME}\" --data-dir=\"${ETCD_DATA_DIR}\" --listen-client-urls=\"${ETCD_LISTEN_CLIENT_URLS}\" --listen-peer-urls=\"${ETCD_LISTEN_PEER_URLS}\" --advertise-client-urls=\"${ETCD_ADVERTISE_CLIENT_URLS}\" --initial-cluster-token=\"{$ETCD_INITIAL_CLUSTER_TOKEN}\" --initial-cluster=\"${ETCD_INITIAL_CLUSTER}\" --initial-cluster-state=\"${ETCD_INITIAL_CLUSTER_STATE}\""
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
[root@lee-x86-node01 system]#

修改完成,保存退出,启动etcd服务

docker启动flink集群 docker使用flannel_linux_03

 查看etcd集群状态

docker启动flink集群 docker使用flannel_flannel_04

[root@lee-x86-node01 system]# etcdctl member list

14988b7f6e50e5f2: name=etcd1 peerURLs=http://192.168.64.150:2380 clientURLs=http://192.168.64.150:2379 isLeader=true

ea970339ce10000d: name=etcd2 peerURLs=http://192.168.64.129:2380 clientURLs=http://192.168.64.129:2379 isLeader=false

[root@lee-x86-node01 system]#

这时候就可以把我们准备的服务放到etcd中去,这里就是flannel的相关配置信息

[root@lee-x86-node01 ~]# cat etcd.sh

{ "Network":"10.10.0.0/16","SubnetLen":24,"Backend":{"Type":"vxlan"} }

[root@lee-x86-node01 ~]#

Network:定义host主机的IP地址池是10.10.0.0

SubnetLen:表示每个主机分配到的子网掩码的长度是多少,这里是24表示你会得到一个10.10.x.0/24的backend。

然后把这个文件写入到我们的etcd中去

[root@lee-x86-node01 ~]# etcdctl --endpoints=http://192.168.64.150:2379 set /usr/local/bin/network/config < /root/etcd.sh 
{"Network":"10.10.0.0/16","SubnetLen":24,"Backend":{"Type":"vxlan"}}

[root@lee-x86-node01 ~]#

因为在同一个etcd集群中,数据都是共享的,然后去我们的另外一台主机直接get一下

[root@x86-104 ~]# etcdctl get /usr/local/bin/network/config

{"Network":"10.10.0.0/16","SubnetLen":24,"Backend":{"Type":"vxlan"} }

[root@x86-104 ~]#

可以得到value值,证明etcd写入成功。

接下来就可以去试验我们的flannel网络了

先去配置flannel的配置文件

docker启动flink集群 docker使用flannel_运维_05

 然后start flannel的服务即可,这个时候我们发现多出了一个叫做flannel.1的网卡,并且地址都是唯一的,根据上面定义的Network池随机生成的唯一的地址

docker启动flink集群 docker使用flannel_docker_06

 并且这个时候flannel会生成一个子网环境的文件,我们的容器地址就是根据这个生成的

docker启动flink集群 docker使用flannel_flannel_07

因此这个时候我们去强行修改docker的启动参数,这里主要是修改bip,即docker0网桥的网段地址

根据subnet.env这个文件去对应的主机上修改。

docker启动flink集群 docker使用flannel_flannel_08

 

docker启动flink集群 docker使用flannel_linux_09

 重启docker服务,查看docker0是否修改成功

docker启动flink集群 docker使用flannel_docker_10

这个时候测试一下在两台主机上分别起一个容器,然后ping一下ip地址

docker启动flink集群 docker使用flannel_运维_11

 ok,上面就是容器通过flannel的vxlan方式简单的通讯,这里我们跟踪一下流量的转发

/ # traceroute 10.10.89.2

traceroute to 10.10.89.2 (10.10.89.2), 30 hops max, 46 byte packets

1 10.10.32.1 (10.10.32.1) 0.015 ms 0.016 ms 0.018 ms

2 10.10.89.0 (10.10.89.0) 3.370 ms 0.448 ms 0.796 ms

3 10.10.89.2 (10.10.89.2) 2.324 ms 0.689 ms 0.503 ms

/ #

发现第一步流向10.10.32.1这个网段,这个其实是我们容器里面的网关地址(其实根据之前的经验可以知道,容器流量出去走的都是网关,这个网关其实就是桥接卡的地址)

/ # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.10.32.1      0.0.0.0         UG    0      0        0 eth0
10.10.32.0      0.0.0.0         255.255.255.0   U     0      0        0 eth0
/ #

docker启动flink集群 docker使用flannel_docker启动flink集群_12

 第二个走向是到10.10.89.0这个网址,这个是对端主机的flannel.1的地址

docker启动flink集群 docker使用flannel_运维_13

这里了解一下流量从容器里面出来,怎么从宿主机出去的

还是看路由

[root@x86-104 ~]# ip r

default via 192.168.64.2 dev ens33 proto dhcp metric 100

10.10.0.0/16 dev flannel.1

10.10.32.0/24 dev docker0 proto kernel scope link src 10.10.32.1

192.168.64.0/24 dev ens33 proto kernel scope link src 192.168.64.129 metric 100

192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1

[root@x86-104 ~]#

物理机到了10.10.32.0这个网段,然后根据路由最长匹配规则把流量给到flannel.1这个网卡上,到了flannel.1之后,flannel就把数据包封装成vxlan模式,然后通过物理机网卡传到对端主机上去。

修改模式为host-gw看看

[root@lee-x86-node01 ~]# cat etcd.sh

{ "Network":"10.10.0.0/16","SubnetLen":24,"Backend":{"Type":"host-gw"} }

[root@lee-x86-node01 ~]#

重新导入到etcd集群中去

[root@lee-x86-node01 ~]# etcdctl --endpoints=http://192.168.64.150:2379 set /usr/local/bin/network/config < /root/etcd.sh

{ "Network":"10.10.0.0/16","SubnetLen":24,"Backend":{"Type":"host-gw"} }

[root@lee-x86-node01 ~]#

然后重启flannel服务

docker启动flink集群 docker使用flannel_linux_14

然后修改docker.service文件

docker启动flink集群 docker使用flannel_linux_15

 重启docker服务即可,然后启动容器

docker启动flink集群 docker使用flannel_运维_16

 通过traceroute我们发现流量走向跟vxlan的不一样了。第二条匹配的是对端物理机网卡地址,而vxlan匹配的是桥接卡的地址

/ # traceroute 10.10.89.2

traceroute to 10.10.89.2 (10.10.89.2), 30 hops max, 46 byte packets

1 10.10.32.1 (10.10.32.1) 0.013 ms 0.016 ms 0.013 ms

2 192.168.64.150

3 10.10.89.2 (10.10.89.2) 0.392 ms 0.502 ms 0.644 ms

/ #

这个时候看一下物理机路由(黄色字体为对端网络的IP地址)

[root@x86-104 /]# ip r

default via 192.168.64.2 dev ens33 proto dhcp metric 100

10.10.0.0/16 dev flannel.1

10.10.32.0/24 dev docker0 proto kernel scope link src 10.10.32.1

10.10.89.0/24 via 192.168.64.150 dev ens33

192.168.64.0/24 dev ens33 proto kernel scope link src 192.168.64.129 metric 100

192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1

[root@x86-104 /]#

如果使用的是host-gw的话,它会把对端的主机地址换过来,根据下面的路由总图也可以知道host-gw模式的区别

docker启动flink集群 docker使用flannel_运维_17

总结:

host-gw模式把每个主机地址都配成网关。

vxlan则是在主机之间建立一个隧道,通过最长匹配原则进入到flannel.1网卡。