# ps -ef|grep docker|grep bip
FLANNEL_OPTIONS="-ip-masq=true"
-ip-masq=true 这个参数的目的是让flannel进行ip伪装,而不让docker进行ip伪装。这么做的原因是如果docker进行ip伪装,流量再从flannel出去,其他host上看到的source ip就是flannel的网关ip,
而不是docker容器的ip。
-----------------------------------------------------------------------------------------------------------------------
Flannel是一个专为kubernetes定制的三层网络解决方案,主要用于解决容器的跨主机通信问题。
Flannel 是由 CoreOS 维护的一个虚拟网络方案。Flannel为每个host分配一个subnet,容器从此subnet中分配ip。这些ip可以在host间路由,容器间无需nat和port mapping就可以跨主机通讯。
首先,flannel利用Kubernetes API或者etcd用于存储整个集群的网络配置,其中最主要的内容为设置集群的网络地址空间。例如,设定整个集群内所有容器的IP都取自网段“10.1.0.0/16”。
接着,flannel在每个主机中运行flanneld作为agent,它会为所在主机从集群的网络地址空间中,获取一个小的网段subnet,本主机内所有容器的IP地址都将从中分配。
然后,flanneld再将本主机获取的subnet以及用于主机间通信的Public IP,同样通过kubernetes API或者etcd存储起来。
最后,flannel利用各种backend mechanism,例如udp,vxlan等等,跨主机转发容器间的网络流量,完成容器间的跨主机通信。
使用Flannel ,添加一台新机器到集群时,Flannel 做了三件事:
- 使用 etcd 为新增机器分配一个子网
- 在宿主机上创建一个虚拟桥接接口(名为 docker0 的桥接器)
- 设置一个网络转发后端
aws-vpc
:在 Amazon AWS 实例表中注册新增机器子网。该实例表最多支持 50 项记录,这意味着,如果你使用 flannel + aws-vpc 方案,集群最多只能包含 50 台机器,集群也只能运行在 AWS 云平台。host-gw
:通过远程机器 IP ,创建到子网的 IP 路由。这要求运行 flannel 的不同主机在二层直接互通(通过mac地址进行通信)。vxlan
:创建一个虚拟的 VXLAN 接口。(扩展的虚拟局域网)
由于 flannel 使用桥接接口转发网络包,从一个容器发往另一个容器的网络包将历经两个网络栈。
Flannel通信原理如图:
步骤:
- IP数据报被封装并通过容器的eth0发送。
- Container1的eth0通过veth对与Docker0交互并将数据包发送到Docker0。然后Docker0转发包。
- Docker0确定Container3的IP地址,通过查询本地路由表到外部容器,并将数据包发送到虚拟NIC Flannel0。
- Flannel0收到的数据包被转发到Flanneld进程。 Flanneld进程封装了数据包通过查询etcd维护的路由表并发送数据包通过主机的eth0。
- 数据包确定网络中的目标主机主机。
- 目的主机的Flanneld进程监听8285端口,负责解封包。
- 解封装的数据包将转发到虚拟NICFlannel0。
- Flannel0查询路由表,解封包,并将数据包发送到Docker0。
- Docker0确定目标容器并发送包到目标容器。
添加flannel网络配置信息到Etcd集群:
etcdctl --endpoints=https://172.17.213.60:2379 \--cert-file=/etc/kubernetes/ssl/etcd.pem \--ca-file=/etc/kubernetes/ssl/ca.pem \--key-file=/etc/kubernetes/ssl/etcd-key.pem \set /flannel/network/config \ '{"Network":"10.254.64.0/18","SubnetLen":24,"Backend":{"Type":"vxlan"}}'
- Network:用于指定Flannel地址池
- SubnetLen:用于指定分配给单个宿主机的docker0的ip段的子网掩码的长度
- SubnetMin:用于指定最小能够分配的ip段
- SudbnetMax:用于指定最大能够分配的ip段,"SubnetMin": "10.0.1.0","SubnetMax": "10.0.20.0",表示每个宿主机可以分配一个24位掩码长度的子网,可以分配的子网从10.0.1.0/24到10.0.20.0/24,也就意味着在这个网段中,最多只能有20台宿主机
- Backend:用于指定数据包以什么方式转发,默认为udp模式,host-gw模式性能最好,但不能跨宿主机网络
Flannel启动过程解析:
- 从etcd中获取network的配置信息
- 划分subnet,并在etcd中进行注册
- 将子网信息记录到/run/flannel/subnet.env中
验证Flannel网络
查看etcd中的数据:
$etcdctl --endpoints=${ETCD_ENDPOINTS} \--ca-file=/etc/kubernetes/ssl/ca.pem \--cert-file=/etc/kubernetes/ssl/kubernetes.pem \--key-file=/etc/kubernetes/ssl/kubernetes-key.pem \ls /kube-centos/network/subnets
/kube-centos/network/subnets/172.30.14.0-24
/kube-centos/network/subnets/172.30.38.0-24
/kube-centos/network/subnets/172.30.46.0-24$etcdctl --endpoints=${ETCD_ENDPOINTS} \--ca-file=/etc/kubernetes/ssl/ca.pem \--cert-file=/etc/kubernetes/ssl/kubernetes.pem \--key-file=/etc/kubernetes/ssl/kubernetes-key.pem \get /kube-centos/network/config
{ "Network": "172.30.0.0/16", "SubnetLen": 24, "Backend": { "Type": "vxlan" } }$etcdctl --endpoints=${ETCD_ENDPOINTS} \--ca-file=/etc/kubernetes/ssl/ca.pem \--cert-file=/etc/kubernetes/ssl/kubernetes.pem \--key-file=/etc/kubernetes/ssl/kubernetes-key.pem \get /kube-centos/network/subnets/172.30.14.0-24
{"PublicIP":"172.20.0.114","BackendType":"vxlan","BackendData":{"VtepMAC":"56:27:7d:1c:08:22"}}
参考资料: https://segmentfault.com/a/1190000016304924?utm_source=tag-newest