flannel跨主机通信部署

既然是跨主机,至少需要两台docker主机

实验环境

ip 服务 备注
192.168.1.12 docker(已启动)、etcd、flannel server1
192.168.1.13 docker(已启动)、etcd、flannel server2

实验目的

让docker不同主机的容器通过flannel网络进行分配ip并完成通信

实验步骤

使用flannel要求关闭防火墙,关闭沙盒,开启路由转发

环境准备

使用flannel要求关闭防火墙,关闭沙盒,开启路由转发

server1/server2

路由转发已开启

如果不关防火墙,放行2380/2379/4001三个端口

[root@localhost ~]# systemctl disable firewalld
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# vim /etc/selinux/config 
SELINUX=disabled
[root@localhost ~]# setenforce 0
[root@localhost ~]# getenforce 
Permissive

还需要设置防火墙默认策略(我也不知道为什么)

[root@localhost ~]# iptables -P FORWARD ACCEPT

安装flannel和etcd

[root@localhost ~]# yum -y install flannel etcd

以上操作两台都要做

配置etcd

server1

修改etcd配置文件,可以让etcd来识别两台docker主机,也可以说是集群,为他们去分配ip子网

[root@localhost ~]# cp -p /etc/etcd/etcd.conf /etc/etcd/etcd.conf.bak
[root@localhost ~]# vim /etc/etcd/etcd.conf
# etcd存放数据目录,为了方便改成了和etcd_name一样的名字
ETCD_DATA_DIR="/var/lib/etcd/etcd1"
# 用于与其他节点通信
ETCD_LISTEN_PEER_URLS="http://192.168.1.12:2380"
# 客户端会连接到这里和 etcd 交互
ETCD_LISTEN_CLIENT_URLS="http://192.168.1.12:2379,http://127.0.0.1:2379"
# 节点名称,每台主机都不一样
ETCD_NAME="etcd1"
该节点同伴监听地址,这个值会告诉集群中其他节点
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.1.12:2380"
# 对外公告的该节点客户端监听地址,这个值会告诉集群中其他节点
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.1.12:2379"
# 集群中的主机信息
ETCD_INITIAL_CLUSTER="etcd1=http://192.168.1.12:2380,etcd2=http://192.168.1.13:2380"
# 集群token,建议修改一个,同一个集群中的token一致
ETCD_INITIAL_CLUSTER_TOKEN="etcd-test"
# 新建集群的时候,这个值为new假如已经存在的集群,这个值为 existing
ETCD_INITIAL_CLUSTER_STATE="new"

为了方便修改,直接将文件传到server2

[root@localhost ~]# scp /etc/etcd/* root@192.168.1.13:/etc/etcd/

server2

[root@localhost ~]# vim /etc/etcd/etcd.conf
ETCD_DATA_DIR="/var/lib/etcd/etcd2"
ETCD_LISTEN_PEER_URLS="http://192.168.1.13:2380"
ETCD_LISTEN_CLIENT_URLS="http://192.168.1.13:2379,http://127.0.0.1:2379"
ETCD_NAME="etcd2"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.1.13:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.1.13:2379"

etcd识别配置文件变量

默认刚才修改的内容,都是etcd启动后不会识别的,所以需要在启动文件中添加

server1

[root@localhost ~]# vim /usr/lib/systemd/system/etcd.service 
# 在第十三行(ExecStart开头)末尾的前一个引号里面,添加如下
# 添加时不换行,空格隔开即可
--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}\"

server2与server1一样,传送文件即可

[root@localhost ~]# scp /usr/lib/systemd/system/etcd.service \
root@192.168.1.13:/usr/lib/systemd/system/etcd.service 

启动etcd服务

启动该服务时,会有其中一台阻塞,需要另一台启动之后,阻塞的一端才会重新启动,如果报错,或者启动不了,请仔细检查改过的两个配置文件

systemctl daemon-reload
systemctl start etcd

其实这里的错误卡了我半天,但就是不知道哪里错,好在重做了一遍,分分钟好了

查看集群健康状态

[root@localhost ~]# etcdctl cluster-health
member a25992cd255e2170 is healthy: got healthy result from http://192.168.1.13:2379
member c3f38a23cbf25e25 is healthy: got healthy result from http://192.168.1.12:2379
cluster is healthy

