【星海出品】Calico研究汇总

Calico项目由Tigera公司发起并主导开发

Calico官方文档:
源码

简介

Tigera是一家专注于云原生安全的公司,于2016年成立,其核心产品包括开源的Calico项目以及商业版的Calico Enterprise。
Calico项目的首次提交出现在2015年(根据GitHub提交历史)
项目早期专注于为容器和Kubernetes提供网络连接与安全策略,后续持续迭代成为云原生领域的核心网络方案。

作为Kubernetes的CNI(容器网络接口)插件,提供Pod间的网络通信和IP地址管理(IPAM)。

与K8S兼容的插件有很多 例如:

Calico、Flannel、Canal、Cilium、kube-router

Calico和Flannel的区别

Calico是纯三层网络(L3):基于 IP 路由实现通信,不依赖覆盖网络(Overlay Network)。
使用边界网关协议(BGP)在节点间交换路由信息,支持直接路由模式(无隧道)或 Overlay 模式(如 IPIP、VXLAN)。
性能接近物理网络,易与现有网络设备集成。不对数据包进行封装,不需要NAT和端口映射,扩展性和性能都很好。
网络安全策略:原生支持 Kubernetes NetworkPolicy,提供细粒度流量控制(如基于标签、端口、协议的规则)。
高级功能:支持 eBPF、服务网格集成、威胁检测等。

Flannel:
覆盖网络(Overlay Network):通过 VXLAN、UDP 等隧道技术构建虚拟网络。
子网分配:为每个节点分配一个子网,容器通过隧道跨节点通信。
模式:支持 host-gw(直接路由,无隧道)、vxlan、udp 等。
基础网络连通:仅提供容器间通信,无原生网络策略支持。
依赖外部工具:需结合 Calico 或其他插件实现安全策略。

calico基本组成

Felix:运行在每一台Host的Agent进程

主要负责网络接口管理和监听、路由、ARP管理、ACL管理和同步、状态上报等。它会监听 ectd 中心的数据存储,从它获取事件,比如说用户在这台机器上加了一个 IP,或者是创建了一个容器等。
用户创建 Pod 后,Felix负责将其网卡、IP、MAC 都设置好,然后在内核的路由表里面写一条,注明这个IP应该到这张网卡。

etcd:相关文献

分布式键值存储数据库,主要负责网络元数据一致性,确保Calico网络状态的准确性,可以与 Kubernetes 共用。

BIRD(Border Internet Routing Daemon)

Calico 中的 BGP 客户端,负责将 Felix 生成的路由信息载入内核,并通过 BGP 协议在集群中分发。
确保跨主机的容器网络通信,使每个节点上的 Pod 可以直接通信。
动态路由:通过 BGP 协议动态学习和传播路由信息,适应网络拓扑的变化。
每个主机都是一个[AS]

Calico CNI 插件

作用:Calico 的 CNI(Container Network Interface)插件,用于配置和管理 Pod 的网络接口。
功能细节:
网络配置:在 Pod 启动时创建网络接口并分配 IP 地址。
网络清理:在 Pod 终止时清理网络接口和 IP 地址。
策略实施:与 Kubernetes 网络策略集成,确保 Pod 之间的通信符合策略规则。

Typha(可选组件)

作用:Typha 是一个优化组件,用于大规模集群中,减轻 Felix 与 etcd 之间的通信压力。
功能细节:
事件聚合:聚合 etcd 中的事件,以更高效的方式分发给 Felix 进程。
性能提升:降低节点间通信的延迟和带宽消耗,提高网络稳定性。

calicoctl

作用:calicoctl 是 Calico 的命令行工具,用于管理和调试 Calico 网络配置。
功能细节:
配置管理:查询和更新网络策略、路由表等配置信息。
状态监控:查看网络连接状态,调试网络问题。

Calico Policy Controller(或 kube-controllers)

作用:监控 Kubernetes API Server 中的网络策略对象,并将其转换为 Calico 理解的格式。
功能细节:
策略同步:确保 Kubernetes 的网络策略在集群内得到正确实施。
自动化管理:自动配置网络策略,简化管理员的操作。

BGP 路由反射器

