calico网络模型中的路由原理

calico的部署

一、下载模板
wget https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/kubeadm/1.7/calico.yamlnode

能够获得一份calico官方提供的v3.1版本calico的部署模板(基于kubeadm)。固然里面都是社区的镜像,咱们能够替换成本地镜像.建议到网易云的景象中心下载,不少其余的国内镜像仓库都不作维护了。后端

二、启/禁用 ip-ip网络

目前官方提供的模板里,默认打开了ip-ip功能,该功能会在node上建立一个设备:tunl0,容器的网络数据会通过该设备被封装一个ip头再转发。这里,calico.yaml中经过修改calico-node的环境变量:CALICO_IPV4POOL_IPIP来实现ipip功能的开关:默认是Always,表示开启;Off表示关闭ipip; cross-subnet表示开启并支持跨子网,目前用不到这种类型。
sed -i "s#Always#Off#g" calico.yaml并发

三、部署:app

注意:部署前,要配置一个参数,让calico-node组件可以识别node的IP,node上可能有多块网卡,官方提供的yaml文件中,ip识别策略(IPDETECTMETHOD)没有配置,即默认为first-found,这会致使一个网络异常的ip做为nodeIP被注册,从而影响node-to-node mesh。咱们能够修改为can-reach的策略,尝试链接某一个Ready的node的IP,以此选择出正确的IP。tcp

为了方便,下面的脚本里,我以任意一个node的ip地址为reach 地址ide

connective_ip=`kubectl get node -o wide |grep Ready |head -n1 |awk '{print $6}'`
sed -i  -rn 'p;/name: IP/,/autodetect/H;/autodetect/{g;s/^\n//;p}' calico.yaml 
sed -i '1,/name: IP/{s/name: IP/name: IP_AUTODETECTION_METHOD/}' calico.yaml
sed -i '1,/\"autodetect\"/{s/\"autodetect\"/can-reach=__ONE_CONNECTIVE_ENDPOINT__/}' calico.yaml
sed -i "s#__ONE_CONNECTIVE_ENDPOINT__#$connective_ip#g" calico.yaml

执行:
kubectl apply -f calico.yamlspa

四、calico使用过程当中的一些其余点3d

  1. calico以ipip模式部署完毕后,node上会有一个tunl0的网卡设备,这是ipip作隧道封装用的。当咱们把节点下线,calico容器都中止后,这个设备依然还在,执行 rmmod ipip 命令能够将它删除(若是calico-node仍在运行,会自动再建一个新的)
  2. calico部署完毕后,其数据记录在calico-etcd容器运行节点的/var/etcd/calico-data目录中,若是要彻底清理集群中的etcd数据,须要将该目录删除。
  3. calico支持以kubernetes为存储后端,以这种方式部署时,calico再也不须要额外部署etcd,而是将数据以CRD的方式存到k8s中。calico的组件依赖kubeconfig与k8s交互。在这种模式下,部署calico须要执行:
wget https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/kubernetes-datastore/calico-networking/1.7/calico.yaml
wget https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/rbac-kdd.yaml
kubectl apply -f rbac-kdd.yaml
kubectl apply -f calico.yaml
此处下载的calico.yaml 仍能够参照上文的部署方式进行ipip、ip pool等的定制化。

calico bgp 网络

经过bgp方式部署好calico后,咱们在集群中建立几个pod:code

root@k8s-calico1:~# pods 
NAMESPACE     NAME                                       READY     STATUS    RESTARTS   AGE       IP                NODE
huang1        huangtest-69d9fddd97-cbzbm                 1/1       Running   0          20m       192.168.211.1     k8s-calico4
huang1        huangtest-69d9fddd97-pbvvw                 1/1       Running   0          3m        192.168.210.194   k8s-calico3
huang2        hhh-6897d64fcd-4zph4                       1/1       Running   0          1d        192.168.97.2      k8s-calico2

咱们在k8s-calico2这个node上来看。执行ip r, 在这个node的路由中,须要咱们关注的有:

192.168.97.2 dev calic285cddbb40 scope link 
blackhole 192.168.97.0/26 proto bird 
192.168.210.192/26 via 10.173.32.26 dev eth0 proto bird 
192.168.211.0/26 via 10.173.32.25 dev eth0 proto bird

192.168.97.2 dev calic285cddbb40 scope link 这条路由将通向容器ip的请求导向veth:calic285cddbb40 ,进而让请求直达容器内的网卡。
blackhole 192.168.97.0/26 proto bird 表示发往192.168.97.0/26网段的报文都会被丢弃且不会回复源端。配置这条路由的缘由是:这台机器上的calico网络可分配的cidr是192.168.97.0/26,容器里访问同网段的其余IP时,配置该路由以免报文被发到外部。
最后两条,分别记录了:要访问calico网络中的某个网段,须要以对应的node IP为网关,经过eth0发包。也就是说经过这两条路由,能够将部分网段(目的IP)的包经由eth0发送到正确的地方。