查看集群中leader是哪台

[root@localhost ~]# etcdctl member list
a25992cd255e2170: name=etcd2 peerURLs=http://192.168.1.13:2380 clientURLs=http://192.168.1.13:2379 isLeader=false
c3f38a23cbf25e25: name=etcd1 peerURLs=http://192.168.1.12:2380 clientURLs=http://192.168.1.12:2379 isLeader=true

isLeader=true1.12就是集群中的领导者,ip会从server1的flannel去分配

vxlan类型容器互通

此类型的backend是通过UDP封装来实现的。

server1

让flannel的etcd使用该文件中,定义的backend类型和给定的大网段范围10.10.0.0/16,然后使用24的子网掩码,在该范围中为容器自动划分ip

[root@localhost ~]# vim /root/etcd.json
{
  "NetWork":"10.10.0.0/16",
  "SubnetLen":24,
  "Backend":{
    "Type":"vxlan"
  }
}

将该文件导入etcd集群中

/usr/local/bin/network/config:该路径物理机并没有,是flannel的etcd内的

[root@localhost ~]# etcdctl --endpoints=http://192.168.1.12:2379 \
set /usr/local/bin/network/config < /root/etcd.json

server2

验证server2是否可以读取到已经导入etcd集群中的值

[root@localhost ~]# etcdctl get /usr/local/bin/network/config
{
  "NetWork":"10.10.0.0/16",
  "SubnetLen":24,
  "Backend":{
    "Type":"vxlan"
  }
}

更改flannel配置文件

server1

使得etcd可以识别这个文件

[root@localhost ~]# vim /etc/sysconfig/flanneld
FLANNEL_ETCD_ENDPOINTS="http://192.168.1.12:2379"
FLANNEL_ETCD_PREFIX="/usr/local/bin/network"

server2

与server1一致,除了ip

[root@localhost ~]# vim /etc/sysconfig/flanneld
FLANNEL_ETCD_ENDPOINTS="http://192.168.1.13:2379"
FLANNEL_ETCD_PREFIX="/usr/local/bin/network"

启动flanneld服务

server1/server2

[root@localhost ~]# systemctl enable flanneld
[root@localhost ~]# systemctl start flanneld

查看flannel分配的ip

查看启动flanneld后,随机在10.10.0.0/16地址池中分配的子网ip

server1

server1的ip为10.10.70.0网段

[root@localhost ~]# ip a
...
6: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default 
    link/ether e2:e4:dc:56:06:db brd ff:ff:ff:ff:ff:ff
    inet 10.10.70.0/32 scope global flannel.1
       valid_lft forever preferred_lft forever
    inet6 fe80::e0e4:dcff:fe56:6db/64 scope link 
       valid_lft forever preferred_lft forever

server2

server2的ip为10.10.27.0网段

[root@localhost ~]# ip a
...
6: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default 
    link/ether 8e:01:ac:3d:40:f7 brd ff:ff:ff:ff:ff:ff
    inet 10.10.27.0/32 scope global flannel.1
       valid_lft forever preferred_lft forever
    inet6 fe80::8c01:acff:fe3d:40f7/64 scope link 
       valid_lft forever preferred_lft forever

这是集群中的物理机会多出一个flannel大网段的路由条目,10.10.0.0/16

[root@localhost ~]# ip r
default via 192.168.1.3 dev ens33 proto static metric 100 
10.10.0.0/16 dev flannel.1 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 
192.168.1.0/24 dev ens33 proto kernel scope link src 192.168.1.13 metric 100 
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1 

docker0连接flannel.1

server1

查看子网的MTU值与flannel子网网关

[root@localhost ~]# cat /run/flannel/subnet.env 
FLANNEL_NETWORK=10.10.0.0/16
FLANNEL_SUBNET=10.10.70.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=false

修改docker启动项

[root@localhost ~]# vim /usr/lib/systemd/system/docker.service
# 第十四行末尾添加
--bip=10.10.70.1/24 --mtu=1450

server2

查看子网MTU值与flannel子网网关

[root@localhost ~]# cat /run/flannel/subnet.env 
FLANNEL_NETWORK=10.10.0.0/16
FLANNEL_SUBNET=10.10.27.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=false

修改docker启动项

