运维开发网

k8s网络之Calico

运维开发网 https://www.qedev.com 2021-01-20 09:45 出处:51CTO 作者:leejia1989
Calico简介Calico组件是Tigera公司以Apache2.0开源协议开源的网络和网络解决方案组件,可用于容器、虚拟机、原生宿主机侧负载。CalicoCNI插件在CNI(ContainerNetworkInterface)框架内封装了Calico的功能,以对k8s环境做支持。虽然Flannel被公认为是最简单的选择,但Calico以其性能、灵活性而闻名。Calico的功能更为全面,不仅提供

Calico简介

Calico组件是Tigera公司以Apache 2.0开源协议开源的网络和网络解决方案组件,可用于容器、虚拟机、原生宿主机侧负载。Calico CNI插件在 CNI(Container Network Interface) 框架内封装了Calico的功能,以对k8s环境做支持。

虽然Flannel被公认为是最简单的选择,但Calico以其性能、灵活性而闻名。Calico的功能更为全面,不仅提供主机和pod之间的网络连接,还涉及网络安全和管理。从Calico 3.x开始,默认配置使用的是IPIP模式这种Overlay的传输方案而非BGP。

Calico架构

k8s网络之Calico

Calico组件主要架构由Felix、Confd、BIRD组成:

  1. Felix是负责Calico Node运行并作为每个节点Endpoint端点的守护程序,它负责管理当前主机中的Pod信息,与集群etcd服务交换集群Pod信息,并组合路由信息和ACL策略。
  2. Confd是负责存储集群etcd生成的Calico配置信息,提供给BIRD层运行时使用。
  3. BIRD(BIRD Internet Routing Daemon)是核心组件,Calico中的BIRD特指BIRD Client和BIRD Route Reflector,负责主动读取Felix在本机上设置的路由信息,并通过BGP广播协议在数据中心中进行分发路由。

此外,etcd组件是Calico组件运行的依赖组件,需事先在集群中部署etcd服务,或复用Kubernetes的etcd;Calico官方也提供了calicoctl管理工具,用于与Calico Node进行状态确认、状态配置等操作。

Calico之IPIP模式

IPIP模式基于Linux kernel的ipip隧道技术实现,即IP报文外面又封装了一层IP报文。内层的IP报文为原报文,外层报文的源IP和目的IP,即是隧道两端的IP。也就是说,应用想要通过隧道在源IP报文外再封装一层IP报文,从而使得原报文能够通过隧道路由到对端。对端的IPIP隧道模块,把原来的外层IP拆解掉,从而还原出原来的IP报文。

IPIP主要做的就是封包,解包的过程。通过IPIP封解包,原始IP报文能够在外层IP的托运下,通过路由穿过隧道,抵达隧道的对端,并且还原出原来的IP报文。这就是IPIP隧道的核心思想。

在使用ipip模式之后,每个node上会自动添加一个tunl0网卡,用于IPIP协议的支持。

IPIP协议格式

k8s网络之Calico

pod跨node通信

k8s网络之Calico

pod和node网络状况

我们使用两个处于不同node的pod:

# kubectl get pods -o wide
pod1                        1/1     Running            17         12d    10.101.26.40     work4   <none>           <none>
pod2                        1/1     Running            17         12d    10.99.1.167      work1   <none>           <none>

登陆work1和work4查看pod的ip和node物理网络的关系,我们可以发现pod内部的网卡在node上会有映射一个虚拟网卡,这一对网卡是一个虚拟机网卡对。一对虚拟网卡就像一跟数据线一遍发送数据另一边就能接收到且数据流向相同:

[[email protected] ~]# route -n|grep 10.99.1.167
10.99.1.167     0.0.0.0         255.255.255.255 UH    0      0        0 cali2703ae2f129
[[email protected] ~]# ifconfig cali2703ae2f129
cali2703ae2f129: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1440
        inet6 fe80::ecee:eeff:feee:eeee  prefixlen 64  scopeid 0x20<link>
        ether ee:ee:ee:ee:ee:ee  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

[[email protected] ~]# route -n|grep 10.101.26.40
10.101.26.40    0.0.0.0         255.255.255.255 UH    0      0        0 cali8a0d30f1f5a
[[email protected] ~]# ifconfig cali8a0d30f1f5a
cali8a0d30f1f5a: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1440
        inet6 fe80::ecee:eeff:feee:eeee  prefixlen 64  scopeid 0x20<link>
        ether ee:ee:ee:ee:ee:ee  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

通信

  1. 在pod1上ping pod2的ip 10.99.1.167
  2. 数据包通过pod1的eth0网卡传输到node work4上虚拟网卡cali8a0d30f1f5a,然后通过查询node work4上的路由,发现目的ip 10.99.1.167匹配到如下路由,故把数据包传输到tunl0网卡,此时IP数据报中Inner IP Header的IP:10.101.26.40 --> 10.99.1.167:
    # route -n|grep tunl0
    Kernel IP routing table
    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
    10.99.1.128     172.18.2.186    255.255.255.192 UG    0      0        0 tunl0
  3. ipip隧道是双向的,创建的时候会指定发送端local和接收端remote ip。tunl0收到数据包之后会按照ipip协议规范对进来的IP数据包封装一层外层IP头,外层IP的目的ip地址根据2步骤中的路由设置目的ip为网关172.18.2.186,外层IP的源ip地址根据创建remote ip为172.18.2.186这个隧道时的local ip地址设置为172.18.2.184。此时IP数据报变为: Outer IP Header的IP:172.18.2.184 --> 172.18.2.186; Inner IP Header的IP:10.101.26.40 --> 10.99.1.167。tunl0把接收到的数据包封装成ipip报文直接发给tcp/ip协议栈。
  4. tcp/ip协议栈根据ipip报文的目的地址和系统路由表,知道目的地址为172.18.2.186的数据报需要通过node work4的eth0发送。
    # route -n|grep eth0
    0.0.0.0         172.18.2.1      0.0.0.0         UG    100    0        0 eth0
    172.18.2.0      0.0.0.0         255.255.255.0   U     100    0        0 eth0
  5. 此ipip数据报经过网关172.18.2.1并最终发送到了node work1的eth0网卡。node work1的tcp/ip协议栈发现是ipip协议,对外层IP数据报解封装并转发给tunl0。tunl0根据内层IP数据包的目的ip地址和本地的路由协议,把数据包再转发到对应的cali2703ae2f129网卡,完成单向通信。
    # route -n|grep cali2703ae2f129
    10.99.1.167     0.0.0.0         255.255.255.255 UH    0      0        0 cali2703ae2f129
  6. pod2回复pod1的响应同理

pod node内通信

如果是同一个node内的pod通信,由于本地已经有对应pod的路由信息了,故直接在本地node路由转发数据报就可以完成互相通信,不需要使用ipip封装。

总结

1,calico IP in IP模式,跨node通信需要封装和解封装,node内通信不需要

2,calico IP in IP模式也是一种overlay的方案

3,通过封装IP数据报实现,属于L3层网络通信方案

4,对IP隧道封包/解封包技术有一定了解,但是不够深入,有问题欢迎指正

扫码领视频副本.gif

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号