一文明白calico的IPIP网络模式

简介: 一文明白calico的IPIP网络模式

前言


本文主要分析k8s中网络组件calico的 IPIP网络模式。旨在理解IPIP网络模式下产生的calixxxx,tunl0等设备以及跨节点网络通信方式。可能看着有点枯燥,但是请花几分钟时间坚持看完,如果看到后面忘了前面,请反复看两遍,这几分钟时间一定你会花的很值。


一、calico介绍


Calico是Kubernetes生态系统中另一种流行的网络选择。虽然Flannel被公认为是最简单的选择,但Calico以其性能、灵活性而闻名。Calico的功能更为全面,不仅提供主机和pod之间的网络连接,还涉及网络安全和管理。Calico CNI插件在CNI框架内封装了Calico的功能。


Calico是一个基于BGP的纯三层的网络方案,与OpenStack、Kubernetes、AWS、GCE等云平台都能够良好地集成。Calico在每个计算节点都利用Linux Kernel实现了一个高效的虚拟路由器vRouter来负责数据转发。每个vRouter都通过BGP1协议把在本节点上运行的容器的路由信息向整个Calico网络广播,并自动设置到达其他节点的路由转发规则。


Calico保证所有容器之间的数据流量都是通过IP路由的方式完成互联互通的。Calico节点组网时可以直接利用数据中心的网络结构(L2或者L3),不需要额外的NAT、隧道或者Overlay Network,没有额外的封包解包,能够节约CPU运算,提高网络效率。


此外,Calico基于iptables还提供了丰富的网络策略,实现了Kubernetes的Network Policy策略,提供容器间网络可达性限制的功能。


calico官网https://www.projectcalico.org/


二、calico架构及核心组件


架构图如下:


7149d80d0fa6c61ef5bff88244f127cf.png


calico核心组件:


  • Felix:运行在每个需要运行workload的节点上的agent进程。主要负责配置路由及 ACLs(访问控制列表) 等信息来确保 endpoint 的连通状态,保证跨主机容器的网络互通;
  • etcd:强一致性、高可用的键值存储,持久存储calico数据的存储管理系统。主要负责网络元数据一致性,确保Calico网络状态的准确性;
  • BGP Client(BIRD):读取Felix设置的内核路由状态,在数据中心分发状态。
  • BGP Route Reflector(BIRD):BGP路由反射器,在较大规模部署时使用。如果仅使用BGP Client形成mesh全网互联就会导致规模限制,因为所有BGP client节点之间两两互联,需要建立N^2个连接,拓扑也会变得复杂。因此使用reflector来负责client之间的连接,防止节点两两相连。


三、calico工作原理


Calico把每个操作系统的协议栈认为是一个路由器,然后把所有的容器认为是连在这个路由器上的网络终端,在路由器之间跑标准的路由协议——BGP的协议,然后让它们自己去学习这个网络拓扑该如何转发。所以Calico方案其实是一个纯三层的方案,也就是说让每台机器的协议栈的三层去确保两个容器,跨主机容器之间的三层连通性。


四、calico的两种网络方式


1)IPIP


把 IP 层封装到 IP 层的一个 tunnel。它的作用其实基本上就相当于一个基于IP层的网桥!一般来说,普通的网桥是基于mac层的,根本不需 IP,而这个 ipip 则是通过两端的路由做一个 tunnel,把两个本来不通的网络通过点对点连接起来。ipip 的源代码在内核 net/ipv4/ipip.c 中可以找到。


2)BGP


边界网关协议(Border Gateway Protocol, BGP)是互联网上一个核心的去中心化自治路由协议。它通过维护IP路由表或‘前缀’表来实现自治系统(AS)之间的可达性,属于矢量路由协议。BGP不使用传统的内部网关协议(IGP)的指标,而使用基于路径、网络策略或规则集来决定路由。因此,它更适合被称为矢量性协议,而不是路由协议。


五、IPIP网络模式分析


由于个人环境中使用的是IPIP模式,因此接下来这里分析一下这种模式。


# kubectl get po -o wide -n paas | grep hello
demo-hello-perf-d84bffcb8-7fxqj   1/1     Running   0          9d      10.20.105.215   node2.perf  <none>           <none>
demo-hello-sit-6d5c9f44bc-ncpql   1/1     Running   0          9d      10.20.42.31     node1.sit   <none>           <none>


