Calico是一种用于管理Docker容器网络的工具。它使用etcd存储和共享虚拟网络和控制平面的状态
Calico为容器和虚拟机工作负载提供一个安全的网络连接。
Calico可以创建并管理一个3层平面网络,为每个工作负载分配一个完全可路由的IP地址。 工作负载可以在没有IP封装或网络地址转换的情况下进行通信,以实现裸机性能,简化故障排除和提供更好的互操作性。 在需要使用overlay网络的环境中,Calico提供了IP-in-IP隧道技术,或者也可以与flannel等其他overlay网络配合使用。
Calico还提供网络安全规则的动态配置。 使用Calico的简单策略语言,就可以实现对容器、虚拟机工作负载和裸机主机各节点之间通信的细粒度控制。
1. 基本概念
-
节点(Node)
运行Docker容器的宿主机实体,可以是物理计算机或虚拟机,在 Calico 中,每个节点上都运行了一个守护进程,称为 Felix。Felix 维护每个节点上的网络状态并处理来自控制平面的命令 -
工作负载(Workload)
在节点上运行的Docker容器实例,在 Calico 中,每个工作负载都关联到一个或多个标签(Label),标记在 Kubernetes 中也称为 "labels",它们用于识别和选择相应的工作负载。 -
Endpoint
链接节点上的工作负载和网络的虚拟接口 -
网络策略(Network Policy)
网络策略是规定哪些工作负载可以与哪些其他工作负载进行通信的规则集合。它可定义源目标和协议等规则,从而允许或禁止流量。 -
Calico网络
一组可以相互访问的Endpoint,形成一个虚拟网络。 -
路由
连接不同节点的Calico网络的物理路径。 -
防火墙(Firewall)
防火墙是隔离传入和传出流量的网络设备或软件。在 Calico 中,网络策略约束了容器流量,实际上是在底层技术上通过 iptables 防火墙策略来实现的
2. 原理
Calico 的核心原理是 "路由优于隧道(Routing is better than tunneling)"。它使用内核路由表和 BGP 协议来引导数据包,从而提供高效可靠的容器网络。
Calico 中每个节点都维护自己的路由表,并使用 BGP 协议告知其他节点它可以到达哪些 IP 地址。这样,当数据包进入集群时,它会被路由到相应的目标节点,这将显着减小了传输延迟并提高了吞吐量。
Calico 还支持使用边界路由器(Border Gateway Protocol router) 进行多个 Kubernetes 集群之间的容器网络互连,从而实现了集群间通信。
3. Calico主要组件
-
Felix:负责客户端响应、配置路由规则和ACL等组件和工具的操作。
-
Bird:BGP客户端,Calico在每个节点上的都会部署一个BGP客户端,它的作用是将Felix的路由信息读入内核,并通过BGP协议在集群中分发。当Felix将路由插入到Linux内核FIB中时,BGP客户端将获取这些路由并将它们分发到部署中的其他节点。这可以确保在部署时有效地路由流量
-
Calicoctl:命令行工具,用于控制和管理Calico集群。
-
Etcd:作为数据存储后端,存储网络状态信息和Kubernetes对象信息等。
-
Typha: 在大规模集群环境下,Felix 需要和Etcd存储系统进行大量的通信,会导致性能和可靠性问题。为了解决这个问题,Calico提供了一个中心化组件Typha,它可以将Felix 和Etcd之间的通信转化为HTTP请求,从而解决性能和可靠性问题。
-
Orchestrator plugin:协调器插件负责允许kubernetes或OpenStack等原生云平台方便管理Calico,可以通过各自的API来配置Calico网络实现无缝集成。如kubernetes的cni网络插件。
4. Calico 网络模式
4.1. IPIP模式
把 IP 层封装到 IP 层的一个 tunnel。作用基本上就相当于一个基于IP层的网桥,将各Node的路由之间做一个tunnel,再把两个网络连接起来的模式。启用IPIP模式时,Calico将在各Node上创建一个名为”tunl0″的虚拟网络接口
IPIP网络的特点是所有pod的数据流量都从隧道tunl0发送,并且在tunl0增加了一层传输层的封包。
IPIP模式的数据包封装结构,以pod1 ping pod2为例:
IPIP的连接方式:
4.2. BGP 模式
直接使用物理机作为虚拟路由路(vRouter),不创建额外的tunnel,通过维护IP路由表或‘前缀’表来实现自治系统(AS)之间的可达性,属于矢量路由协议,使用基于路径、网络策略或规则集来决定路由
BGP网络中,pod之间的流量直接从网卡发送目的地,减少了tunl0这个环节
- 全互联模式(node-to-node mesh)
每一个BGP Speaker都需要和其他BGP Speaker建立BGP连接,这样BGP连接总数就是N^2,如果数量过大会消耗大量连接。如果集群数量超过100台官方不建议使用此种模式 - Route Reflector 模式(RR)(路由反射)
指定一个或多个BGP Speaker为RouterReflection,它与网络中其他Speaker建立连接,每个Speaker只要与Router Reflection建立BGP就可以获得全网的路由信息。在calico中可以通过Global Peer实现RR模式。
bgp的连接方式:
路由反射模式:
4.3. 两种网络模式对比
- IPIP网络:
流量:tunlo设备封装数据,形成隧道,承载流量。
适用网络类型:适用于互相访问的pod不在同一个网段中,跨网段访问的场景。外层封装的ip能够解决跨网段的路由问题。
效率:流量需要tunl0设备封装,效率略低
- BGP网络:
流量:使用路由信息导向流量
适用网络类型:适用于互相访问的pod在同一个网段,适用于大型网络。
效率:原生hostGW,效率高
5. 使用
5.1. 安装docker和K8S
calico的使用基于容器和K8S
docker的安装参考官方文档:
https://docs.docker.com/engine/install/
K8S的安装参考官方文档:
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
安装成功并初始化后使用kubectl get nodes
可以看到如下信息
[root@localhost ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master.local NotReady master 97s v1.18.8
5.2. 安装calico
在Docker宿主机上运行以下命令进行安装:
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.1/manifests/tigera-operator.yaml
安装后运行watch kubectl get pods -n --all-namespaces
查看所有在运行的pod
删除master节点上的taints标记信息,因为部署的是单节点测试集群,需要让scheduler可以向master上面调度创建pods
[root@localhost ~]# kubectl taint nodes --all node-role.kubernetes.io/master-
node/master.local untainted
查看并确认在测试集群中已经有一个node节点
[root@localhost ~]# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
master.local NotReady master 25m v1.18.8 192.168.88.133 <none> CentOS Linux 7 (Core) 3.10.0-1160.el7.x86_64 docker://23.0.5
5.3. 安装calicoctl
下载calicoctl
curl -L https://github.com/projectcalico/calico/releases/v3.25.1/download/calicoctl-linux-amd64 -o calicoctl
calicoctl常用命令
#查看集群节点状态
$ calicoctl node status
# 查看 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
5.4. 创建虚拟网络
使用以下命令创建一个新的Calico环境:
calicoctl apply -f - <<EOF
kind: IPPool
metadata:
name: ippool-192-168-0-0-16
spec:
cidr: 192.168.0.0/16
EOF
5.5. 创建Endpoint
使用以下命令创建一个新的Endpoint:
docker run -d --name=my-nginx --net=none nginx
calicoctl container add my-nginx 192.168.0.10
5.6. 配置策略
使用以下命令配置网络策略:
calicoctl apply -f - <<EOF
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: allow-80
spec:
selector: app == "my-nginx"
ingress:
- action: Allow
protocol: TCP
destination:
ports:
- 80
EOF
6. calico和flannel的对比
flannel的三种模式
-
Calico 提供的 BGP 网络解决方案,与 Flannel 的 host-gw 模式都是基于路由表实现容器数据包转发,但不同于Flannel使用flanneld进程来维护路由信息的做法,Calico项目使用BGP协议来自动维护整个集群的路由信息。
-
fannel host-gw 必须二层连通
Pod 通信时,相当于把对方的宿主机当做网关
本机上有路由规则: 【对方 Pod IP】 —— 【对方主机 MAC 地址】
这样本机 Pod 要发送给对方 Pod,就会直接发给对方主机,对方主机上当然会有自己所有 Pod 的路由信息,这样完成了通信
同样,对方需要发回数据时,也是直接将数据发到本宿主机上,然后转发给对应的 Pod
封装的数据包为 【对方主机mac地址】【Pod IP 地址】【端口】
因此这样要求必须二层连通,直接可以到达对方宿主机
若是三层,中间的路由器不认识【Pod IP 地址】,也无法解析到【下一跳】,因此不知道该发到哪,所以只能二层连通
Calico BGP 解决了此问题,支持 BGP 的路由器中也会存储着 【Pod IP】—— 【宿主机MAC地址】的映射信息,因此知道该如何转发,这个信息的分发和维护,基于BGP的内在机制 (Brid 组件)
总体来说,Calico 使用基于 BGP 的路由,可以支持任意拓扑,并且适用于大规模部署。而 Flannel 使用基于 VXLAN 的覆盖网络,仅支持扁平拓扑,并且适用于小规模部署。calico相比flannel支持不需要封装的路由通信,性能更好。此外,Calico 还提供了更高级的安全性和网络策略功能,可以更好地保护应用程序和数据。