作用:用于大规模集群中,通过集中式的路由分发减少节点间的连接数。
功能细节:
路由优化:解决 BGP 全互联模式(Node-to-Node Mesh)在大规模集群中的扩展性问题。
冗余设计:通常部署多个 BGP 路由反射器,以提高网络的可靠性和可用性。

calico

calico把每个节点都作为一个虚拟路由器,并把每个节点上的Pod当作是节点路由器后的一个终端设备并为其分配一个IP地址。各节点路由器通过BGP协议生成路由规则,从而实现不通节点上Pod间的通信。

BGP是一个去中心化自治路由协议,它通过维护IP路由表或“前缀”来实现自治系统之间的可达性,通常作为大规模数据中心维护不同自治系统之间路由信息的矢量路由协议。Linux内核原生支持BGP,因此可以把一台Linux主机配置为边界网关。
BGP里包含AS(Autonomous System)自治系统, 独立维护着一个路由表,具有去中心化,防止单点故障的功能。
BGP 使用路径矢量(AS_PATH)记录路由经过的 AS 列表,防止路由环路。
AS 之间通过 BGP 对等体建立连接,自主协商路由信息,无需第三方介入。

Calico工作模式:

• IPIP:Overlay Network方案,源数据包封装在宿主机网络包里进行转发和通信。(默认)
• BGP:基于路由转发,每个节点通过BGP协议同步路由表,写到宿主机。 (值设置Never)
• CrossSubnet:同时支持BGP和IPIP,即根据子网选择转发方式。(折中方案,集群当中是有两个网段,又想使用路由的高性能)

通过调整参数改变工作模式:

- name: CALICO_IPV4POOL_IPIP
value: "Always"

由于默认是IPIP模式,如果需要启用BGP模式,则需要修改相关配置: 即将CALICO_IPV4POOL_IPIP 和 CALICO_IPV4POOL_VXLAN 的值设置为Never

这两个参数设置为never后,跨节点之间的通信,就不会经过overlay的封装。自然而然就是通过路由的方式实现跨节点pod通信了。

- name: CALICO_IPV4POOL_IPIP
  value: "Never"
  # Enable or Desable VXLAN on the default IP pool.
- name: CALICO_IPV4POOL_VXLAN
  value: "Never"

BGP的几种模式:

1.Full-mesh (全互联模式)
启用 BGP 后,Calico 的默认行为是创建完整的内部 BGP (iBGP)连接,其中每个节点相互对等。
这允许 Calico 在任何 L2 网络上运行,无论是公有云还是私有云全网格非常适合 100 个或更少的中小型部署
但在更大的规模下,Full-mesh的效率会降低,官方建议使用路由反射模式。

2.Route reflectors (路由器反射模式)
若要构建内部BGP(iBGP)的大型集群,可以使用 BGP 路由反射器来减少每个节点上使用的 BGP 对等互连数。
在此模型中,一些节点充当路由反射器,并配置为在它们之间建立Full-mesh模式。
然后,将其他节点配置为与这些路由反射器的子集(通常为2 个用于冗余)对等互连,与Full-mesh模式相比,
减少了BGP对等连接的总数。

3.Top of Rack(物理边缘路由器)
在使用Top of Rack模式时,可考虑与路由器反射模式一起使用。
在本地部署中,可以将 Calico 配置为直接与物理网络基础结构对等互连。
通常,这涉及禁用 Calico 的默认Full-mesh模式,而是将 Calico与L3 Top of Rack 路由器对等。
构建本地 BGP 网络的方法有很多种。
如何配置 BGP 由您决定 - Calico 适用于 iBGP 和 eBGP 配置\
您可以有效地将 Calico 视为网络设计中的任何其他路由器。

参考文献:
https://www.cnblogs.com/amsilence/p/18229363

配置文件

节点主机目录:/etc/calico/calico-node 文件位于每个 Kubernetes 节点主机的文件系统中

Calico 以 DaemonSet 形式部署,虽然其核心组件(如 Felix、BIRD)运行在 Calico 容器中,但配置文件需要在节点主机上可见,以便:
调试和管理:管理员可以直接在节点主机上查看和修改配置文件,而无需进入容器。
持久化存储:节点主机的文件系统提供了更稳定的存储,避免容器重启或重建时配置文件丢失。