进行ping测试


这里在demo-hello-perf这个pod中ping demo-hello-sit这个pod。


root@demo-hello-perf-d84bffcb8-7fxqj:/# ping 10.20.42.31
PING 10.20.42.31 (10.20.42.31) 56(84) bytes of data.
64 bytes from 10.20.42.31: icmp_seq=1 ttl=62 time=5.60 ms
64 bytes from 10.20.42.31: icmp_seq=2 ttl=62 time=1.66 ms
64 bytes from 10.20.42.31: icmp_seq=3 ttl=62 time=1.79 ms
^C
--- 10.20.42.31 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 6ms
rtt min/avg/max/mdev = 1.662/3.015/5.595/1.825 ms


进入pod demo-hello-perf中查看这个pod中的路由信息


root@demo-hello-perf-d84bffcb8-7fxqj:/# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         169.254.1.1     0.0.0.0         UG    0      0        0 eth0
169.254.1.1     0.0.0.0         255.255.255.255 UH    0      0        0 eth0


根据路由信息,ping 10.20.42.31,会匹配到第一条。


第一条路由的意思是:去往任何网段的数据包都发往网关169.254.1.1,然后从eth0网卡发送出去。


demo-hello-perf所在的node node2.perf 宿主机上路由信息如下:


# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.16.36.1     0.0.0.0         UG    100    0        0 eth0
10.20.42.0      172.16.35.4     255.255.255.192 UG    0      0        0 tunl0
10.20.105.196   0.0.0.0         255.255.255.255 UH    0      0        0 cali4bb1efe70a2
169.254.169.254 172.16.36.2     255.255.255.255 UGH   100    0        0 eth0
172.16.36.0     0.0.0.0         255.255.255.0   U     100    0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0


可以看到一条Destination为 10.20.42.0的路由。


意思是:当ping包来到master节点上,会匹配到路由tunl0。该路由的意思是:去往10.20.42.0/26的网段的数据包都发往网关172.16.35.4。因为demo-hello-perf的pod在172.16.36.5上,demo-hello-sit的pod在172.16.35.4上。所以数据包就通过设备tunl0发往到node节点上。


demo-hello-sit所在的node node1.sit 宿主机上路由信息如下:

# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.16.35.1     0.0.0.0         UG    100    0        0 eth0
10.20.15.64     172.16.36.4     255.255.255.192 UG    0      0        0 tunl0
10.20.42.31     0.0.0.0         255.255.255.255 UH    0      0        0 cali04736ec14ce
10.20.105.192   172.16.36.5     255.255.255.192 UG    0      0        0 tunl0


当node节点网卡收到数据包之后,发现发往的目的ip为10.20.42.31,于是匹配到Destination为10.20.42.31的路由。


该路由的意思是:10.20.42.31是本机直连设备,去往设备的数据包发往cali04736ec14ce


为什么这么奇怪会有一个名为cali04736ec14ce的设备呢?这是个啥玩意儿呢?


其实这个设备就是veth pair的一端。在创建demo-hello-sit 时calico会给demo-hello-sit 创建一个veth pair设备。一端是demo-hello-sit 的网卡,另一端就是我们看到的cali04736ec14ce


接着验证一下。我们进入demo-hello-sit 的pod,查看到 4 号设备后面的编号是:122964


root@demo-hello-sit--6d5c9f44bc-ncpql:/# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
4: eth0@if122964: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1380 qdisc noqueue state UP group default 
    link/ether 9a:7d:b2:26:9b:17 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.20.42.31/32 brd 10.20.42.31 scope global eth0
       valid_lft forever preferred_lft forever


然后我们登录到demo-hello-sit这个pod所在的宿主机查看


# ip a | grep -A 5 "cali04736ec14ce"
122964: cali04736ec14ce@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1380 qdisc noqueue state UP group default 
    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 16
    inet6 fe80::ecee:eeff:feee:eeee/64 scope link 
       valid_lft forever preferred_lft forever
120918: calidd1cafcd275@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1380 qdisc noqueue state UP group default 
    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 2


发现pod demo-hello-sit中 的另一端设备编号和这里在node上看到的cali04736ec14ce编号122964是一样的


所以,node上的路由,发送cali04736ec14ce网卡设备的数据其实就是发送到了demo-hello-sit的这个pod中去了。到这里ping包就到了目的地。