[root@localhost ~]# vim /usr/lib/systemd/system/docker.service
# 第十四行末尾添加
--bip=10.10.27.1/24 --mtu=1450

server1/server2

重启docker服务

[root@localhost ~]# systemctl daemon-reload 
[root@localhost ~]# systemctl restart docker

这个时候docker0和flannel.1就可以进行连接了

server1

查看docker0与flannel.1

[root@localhost ~]# ip a
...
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:17:be:e7:95 brd ff:ff:ff:ff:ff:ff
    inet 10.10.70.1/24 brd 10.10.70.255 scope global docker0
       valid_lft forever preferred_lft forever
6: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default 
    link/ether e2:e4:dc:56:06:db brd ff:ff:ff:ff:ff:ff
    inet 10.10.70.0/32 scope global flannel.1
       valid_lft forever preferred_lft forever
    inet6 fe80::e0e4:dcff:fe56:6db/64 scope link 
       valid_lft forever preferred_lft forever

查看路由条目,多出了子网的路由条目,可以由docker0来转发

[root@localhost ~]# ip r
default via 192.168.1.3 dev ens33 proto static metric 100 
10.10.0.0/16 dev flannel.1 
10.10.70.0/24 dev docker0 proto kernel scope link src 10.10.70.1 
192.168.1.0/24 dev ens33 proto kernel scope link src 192.168.1.12 metric 100 
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1 

server2

查看docker0与flannel.1

[root@localhost ~]# ip a
...
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:9c:06:7a:d1 brd ff:ff:ff:ff:ff:ff
    inet 10.10.27.1/24 brd 10.10.27.255 scope global docker0
       valid_lft forever preferred_lft forever
6: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default 
    link/ether 8e:01:ac:3d:40:f7 brd ff:ff:ff:ff:ff:ff
    inet 10.10.27.0/32 scope global flannel.1
       valid_lft forever preferred_lft forever
    inet6 fe80::8c01:acff:fe3d:40f7/64 scope link 
       valid_lft forever preferred_lft forever

查看路由条目,多出了子网的路由条目,可以由docker0来转发

[root@localhost ~]# ip r
default via 192.168.1.3 dev ens33 proto static metric 100 
10.10.0.0/16 dev flannel.1 
10.10.27.0/24 dev docker0 proto kernel scope link src 10.10.27.1 
192.168.1.0/24 dev ens33 proto kernel scope link src 192.168.1.13 metric 100 
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1 

运行容器测试

server1

运行容器并进入容器查看ip

[root@localhost ~]# docker run -itd --name bbox1 busybox
8788b00424a2a36d5b1c85c540afc12bdff323c934e8cfa0037dbc6a2f9d94cf
[root@localhost ~]# docker exec -it bbox1 /bin/sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
7: eth0@if8: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue 
    link/ether 02:42:0a:0a:46:02 brd ff:ff:ff:ff:ff:ff
    inet 10.10.70.2/24 brd 10.10.70.255 scope global eth0
       valid_lft forever preferred_lft forever

Bbox1容器ip自动分配了flanneld分配的子网网段10.10.70.0/24中的10.10.70.2

server2

运行容器并进入容器查看ip

[root@localhost ~]# docker run -itd --name bbox2 busybox
ce22f36ea42601c58ef35dbf28aae4c28e3a356475d8c3972d17aecdcb5051be
[root@localhost ~]# docker exec -it bbox2 /bin/sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
7: eth0@if8: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue 
    link/ether 02:42:0a:0a:1b:02 brd ff:ff:ff:ff:ff:ff
    inet 10.10.27.2/24 brd 10.10.27.255 scope global eth0
       valid_lft forever preferred_lft forever

bbox2容器ip自动分配了flanneld分配的子网网段10.10.27.0/24中的10.10.27.2

进行发送ping包测试

如果你的防火墙是放行的端口,在这里请stop防火墙,否则ping不同

/ # ping 10.10.70.2
PING 10.10.70.2 (10.10.70.2): 56 data bytes
64 bytes from 10.10.70.2: seq=0 ttl=62 time=0.629 ms
64 bytes from 10.10.70.2: seq=1 ttl=62 time=0.520 ms

与外网也是可以通过docker0去转发的

host-gw类型容器互通

与vxlan的区别在于,它的路由路径如下:

server1