Felix:calico的核心组件,运行在每个节点上。主要的功能有接口管理、路由规则、ACL规则和状态报告
以DaemonSet方式部署,主要负责维护宿主机上路由规则以及ACL规则。(从别的节点学习路由表的信息)

接口管理:Felix为内核编写一些接口信息,以便让内核能正确的处理主机endpoint的流量。特别是主机之间的ARP请求和处理ip转发。

路由规则:Felix负责主机之间路由信息写到linux内核的FIB(Forwarding Information Base)转发信息库,保证数据包可以在主机之间相互转发。

通过 proxy_arp 设置解决跨节点 ARP 请求问题

Veth Pair:每个 Pod 通过 veth 对连接到宿主机的网络命名空间

/etc/calico/calico-node 文件用于配置 Calico 在节点上的运行参数,例如:

网络模式:选择 BGP 模式或 IPIP 模式。
IP 地址池:定义 Pod 的 IP 地址范围和子网。
路由规则:配置路由分发和同步策略。
其他参数:如日志级别、健康检查间隔等。

K8S中calico与etcd的关系

etcd是Calico的分布式键值存储系统,负责存储所有网络状态信息,确保各节点数据一致性。
Calico通过etcd的API进行数据的读写操作。
数据同步流程
Calico组件(如Felix、BIRD)将本地网络配置、路由信息、网络策略等写入etcd。
其他节点通过监听etcd的变更事件,实时同步最新数据,实现全局网络状态的一致性。

定义Pod之间的访问控制规则(如允许/拒绝特定端口的流量),例如:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-http
spec:
  podSelector:
    matchLabels:
      app: web
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 80

这些策略会被转换为Calico内部的ACL规则,并存储在etcd中。

调度情况

Pod创建时
Kubernetes通过CNI接口调用Calico,为Pod分配IP。
Calico的Felix组件将Pod的IP、节点信息等写入etcd。
其他节点通过监听etcd获取该Pod的路由信息,更新本地路由表。

网络策略更新时
用户通过kubectl apply更新NetworkPolicy。
Kubernetes将策略存入etcd。
Calico的kube-controllers组件检测到变更,将策略转换为Calico格式并写入etcd。
各节点的Felix组件同步策略,并更新iptables/eBPF规则。

查看节点 BGP 邻居状态

calicoctl node status

网络策略

apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
  name: deny-db-access
  namespace: default
spec:
  selector: role == 'db'
  ingress:
    - action: Deny
      source:
        namespaceSelector: name == 'default'
  egress:
    - action: Allow

监控指标

felix_resync_state:数据同步状态
bgp_peer_up:BGP 邻居状态
iptables_chain_update_seconds:策略更新时间

常用命令

验证 BGP 会话状态:
calicoctl node status
查看路由表:
ip route show table all
检查网络策略:
calicoctl get networkpolicy -A
优化
eBPF

前身为BPF(Berkeley Packet Filter,伯克利包过滤器)Linux中被libcap 和tcpdump等应用使用。

2013年,Alexei Starovoitov对BPF进行了彻底地改造,改造后的BPF被命名为eBPF(extended BPF),于Linux Kernel 3.15中引入Linux内核源码。

eBPF支持了更多领域的应用,它不仅支持网络包的过滤,还可以通过 kprobe,tracepoint,lsm等Linux现有的工具对响应事件进行追踪。

涉及JIT 编译器、ELF格式书写等技术。

calicoctl patch kubecontrollersconfiguration default --patch='{"spec": {"controllers": {"node": {"hostEndpoint": {"autoCreate": "Enabled"}}}}}'
调整BGP
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  logSeverityScreen: Info
  nodeToNodeMeshEnabled: true
  asNumber: 64512
calico常用命令
# 下载工具:https://github.com/projectcalico/calicoctl/releases

$ wget -O /usr/local/bin/calicoctl https://github.com/projectcalico/calicoctl/releases/download/v3.13.3/calicoctl

$ chmod +x /usr/local/bin/calicoctl
# 查看集群节点状态

$ calicoctl node status

如果使用 calicoctl get node,需要指定 calicoctl 配置,默认使用 /etc/calico/calicoctl.cfg

# 设置 calicoctl 配置文件
$ vim /etc/calico/calicoctl.cfg