注意看 demo-hello-sit这个pod所在的宿主机的路由,有一条 Destination为10.20.105.192的路由


# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
...
0.0.0.0         172.16.35.1     0.0.0.0         UG    100    0        0 eth0
10.20.105.192   172.16.36.5     255.255.255.192 UG    0      0        0 tunl0
...


再查看一下demo-hello-sit的pod中路由信息,和demo-hello-perf的pod中是一样的。

所以综合上述例子来看,IPIP的网络模式就是将IP网络封装了一层。特点就是所有pod的数据流量都从隧道tunl0发送,并且tunl0这里增加了一层传输层的封包操作。


六、抓包分析


在demo-hello-perf这个pod中ping demo-hello-sit这个pod,接着在demo-hello-sit这个pod所在的宿主机进行tcpdump


# tcpdump  -i eth0 -nn -w icmp_ping.cap
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes


在demo-hello-perf这个pod中进行ping demo-hello-sit的操作


root@demo-hello-perf-d84bffcb8-7fxqj:/# ping 10.20.42.31
PING 10.20.42.31 (10.20.42.31) 56(84) bytes of data.
64 bytes from 10.20.42.31: icmp_seq=1 ttl=62 time=5.66 ms
64 bytes from 10.20.42.31: icmp_seq=2 ttl=62 time=1.68 ms
64 bytes from 10.20.42.31: icmp_seq=3 ttl=62 time=1.61 ms
^C
--- 10.20.42.31 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 6ms
rtt min/avg/max/mdev = 1.608/2.983/5.659/1.892 ms


结束抓包后下载icmp_ping.cap到本地windows进行抓包分析


能看到该数据包一共5层,其中IP(Internet Protocol)所在的网络层有两个,分别是pod之间的网络和主机之间的网络封装。


8caac0c6908337cbffacbe12cd146739.png


红色框选的是两个pod所在的宿主机,蓝色框选的是两个pod的ip,src表示发起ping操作的pod所在的宿主机ip以及发起ping操作的pod的ip,dst表示被ping的pod所在的宿主机ip及被ping的pod的ip


根据数据包的封装顺序,应该是在demo-hello-perf ping demo-hello-sit的ICMP包外面多封装了一层主机之间的数据包。


eea4ed8e476fa68b1e710770d4c1255a.png


可以看到每个数据报文共有两个IP网络层,内层是Pod容器之间的IP网络报文,外层是宿主机节点的网络报文(2个node节点)。之所以要这样做是因为tunl0是一个隧道端点设备,在数据到达时要加上一层封装,便于发送到对端隧道设备中。


两层封包的具体内容如下:


29ea77d4504990aadded127488cbbdcd.png


Pod间的通信经由IPIP的三层隧道转发,相比较VxLAN的二层隧道来说,IPIP隧道的开销较小,但其安全性也更差一些。


七、pod到svc的访问


查看service


# kubectl get svc -o wide -n paas | grep hello
demo-hello-perf              ClusterIP   10.10.255.18    <none>        8080/TCP              10d    appEnv=perf,appName=demo-hello
demo-hello-sit               ClusterIP   10.10.48.254    <none>        8080/TCP              10d    appEnv=sit,appName=demo-hello


在pod demo-hello-sit 的宿主机上抓包


# tcpdump -i eth0 -nn -w svc.cap
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes


测试访问,在demo-hello-sit中curl demo-hello-perf的svc的地址和端口


root@demo-hello-perf-d84bffcb8-7fxqj:/# curl -I http://10.10.48.254:8080/actuator/health
HTTP/1.1 200
Content-Type: application/vnd.spring-boot.actuator.v3+json
Transfer-Encoding: chunked
Date: Fri, 30 Apr 2021 01:42:56 GMT
root@demo-hello-perf-d84bffcb8-7fxqj:/# curl -I http://10.10.48.254:8080/actuator/health
HTTP/1.1 200
Content-Type: application/vnd.spring-boot.actuator.v3+json
Transfer-Encoding: chunked
Date: Fri, 30 Apr 2021 01:42:58 GMT
root@demo-hello-perf-d84bffcb8-7fxqj:/# curl -I http://10.10.48.254:8080/actuator/health
HTTP/1.1 200
Content-Type: application/vnd.spring-boot.actuator.v3+json
Transfer-Encoding: chunked
Date: Fri, 30 Apr 2021 01:42:58 GMT


