当然,在单独安装Flanneld之前回顾一下本人前面写的相关的flanneld 的文章
Flannel是一种基于overlay网络的跨主机容器网络解决方案,也就是将TCP数据包封装在另一种网络包里面进行路由转发和通信,
Flannel是CoreOS开发,专门用于docker多机互联的一个工具,让集群中的不同节点主机创建的容器都具有全集群唯一的虚拟ip地址
Flannel使用go语言编写
Flannel为每个host分配一个subnet,容器从这个subnet中分配IP,这些IP可以在host间路由,容器间无需使用nat和端口映射即可实现跨主机通信
每个subnet都是从一个更大的IP池中划分的,flannel会在每个主机上运行一个叫flanneld的agent,其职责就是从池子中分配subnet
Flannel使用etcd存放网络配置、已分配 的subnet、host的IP等信息
Flannel数据包在主机间转发是由backend实现的,目前已经支持UDP、VxLAN、host-gw、AWS VPC和GCE路由等多种backend
- 容器直接使用目标容器的ip访问,默认通过容器内部的eth0发送出去。
- 报文通过veth pair被发送到vethXXX。
- vethXXX是直接连接到虚拟交换机docker0的,报文通过虚拟bridge docker0发送出去。
- 查找路由表,外部容器ip的报文都会转发到flannel0虚拟网卡,这是一个P2P的虚拟网卡,然后报文就被转发到监听在另一端的flanneld。
- flanneld通过etcd维护了各个节点之间的路由表,把原来的报文UDP封装一层,通过配置的iface发送出去。
- 报文通过主机之间的网络找到目标主机。
- 报文继续往上,到传输层,交给监听在8285端口的flanneld程序处理。
- 数据被解包,然后发送给flannel0虚拟网卡。
- 查找路由表,发现对应容器的报文要交给docker0。
- docker0找到连到自己的容器,把报文发送过去。
Falnnel要用etcd存储自身一个子网信息,所以要保证能成功连接Etcd,写入预定义子网段:
cd /etc/ssl/kubernetes/
etcdctl \
--ca-file=ca.pem --cert-file=kubernetes.pem --key-file=kubernetes-key.pem \
--endpoints="https://10.211.55.11:2379,https://10.211.55.12:2379,https://10.211.55.13:2379" ls
set /coreos.com/network/config '{ "Network": "172.17.0.0/16", "Backend": {"Type": "vxlan"}}'
- Network:用于指定Flannel地址池
- SubnetLen:用于指定分配给单个宿主机的docker0的ip段的子网掩码的长度
- SubnetMin:用于指定最小能够分配的ip段
- SudbnetMax:用于指定最大能够分配的ip段,在上面的示例中,表示每个宿主机可以分配一个16位掩码长度的子网
- Backend:用于指定数据包以什么方式转发,默认为udp模式,host-gw模式性能最好,但不能跨宿主机网络
下载二进制包
wget https://github.com/coreos/flannel/releases/download/v0.11.0/flannel-v0.11.0-linux-amd64.tar.gz
tar -zxvf flannel-v0.11.0-linux-amd64.tar.gz
mv flanneld mk-docker-opts.sh /usr/bin/
vim /etc/flanneld.conf
FLANNEL_OPTIONS="--etcd-endpoints=https://10.211.55.11:2379,
https://10.211.55.12:2379,https://10.211.55.13:2379 -etcd-cafile=/etc/kubernetes/ca.pem
-etcd-certfile=/etc/kubernetes/kubernetes.pem -etcd-keyfile=/etc/kubernetes/kubernetes-key.pem"
启动脚本
[Unit]
Description=Flanneld overlay address etcd agent
After=network-online.target network.target
Before=docker.service
[Service]
Type=notify
EnvironmentFile=/etc/flanneld.conf
ExecStart=/usr/bin/flanneld --ip-masq $FLANNEL_OPTIONS
ExecStartPost=/usr/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/subnet.env
Restart=on-failure
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl start flanneld
systemctl enable flanneld
Flannel启动过程解析:
- 从etcd中获取network的配置信息
- 划分subnet,并在etcd中进行注册
- 将子网信息记录到/run/flannel/subnet.env中
查看etcd中存入的子网信息
[root@k8s-master1 ~]# etcdctl --ca-file=/etc/etcd/ssl/ca.pem -etcd-cafile=/etc/kubernetes/ca.pem \
-etcd-certfile=/etc/kubernetes/kubernetes.pem -etcd-keyfile=/etc/kubernetes/kubernetes-key.pem \
--endpoints="https://10.211.55.11:2379,https://10.211.55.12:2379,https://10.211.55.13:2379" ls /coreos.com/network/subnets
/coreos.com/network/subnets/172.17.69.0-24
/coreos.com/network/subnets/172.17.55.0-24
/coreos.com/network/subnets/172.17.51.0-24
对应的网卡信息:
ifconfig flannel.1
flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450
inet 172.17.55.0 netmask 255.255.255.255 broadcast 0.0.0.0
ether 1e:5b:2c:3d:ae:89 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
可以看到flannel0网卡的地址和etcd存储的地址一样,这样flannel网络配置完成
Docker安装以后需要修改其启动参数以使其能够使用flannel进行IP分配,以及网络通讯
在Flannel运行之后,会生成一个环境变量文件/run/flannel/subnet.env ,可以使用flannel提供的脚本将subnet.env转写成Docker启动参数,创建好的启动参数默认生成在/run/docker_opts.env文件中:
,包含了当前主机要使用flannel通讯的相关参数,如下:
可以使用flannel提供的脚本将subnet.env转写成Docker启动参数,创建好的启动参数默认生成在/run/docker_opts.env文件中:
# /opt/flannel/mk-docker-opts.sh -c
[root@k8s-master1 ~]# cat /run/flannel/subnet.env
DOCKER_OPTS=" --bip=172.17.55.1/24 --ip-masq=false --mtu=1450"
通过上面flanneld的启动脚本可以看到(红色部分),我们把 DOCKER 启动需要的参数生成到 /run/flannel/subnet.env,当然也可以指定默认配置文件/run/docker_opts.env
# vim /lib/systemd/system/docker.service
EnvironmentFile=/run/docker_opts.env
ExecStart=/usr/bin/dockerd $DOCKER_OPTS -H fd://
我们这里面推荐下面的方式
vim /usr/lib/systemd/system/docker.service
修改docker的服务启动文件
vim /usr/lib/systemd/system/docker.service
[Service]
EnvironmentFile=/run/flannel/subnet.env
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock $DOCKER_NETWORK_OPTIONS
systemctl daemon-reload
systemctl start flanneld
systemctl enable flanneld
systemctl restart docker
说明一下Flannel必须先于Docker启动,因为docker 依赖的参数是flanneld启动生成的
这时可以看到docker0的ip已经位于flannel网卡的网段之中:
查看生成的路由规则
我3台都部署了flanneld
所以会看到3条路由表,同时和etcd存储的消息一致
route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.211.55.1 0.0.0.0 UG 0 0 0 eth0
10.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 eth0
169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 eth0
172.17.51.0 172.17.51.0 255.255.255.0 UG 0 0 0 flannel.1
172.17.55.0 0.0.0.0 255.255.255.0 U 0 0 0 docker0
172.17.69.0 172.17.69.0 255.255.255.0 UG 0 0 0 flannel.1
172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 br-18d0011e4542
测试
在各节点依次ping 各个docker0 的地址
如果能通说明Flannel部署成功。如果不通检查下日志:
journalctl -u flannel
tail -f /var/log/messages
这里说明一下,一定要确保连接的ETCD 没问题,确保3台节点的数据都一致,之前遇到一个问题是ETCD 各节点数据不一致,导致路由规则生成有问题
各节点分配的iP不通