apiVersion: projectcalico.org/v3
kind: CalicoAPIConfig
metadata:
spec:
  datastoreType: "etcdv3"
  etcdEndpoints: https://10.10.0.174:2379
  etcdKeyFile: /opt/kubernetes/ssl/server-key.pem
  etcdCertFile: /opt/kubernetes/ssl/server.pem
  etcdCACertFile: /opt/kubernetes/ssl/ca.pem

# 查看 calico 节点
$ calicoctl get nodes

# 查看 IPAM的IP地址池
$ calicoctl get ippool -o wide

# 查看bgp网络配置情况
$ calicoctl get bgpconfig

# 查看ASN号,一个编号就是一个自治系统
$ calicoctl get nodes --output=wide

# 查看 bgp peer
$ calicoctl get bgppeer
流量方向
full mesh

Pod 1 访问 Pod 2 流程如下
1、数据包从 Pod1 出到达Veth Pair另一端(宿主机上,以cali前缀开头)
2、宿主机根据路由规则,将数据包转发给下一跳(网关)
3、到达 Node2,根据路由规则将数据包转发给 cali 设备,从而到达 Pod2。
其中,这里最核心的 下一跳 路由规则,就是由 Calico 的 Felix 进程负责维护的。
这些路由规则信息,则是通过 BGP Client 中 BIRD 组件,使用 BGP 协议来传输。
Calico 项目实际上将集群里的所有节点,都当作是边界路由器来处理,它们一起组成了一个全连通的网络,互相之间通过 BGP 协议交换路由规则。这些节点,我们称为 BGP Peer。

而 Flannel host-gw 和 Calico 的唯一不一样的地方就是当数据包下一跳到达node2节点容器时发生变化,并且出数据包也发生变化,知道它是从veth的设备流出,容器里面的数据包到达宿主机上,这个数据包到达node2之后,它又根据一个特殊的路由规则,这个会记录目的通信地址的cni网络,然后通过cali设备进去容器,这个就跟网线一样,数据包通过这个网线发到容器中,这也是一个二层的网络互通才能实现。

Route Reflector 模式(RR)(路由反射)

设置方法请参考官方链接 https://docs.projectcalico.org/master/networking/bgp

Calico 维护的网络在默认是 (Node-to-Node Mesh)全互联模式,Calico集群中的节点之间都会相互建立连接,用于路由交换。但是随着集群规模的扩大,mesh模式将形成一个巨大服务网格,连接数成倍增加。
这时就需要使用 Route Reflector(路由器反射)模式解决这个问题。
确定一个或多个Calico节点充当路由反射器,让其他节点从这个RR节点获取路由信息。

在BGP中可以通过calicoctl node status看到启动是 node-to-node mesh 网格的形式,这种形式是一个全互联的模式,默认的BGP在k8s的每个节点担任了一个BGP的一个喇叭,一直吆喝着扩散到其他节点,随着集群节点的数量的增加,那么上百台节点就要构建上百台链接,就是全互联的方式,都要来回建立连接来保证网络的互通性,那么增加一个节点就要成倍的增加这种链接保证网络的互通性,这样的话就会使用大量的网络消耗,所以这时就需要使用Route reflector,也就是找几个大的节点,让他们去这个大的节点建立连接,也叫RR,也就是公司的员工没有微信群的时候,找每个人沟通都很麻烦,那么建个群,里面的人都能收到,所以要找节点或着多个节点充当路由反射器,建议至少是2到3个,一个做备用,一个在维护的时候不影响其他的使用。

IPIP模式流量方向

IPIP 是linux内核的驱动程序,可以对数据包进行隧道,两个不同的网络 vlan1 和 vlan2。基于现有的以太网将原始包中的原始IP进行一次封装,通过tunl0解包,这个tunl0类似于ipip模块,和Flannel vxlan的veth很类似。

Pod1 访问 Pod2 流程如下:
1、数据包从 Pod1 出到达Veth Pair另一端(宿主机上,以cali前缀开头)。
2、进入IP隧道设备(tunl0),由Linux内核IPIP驱动封装,把源容器ip换成源宿主机ip,目的容器ip换成目的主机ip,这样就封装成 Node1 到 Node2 的数据包。

你可能感兴趣的:(网络,k8s)