K8s网络实战分析之Calico-ipip模式

Kubernetes为每个Pod都分配了唯一的IP地址,一个Pod里的多个容器共享PodIp地址。Kubernetes要求底层网络支持集群内任意两个Pod间的TCP/IP直接通信。Kubernetes的跨主机任意Pod访问方式主要是遵循CNI容器网络规范,目前已经有多个开源组件支持CNI,包括Flannel、Open VSwitch、Calico等。本文主要介绍在Calico的ipip模式下,K8s的Pod间访问原理。

Calico容器网络简介

Calico是一个基于BGP的纯三层网络方案,其会为每个容器(pod)分配一个可路由的IP,在通信时不需要解包和拆包,因此网络性能损耗小,易于排查和水平扩展。

image.png

Calico标志

标题Calico架构

image.png
Calico网络模型主要工作组件:

  1. Felix:Calico Agent,运行在每一台 Host 的 agent 进程,主要负责网络接口管理和监听、路由、ARP 管理、ACL 管理和同步、状态上报等,保证跨主机容器的网络互通。

  2. etcd:Calico的后端存储,主要负责网络元数据一致性,确保Calico网络状态的准确性,可以与kubernetes共用;

  3. BGP Client(BIRD):Calico 为每一台 Host 部署一个 BGP Client,使用 BIRD 实现,BIRD 是一个单独的持续发展的项目,实现了众多动态路由协议比如 BGP、OSPF、RIP 等。负责将Felix 在各Node上的设置通过BGP协议广播到Calico网络,从而实现网络互通。

  4. BGP Route Reflector:在大型网络规模中,如果仅仅使用 BGP client 形成 mesh 全网互联的方案就会导致规模限制,因为所有节点之间俩俩互联,需要 N^2 个连接,为了解决这个规模问题,可以采用 BGP 的 Router Reflector 的方法,使所有 BGP Client 仅与特定 RR 节点互联并做路由同步,从而大大减少连接数。

IPIP模式简介

Calico中的IP Pool可以使用两种模式:BGP或者IPIP。本文使用的是IPIP模式,是一种将各Node的路由之间做一个tunnel,再把网络连接起来的模式:
image.png
从字面上说,就是将一个IP数据包套在另一个IP包里,使用到了Linux提供的隧道技术。可以理解为一个基于IP层的网桥,将两个本不通的网络通过点对点连接起来。

K8s-Calico-IPIP网络实战分析

下面我们就进行基于Calico-IPIP模式下的K8s容器互联网络分析。
##实验准备
准备了1master 2slaver的K8s集群,设置为Calico-IPIP网络。每个slaver内(node1,node2)分别部署了一个Pod容器,结构示意图如下:
image.png

网络结构解析

pod网络

首先通过指令 kubectl exec -it pod1 /bin/bash</font color=grey> 进入pod1容器中,再使用指令 ip addr</font color=grey> 查看pod1内的网络设备。

ip addr
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
4: eth0@if26: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default 
    link/ether ce:83:2b:89:af:9e brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.100.15.150/32 scope global eth0
       valid_lft forever preferred_lft forever

可以看到,pod只有普通的loopback和eth0。

node网络

先查看node网络设备。

ip addr
...省略部分
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:16:3e:02:03:5c brd ff:ff:ff:ff:ff:ff
    inet 172.31.112.2/20 brd 172.31.127.255 scope global dynamic eth0
       valid_lft 311927346sec preferred_lft 311927346sec
4: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1440 qdisc noqueue state UNKNOWN group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
    inet 10.100.15.128/32 brd 10.100.15.128 scope global tunl0
       valid_lft forever preferred_lft forever
26: cali3ef8aad4b4e@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default 
    link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 1

node中除了eth0外,多了tunl0和cali3ef8aad4b4e(下面简称为cali.4e),结合之前的Calico简介,大家肯定可以猜到,tunl0就是Calico在IPIP模式下的隧道名称 ,而cali.4e是啥子类,注意到,该设备的编号为26。让我们回到pod1中,查看pod1内的ip link:

$ip link show eth0
4: eth0@if26: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP mode DEFAULT group default 
    link/ether ce:83:2b:89:af:9e brd ff:ff:ff:ff:ff:ff link-netnsid 0

eth0@if26,这里eth0连接的设备号也是26!其实这个设备就是veth pair,K8s在创建Pod的时候,会创建一个veth pair设备。设备的一端是pod2的网卡,另一端就是我们在node中看见的cali.4e了。是不是清楚了很多☺node2与之类似。
下面我们将node节点的route规则也贴上,后面会用到。