结束抓包,下载svc.cap文件放到wireshark中打开查看


1c97410f4f977d8dd349dfd3d4951896.png


可以看到wireshark中Src和Dst的结果。任然是和上面pod中访问pod的ip地址一样。这里Src和Dst任然是两个pod的宿主机的内网ip和两个pod自己的ip地址。是用ipip的方式进行通信的。


通过以上例子演示,应该就看明白了IPIP网络模式的通信方式了吧!

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
24天前
|
NoSQL 关系型数据库 MySQL
《docker高级篇(大厂进阶):4.Docker网络》包括:是什么、常用基本命令、能干嘛、网络模式、docker平台架构图解
《docker高级篇(大厂进阶):4.Docker网络》包括:是什么、常用基本命令、能干嘛、网络模式、docker平台架构图解
150 56
《docker高级篇(大厂进阶):4.Docker网络》包括:是什么、常用基本命令、能干嘛、网络模式、docker平台架构图解
|
1月前
|
安全 Docker 容器
docker的默认网络模式有哪些
Docker 默认网络模式包括:1) bridge:默认模式,各容器分配独立IP,可通过名称或IP通信;2) host:容器与宿主机共享网络命名空间,性能最优但有安全风险;3) none:容器隔离无网络配置,适用于仅需本地通信的场景。
42 6
|
2月前
|
域名解析 网络协议 虚拟化
vmware 提供的三种网络工作模式
本文介绍了VMware虚拟机的三种网络工作模式:Bridged(桥接模式)、NAT(网络地址转换模式)和Host-Only(仅主机模式)。桥接模式将虚拟机与主机通过虚拟网桥连接,实现与物理网络的直接通信;NAT模式通过虚拟NAT设备和DHCP服务器使虚拟机联网;Host-Only模式则将虚拟机与外网隔离,仅与主机通信。此外,文章还简要介绍了网络相关的基础知识,包括主机名、IP地址、子网掩码、默认网关和DNS服务器。
108 3
|
3月前
|
安全 定位技术 数据安全/隐私保护
|
3月前
|
负载均衡 应用服务中间件 数据安全/隐私保护
docker swarm 创建 Swarm 模式下的网络
【10月更文挑战第14天】
83 6
|
3月前
|
存储 前端开发 JavaScript
链动模式融合排队免单:扩散用户裂变网络、提高复购
将链动2+1与排队免单结合的模式及链动3+1模式转化为可运行代码涉及多个技术领域,包括后端开发、前端开发、数据库设计等。本文提供了一个简化的技术框架,涵盖用户管理、订单处理、奖励计算、团队结构等核心功能,并提供了示例代码。同时,强调了安全性、测试与部署的重要性,以确保系统的稳定性和合规性。
|
2月前
|
Docker 容器
【赵渝强老师】Docker的None网络模式
Docker容器在网络方面实现了逻辑隔离,提供了四种网络模式:bridge、container、host和none。其中,none模式下容器具有独立的网络命名空间,但不包含任何网络配置,仅能通过Local Loopback网卡(localhost或127.0.0.1)进行通信。适用于不希望容器接收任何网络流量或运行无需网络连接的特殊服务。
|
2月前
|
Docker 容器
【赵渝强老师】Docker的Host网络模式
Docker容器在网络环境中是隔离的,可通过配置不同网络模式(如bridge、container、host和none)实现容器间或与宿主机的网络通信。其中,host模式使容器与宿主机共享同一网络命名空间,提高性能但牺牲了网络隔离性。
|
2月前
|
Kubernetes Docker 容器
【赵渝强老师】Docker的Container网络模式
Docker容器在网络环境中彼此隔离,但可通过配置不同网络模式实现容器间通信。其中,container模式使容器共享同一网络命名空间,通过localhost或127.0.0.1互相访问,提高传输效率。本文介绍了container模式的特点及具体示例。
|
2月前
|
Linux Docker 容器
【赵渝强老师】Docker的Bridge网络模式
本文介绍了Docker容器的网络隔离机制及其四种网络模式:bridge、container、host和none。重点讲解了默认的bridge模式,通过示例演示了如何创建自定义bridge网络并配置容器的网络信息。文中还附有相关图片和视频讲解,帮助读者更好地理解Docker网络的配置和使用方法。