12. 最常见的方案@flannel

forewords

我们从最底下开始一路向上, 中间串了一大堆奇奇怪怪又不可或缺的东西, 现在我们终于来到最上层的K8s网络插件啦, 感觉好像你玩了很久的塞尔达, 打了不少小怪, 做了一堆支线剧情, 现在终于看到第一个小boss了, 终于到了我们的flannel了! 这家伙在我看来是K8s网络中最经典的玩法, 不少网课教程里都用默认使用这个插件来介绍K8s网络, 据我的了解它目前也是很多大公司落地最广的方案.

那我们再回顾一下K8s网络中的一些基本概念与基本矛盾, 我们现在有好几多从节点, 然后想要在上面布置一些pod. 每个pod我们都会给它一个虚拟IP, pod间彼此通过这个虚拟IP相互通信. 我们要做的就是使这一切发生, 在这其中的基本矛盾包含两个方面:

  • pod ip 重复问题: 我们想在从节点上起容器, docker会从指定网段中拿出一个(虚拟)IP给容器, 如果不同pod之间想要通过虚拟IP通信, 那么我们就要使得所有容器的ip之间不能重复, 这个比较容易, 每个节点上的flanneld去etcd那儿注册自己节点上的网段, 然后挑一个没人用的网段, 拿来给自己的docker用就可以了

  • 虚拟ip路由的问题: 提到虚拟ip, 就会有物理ip, 虚拟ip指容器被分到的ip, 物理ip指物理机上的ip, 容器在发包的时候会把自己的虚拟ip封到ip头里, 然后通过物理网络发送过去, 然而这个虚拟ip在物理网络上是没有人认识也不知道从哪儿传送过去, 为了解决这个问题, flannel提出了两类方案:

    • Overlay 风格的网络: 所谓overlay就是在虚拟ip头上封一个宿主机ip, 然后发送到对端宿主机上, 对面宿主机拆开头以后, 把包传递给自己身上的虚拟ip就可以了, 封包的方法有 udp, 以及 vxlan 两种

    • 路由风格的网络: 我们的问题在于虚拟IP没有人认识, 那么我们直接改写所有宿主机身上的路由表, 这下大家都认识了, 你的包就可以发了, 没有了封包的过程, 通信效率堪比宿主机通信, 但是这里的毛病在于你只能修改宿主机, 如果你想穿越这个局域网途径路由器到达另一个局域网呢? 路由器可是不认识这个人的, 直接就丢掉了, 当然我们也有一些手段能让这这一切发生, 总的来说这种方式我们叫它 host-gateway 玩法

flannel的启动流程

最简单的方法通过 kubectl 自动化启动, 但为了搞明白发生了什么我们说说手动起flannel的过程, "起flannel" 指的是 编写配置文件 + 使flanneld在每个节点上都运行起来 两步. 比如我们可以这样:

# flannel整体的网段, 所有宿主机申请的网段都会在这其中
$ etcdctl set /coreos.com/network/config '{"Network":"172.17.0.0/16"}'

# 然后你去 所有的从节点上:
$ flanneld &

这样所有节点上都运行了flanneld, flannel就起起来了, 它在启动的时候做了这些事:

  • 从etcd里查整体网段是什么样的

  • 从中挑出一个没人用的, 作为自己这个节点上的容器网段

  • 将取到的网段信息记录在/run/flannel/subnet.env, 并将这个文件改成Docker的环境变量文件 /docker/flannel/docker

# 看一下, flannel是如何在 etcd中挑一个没人用的网段, 并注册自己网段的
$ etcdctl ls /coreos.com/network/subnets
/coreos.com/network/subnets/172.17.18.0-24 # 节点-1 使用的网段
/coreos.com/network/subnets/172.17.19.0-24 # 节点-2 使用的网段
/coreos.com/network/subnets/172.17.20.0-24 # 节点-3 使用的网段

# 看一下, 是那个节点占用的这个网段
$ etcdctl get /coreos.com/network/subnets/172.17.18.0-24
{"PublicIP":"192.168.14.97"} # 噢原来是节点-1啊, 这是节点-1的公网IP

# flannel取到了自己的网段以后, 会生成一个docker配置文件, 如下:
DOCKER_OPT_BIP="--bip=172.17.18.0/24" 
DOCKER_OPT_IPMASQ="--ip-masq=true"
DOCKER_OPT_OPTIONS="--bip=172.17.18.0 --ip-masq=true"

ehhh...

我们已经划分好网段了, 那么第一个问题就已经解决了, 接下来我们可以开始讨论如何通信的问题了, 这东西说到底也就是个 "如何把包传递过去" 的问题, 实现方案有 udp / vxlan / host-gateway 三种, 我们在下一篇开始整活!

Last updated

Was this helpful?