学习目的:
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的工作原理
分析:
我们有两个容器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的配置文件
然后修改一下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服务
查看etcd集群状态
[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的配置文件
然后start flannel的服务即可,这个时候我们发现多出了一个叫做flannel.1的网卡,并且地址都是唯一的,根据上面定义的Network池随机生成的唯一的地址
并且这个时候flannel会生成一个子网环境的文件,我们的容器地址就是根据这个生成的
因此这个时候我们去强行修改docker的启动参数,这里主要是修改bip,即docker0网桥的网段地址
根据subnet.env这个文件去对应的主机上修改。
重启docker服务,查看docker0是否修改成功
这个时候测试一下在两台主机上分别起一个容器,然后ping一下ip地址
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
- / #
第二个走向是到10.10.89.0这个网址,这个是对端主机的flannel.1的地址
这里了解一下流量从容器里面出来,怎么从宿主机出去的
还是看路由
[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.service文件
重启docker服务即可,然后启动容器
通过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 (192.168.64.150) 0.327 ms 0.459 ms 0.475 ms
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模式的区别
总结:
host-gw模式把每个主机地址都配成网关。
vxlan则是在主机之间建立一个隧道,通过最长匹配原则进入到flannel.1网卡。