/ # traceroute 10.10.27.2
traceroute to 10.10.27.2 (10.10.27.2), 30 hops max, 46 byte packets
 1  10.10.70.1 (10.10.70.1)  0.013 ms  0.011 ms  0.008 ms
 2  10.10.27.0 (10.10.27.0)  3.220 ms  0.387 ms  0.167 ms
 3  10.10.27.2 (10.10.27.2)  0.173 ms  1.595 ms  0.888 ms

10.10.70.2与10.10.27.2的路由转发路径是这样的

10.10.70.2>10.10.70.1>10.10.27.0>10.10.27.2

全部都是经过容器的ip网段来转发的,尽管也通过了docker0

而host-gw的意义就在于,它是通过物理机的ip来进行转发的

只需要基于以上实验,修改导入etcd的IP地址池那个文件中的类型即可

[root@localhost ~]# vim etcd.json
{
  "NetWork":"10.10.0.0/16",
  "SubnetLen":24,
  "Backend":{
    "Type":"host-gw"
  }
}

重新导入到etcd中

[root@localhost ~]# etcdctl --endpoints=http://192.168.1.12:2379 set /usr/local/bin/network/config < /root/etcd.json
{
  "NetWork":"10.10.0.0/16",
  "SubnetLen":24,
  "Backend":{
    "Type":"host-gw"
  }
}

server2

验证是否导入成功

[root@localhost ~]# etcdctl get /usr/local/bin/network/config
{
  "NetWork":"10.10.0.0/16",
  "SubnetLen":24,
  "Backend":{
    "Type":"host-gw"
  }
}

server1

重启flanneld,再次查看MTU变为了1500

[root@localhost ~]# systemctl restart flanneld
[root@localhost ~]# cat /run/flannel/subnet.env 
FLANNEL_NETWORK=10.10.0.0/16
FLANNEL_SUBNET=10.10.70.1/24
FLANNEL_MTU=1500
FLANNEL_IPMASQ=false

此时再次查看路由条目

[root@localhost ~]# ip r
default via 192.168.1.3 dev ens33 proto static metric 100 
10.10.0.0/16 dev flannel.1 
10.10.27.0/24 via 192.168.1.13 dev ens33 
10.10.70.0/24 dev docker0 proto kernel scope link src 10.10.70.1 
192.168.1.0/24 dev ens33 proto kernel scope link src 192.168.1.12 metric 100 
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1 

多出了集群中非本机容器的ip子网网段,并且由集群中该容器的物理机的地址去转发

也就是说两个主机之间的容器要进行通信,现在由各自主机的ens33来转发

修改docker启动项中的MTU值

[root@localhost ~]# vim /usr/lib/systemd/system/docker.service
# 修改--mtu=1500即可

重启docker

[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl restart docker

server2

执行相同的步骤

重启flanneld,修改MTU值,重启docker

容器路由跟踪测试

由于刚才重启了docker,所以容器全都停了,重新启动进行验证即可

[root@localhost ~]# docker start bbox2
bbox2

server1

[root@localhost ~]# docker start bbox1
bbox1
[root@localhost ~]# docker exec -it bbox1 /bin/sh
/ # traceroute 10.10.27.2
traceroute to 10.10.27.2 (10.10.27.2), 30 hops max, 46 byte packets
 1  10.10.70.1 (10.10.70.1)  0.014 ms  0.011 ms  0.008 ms
 2  192.168.1.13 (192.168.1.13)  2.675 ms  0.483 ms  0.362 ms
 3  10.10.27.2 (10.10.27.2)  1003.607 ms  0.432 ms  0.372 ms

这时的路由跟踪看出,两个容器是经过物理机的ens33的IP地址来转发的。

vxlan和host-gw的区别

1、

host-gw把每个物理机都配置为容器的子网网关,每个物理机都知道各自内的子网和如何转发。

vxlan是在物理机之间建立vxlan隧道,不同的物理机的容器都在vxlan的一个大网中。

2、

两种虽然都使用不同的机制建立容器间的通信,但是对于容器则不需要任何改变。

3、

由于vxlan需要对数据进行额外封装,性能较差。

而相反host-gw的性能就相对较好。

评论




正在载入...
PoweredHexo
HostedAliyun
DNSAliyun
ThemeVolantis
UV
PV
BY-NC-SA 4.0