咱们能够这么理解:pod hhh-6897d64fcd-4zph4中ping huangtest-69d9fddd97-pbvvw时,流量是这么走的:

0、数据包封装完成,srcip:192.168.97.2 , destip:192.168.210.194
一、容器中只有eth0网卡,容器里ip r 看到的是default **** dev eth0,因此流量经过容器的eth0发送。
二、容器网卡的配置是经过vethpair作的,也就是说,容器里网卡发的包,在宿主机上都会被calic285cddbb40设备发出。
三、经过第2步,网络报文就在宿主机的网络中,受宿主机路由影响,192.168.210.192/26 via 10.173.32.26 dev eth0 proto bird这条路由会将数据从eth0转发,并发给路由中记录的网关:10.173.32.26(这个ip,就是pod huangtest-69d9fddd97-pbvvw所在的node:k8s-calico3 的ip)
四、10.173.32.26是node:k8s-calico3上eth0的ip,收到包后,在机器自身的路由表中寻找合理的路由,固然这个地方也会有路由:192.168.210.194 dev calif6874dae1d2 scope link,因而包顺利被对端接收

calico ipip 网络

咱们经过ip-ip模式部署calico,而后将原有的pod所有删掉重建,以下:

root@k8s-calico1:~# pods 
NAMESPACE     NAME                                       READY     STATUS             RESTARTS   AGE       IP                NODE
huang1        huangtest-69d9fddd97-2b8hr                 1/1       Running            0          1m        192.168.97.1      k8s-calico2
huang1        huangtest-69d9fddd97-npwzw                 1/1       Running            0          1m        192.168.210.65    k8s-calico4
huang2        hhh-6897d64fcd-kqsj4                       1/1       Running            0          10s       192.168.210.129   k8s-calico3

咱们再去看看k8s-calico2这个node 上的路由,一样的须要咱们关注的路由有下面的几条:

root@k8s-calico2:~# ip r  |grep bird
192.168.97.1 dev cali3683f65394b scope link
blackhole 192.168.97.0/26 proto bird 
192.168.110.64/26 via 10.173.32.24 dev tunl0 proto bird onlink 
192.168.210.64/26 via 10.173.32.25 dev tunl0 proto bird onlink 
192.168.210.128/26 via 10.173.32.26 dev tunl0 proto bird onlink

前两条再也不赘述,咱们看到最后三条路由,其实他们描述的逻辑与BGP的那两条没有差异,只不过网卡换成了tunl0.

咱们以一个例子来解释清楚:pod huangtest-69d9fddd97-2b8hr ping hhh-6897d64fcd-kqsj4

0、封装报文,SRCIP:192.168.97.1 DESTIP:192.168.210.129
一、容器中只有eth0网卡,容器里ip r 看到的是default **** dev eth0,因此流量经过容器的eth0发送。
二、容器网卡的配置是经过vethpair作的,也就是说,容器里网卡发的包,在宿主机上都会被calic285cddbb40设备发出。
三、经过第2步,网络报文就在宿主机的网络中,受宿主机路由影响,192.168.210.128/26 via 10.173.32.26 dev tunl0 proto bird onlink 识别到匹配的对端IP,将报文从tunl0发出到10.173.32.26。这里,tunl0会对报文进行封装,在原有的ip报文之上封装了一个ip头部,新的头部中,srcip是宿主机自身的ip:10.173.32.23, destip是对端的ip地址:10.173.32.26。
咱们能够经过tcpdump抓包看到这个步骤:
封装前:

clipboard.png

封装后(注意到输出内容结尾有ipip-proto-4):

clipboard.png
四、因为宿主机上只有一个eth的物理机网卡,因此流量终究仍是从eth0向外发出到10.173.32.26。10.173.32.26这个节点的eth0网卡,收到了报文后,发现带有ipip协议的标记(第3步中tcpdump抓包看到的ipip-proto-4),将ipip头部解开,因而处理到了真实的报文。
五、宿主机上192.168.210.129 dev cali5ce61eb6bc2 scope link 这个路由将包发给vethpair,从而被容器内的eth0接收。
六、icmp响应包的走向与上述的走向逻辑上相同。

待定:补充ipip和bgp的使用场景。以及calico的BGP路由配置方法(AS,node-mesh)

相关文章
相关标签/搜索