kuber-router踩坑记

2020-06-15

导语

kube-router大名鼎鼎,’A turn-key Kubernetes networking solution purpose built for operational simplicity and performance’.总结起来就一句:操作简单,性能高效。目标是取代kube-proxy和一众cni插件(如flannel、calico等)。

kube-router采用lvs实现svc网络,采用bgp实现pod网络

用一副图,概括它的主要特性:
upload successful

选型考虑

我们本地机房的开发环境和自动化测试环境有自己的特点,我们需要连上公司的办公网络,就可以直接访问集群里的PodIP和CluterIP,这样更方便测试和排查问题,所以需要一种机制把集群里的Pod网络和虚拟ClusterIP网络给引出来。

Kube-router替代kube-proxy可行性分析

kube-proxy的作用主要是用于监听API server中 service 和endpoint的变化情况,并通过iptables或ipvs等为服务配置负载均衡。kube-router采用了相同技术的实现流量转发,服务发现。因此可以直接替代kubeproxy来为服务配置负载均衡

Kube-router替代flannel/Calico可行性分析

kubernetes 对网络的要求是:容器之间(包括同一台主机上的容器,和不同主机的容器)可以互相通信,容器和集群中所有的节点也能直接通信。

在kube-router出现之前,kubernetes长期以来使用第三方模块来负责网络模块配置,其中flannel是其中较为常用的一个,以flannel为例。

flannel在集群中的功能主要有以下两点:

能够给每个 Node 分配互不冲突的网段,意味着集群内每个容器有着互不冲突的 IP 地址;(指定 docker 启动参数的方式指定网段)

能够建立一个覆盖网络,通过这个覆盖网络,能将数据包原封不动传递到目标容器内。(这里传递通常是 UDP 数据包)

在实际运行过程中,每个节点需要部署一个flannel服务,部署成功后会生成一个flannel.0的虚拟设备,同时会运行运行flanneld的进程,用以链接flannel.0和物理网卡。传输过程中的数据包通过路由规则判断,如果是本网段的访问,就会走docker0网桥;如果是跨网段,也就是要跨宿主机访问,就会将数据发往flannel.0flanneld将数据包封装成底层通信包,协议包括UDP、Vxlan等,这里往往用的是UDP,这个UDP 的packet 会根据 etcd 存放的路由表(一般会缓存到主机内存里)找到目的容器 IP所承载的宿主机 IP,不借助第三方路由设备的前提下,数据包发送到了宿主机上。此时目标宿主机的flanneld进程会对 UDP包进行解包操作,转化成数据包原本的协议,最终根据主机内部路由流入到目标容器中。

Kuberouter不像flannel一样采用子网管理的方式,而是利用kube-conroller-manager来做子网分配,每一个节点会根据cluster CIDR被分配到集群中独一无二的子网ip。Kube-router在每个节点上运行IBGP,并生成kube-brige网桥,将所有节点组成网络。所有的集群中的节点在集群中将组成可配置的私有自治网络,与拥有不同ASN码的对端BGP端点进行连接。Kube-router将会广播podCIDR,并且保存从同一个主机命名空间学习到的路由。pod通过kube-bridge网桥与宿主机物理网卡连通。

子网IP的管理是由CNI的brige插件配合IPAM的host-local插件完成。hostlocal为kubelet上默认的cni插件

cni配置

在部署kuberouter之前,还需要部署CNI插件,这里我们采用kubelet自带的cni选项:

--network-plugin=cni 以启用cni插件
--cni-bin-dir=/opt/cni/bin 指定cni插件可执行文件路径
--cni-conf-dir=/etc/cni/net.d 指定cni插件配置文件路径

为支持网段的分配,还需要在controller-manager中加入如下配置:

--cluster-cidr=10.244.0.0/16 # 根据需要配置网段
--allocate-node-cidrs=true

踩坑经过

2020.06.10 这一天,kube-router发布了pre-release版本,如图:
upload successful
由图可知,该版本需要清空iptables或者安装前重启机器

本人在这天修改了一个--enable-ibgp=false参数,修改为true并重启了daemonset的kube-router,结果集群网络炸了,部分pod无法ping通其他宿主机上的pod。第一时间肯定是回滚操作,enable-ibgp改回为false,依然无法恢复网络。

排查到发现,才知道我们kube-router的镜像版本赫然写着:cloudnativelabs/kube-router

没有标签!!! 意味着容器每次重启会去拉取最新的镜像版本。于是拉取了这一天刚刚发布的镜像版本。这个版本需要清空iptables或者安装前重启机器。而我显然没这么做,于是网络就炸了。

这个坑虽然不是我自己埋的。但也说明我们对镜像版本的设置太过随意,给自己埋下祸根。以后需要汲取教训,避免这种低级错误。