node1
route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.31.127.253  0.0.0.0         UG    0      0        0 eth0
10.100.6.128    172.31.112.1    255.255.255.192 UG    0      0        0 tunl0
10.100.9.192    172.31.127.252  255.255.255.192 UG    0      0        0 tunl0
10.100.15.128   0.0.0.0         255.255.255.192 U     0      0        0 *
10.100.15.129   0.0.0.0         255.255.255.255 UH    0      0        0 cali386c6dca3ac
10.100.15.150   0.0.0.0         255.255.255.255 UH    0      0        0 cali3ef8aad4b4e
169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.31.112.0    0.0.0.0         255.255.240.0   U     0      0        0 eth0
node2
route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.31.127.253  0.0.0.0         UG    0      0        0 eth0
10.100.6.128    172.31.112.1    255.255.255.192 UG    0      0        0 tunl0
10.100.9.192    0.0.0.0         255.255.255.192 U     0      0        0 *
10.100.9.193    0.0.0.0         255.255.255.255 UH    0      0        0 cali4360a48538f
10.100.9.206    0.0.0.0         255.255.255.255 UH    0      0        0 cali2d771657bc2
10.100.9.207    0.0.0.0         255.255.255.255 UH    0      0        0 cali7116f2b12fa
10.100.15.128   172.31.112.2    255.255.255.192 UG    0      0        0 tunl0
169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.31.112.0    0.0.0.0         255.255.240.0   U     0      0        0 eth0

网络结构小结

根据上节的信息,绘出当前实验网络的主要设备图。后面将进行网络连接实战。
image.png

网络连接实战

node间连接

很容易的,我们先猜测一个从pod2发往pod1的ip数据流向。
image.png
下面让我们一起来验证我们的猜测吧!使用的工具就是tcpdump啦~
分别在两个node的Cali.c2、tunl0、eth0出进行抓包分析,结果如下图所示,其中Cali.c2与tunl0的ip完全一致,因此合并输出。
image.png
按照标志的①、②、③、④来依次分析:
①:上节已经说了,pod2中的eth0(即图中的vthe0)与Cali.c2是一对veth pair,因此,Cali.c2接收到的ip流向一定与vthe0相同,为 10.100.9.206->10.100.15.150</font color=grey>。查看之前的node2 route表,发现有一条 :

 Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.100.15.128   172.31.112.2    255.255.255.192 UG    0      0        0 tunl0

所有发往10.100.15.128/255.255.255.192的ip报都需要通过tunl0,经过172.31.112.2作为gateway发送。因此,cali.c2的ip报会发往tunl0。
②:经过tunl0的ip报会被再封上一层ip。通过node2 的route规则,会发往eth0,因此我们在eth0处的抓包结果为 172.31.127.252 > 172.31.112.2: IP 10.100.9.206 > 10.100.15.150</font color=grey>

 Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
172.31.112.0    0.0.0.0         255.255.240.0   U     0      0        0 eth0

③、④:三和四其实就是①、②的逆过程,检查node1的route表即可知道流向。etho0将ipip拆封后,将流量发给tunl0,tunl0再转发给cali.4e。

 Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.100.15.150   0.0.0.0         255.255.255.255 UH    0      0        0 cali3ef8aad4b4e

node内连接

如果是同一个node内的两个pod进行访问,那么还会走tunl0进行ipip封装吗?
其实很容易回答这个问题,通过上节的route规则就可以知道,Calico会为每一个node分配一小段网络,同时会Wie每个pod创建一个“入”的ip route规则。如下图所示,当从pod2访问pod3时,Cali.c2是直接发出10.100.9.206-> 10.100.9.207</font color=grey>流量的,在node2的ip route中,发往10.100.9.207的ip报直接会被转发到cali.fa,不会用到tunl0,只有在node间访问的时候才会使用tunl0进行ipip封装!

 Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.100.9.207    0.0.0.0         255.255.255.255 UH    0      0        0 cali7116f2b12fa

image.png

总结

通过上节的实战与分析,相信大家一定对Calico-ipip网络有了比较清晰的印象,文章最后做个小结:

  1. IPIP模式下,node间的Pod访问会使用IPIP技术对出node的ip报进行隧道封装
  2. node内的Pod访问不会用到ipip隧道封装。
  3. Pod的ip都是由calico-node设置的IP地址池进行分配的,docker0对kubernetes设置的Pod的IP地址将不再起作用。
    下一篇我会基于本文的实战基础,对kubernetes service的网络调用进行实战分析。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值