四、Kubernetes网络--Calico
另外一种虚拟网络解决方案。可以为容器,虚拟机,物理机提供网络服务;可以与K9S,Mesos, Neutron 等集成。
4.1 Calico 简介
(1)简介
Calico 是针对容器,虚机,物理机服务器的网路解决方案。
# 提供CNI plugin 可以与K8S, Mesos 集成
#提供 Libnetwork plugin 可以与Docker集成
#与Neutron plugin 形式与OpenStack集成
(2)K8S 网络的核心思想
K8S的网络实现,为每一个WorkNode分配一个Pod 子网,所有WorkNode里的Pod从这个子网里分配一个集群内唯一的IP地址。之前学习过的两种K8S网络方案:
第一种,是K8S自带的KutbeNet,通过修改连接WorkNode路由器的配置,增加Pod对应子网的路由,从而实现跨WorkNode 的Pod网络的连接。
第二种,是Flannel,给每一个WorkNode配置Pod子网对应的路由,从而实现跨WorkNode的Pod网络的连接。是Flannel相当于是在每个WorkNode上实现了分布式的虚拟路由器,来代替在KutbeNet上需要配置连接WorkNode的集中式路由器,避免配置K8S集群以外路由设备的操作;也避免一些单点故障。需要在WorkNode上运行Flanneld进程,一般这个进程跑在K8S容器Pod里面,通过这个进程来检测K8S的API, 检测API,再同步etcd,保证每个节点上的数据都是同步的,就是要检测每个WorkNode里的K8S API,当集群很大时,这种同步对于集中的API server和etcd都是压力。
(3)calico 网络
However, 这里是重点:Calico 的核心是通过BGP来提供节点之间的数据同步,从而缓解了K8S api 与 etcd之间的压力。因此,可以适用于更大规模的集群。
可以提供K8S Pod网络,还可以提供network policy,可以实现多个用户之间的网络隔离,是Kutbnet和Flannel 所不具备的。
(4)Calico 架构
# 独立的完整的网络解决方案,可以供给Docker, K8s, OpenStack,物理服务器用。是一个完整、独立的解决方案。所以,也需要数据库来存储网络信息,在K8S中存储可以是一个独立的etcd, 也可以共用K8S的etcd。
# Calico与Kubenetes集成
#Master Node
首先需要在MasterNode上运行一个叫Calico-kube-controllers的Pod,这个Pod与其他的K8s管理容器、管理进程一样,也是运行在Hostnetwork下面;这个Pod一方面去连接K8S 的API, 监听并读取K8S上的数据和变化,另外一方面需要连接Calico的etcd,将K8S的数据同步到etcd。对比Flannel,是没有一个集中的controller运行在Master上,是每一个运行在WorkNode上的Flanneld同步K8SAPI 和etcd。
Calico 是集中同步
Flannel是分布同步
#Worker Node
在每个Worker Node上,Calico 会运行一个叫calico-node的Pod,也是运行在HostNetwork下面,在Worker Node, Calico-node主要负责在WorkNode上去配置Calico的CNI,同时配置WorkNode的网络。
Calico-node 具体内容:
Calico容器中运行了四个进程(传统的进程管理方法,与Docker思想不同),但是Calico使用程序:runsvdir来管理这4个进程,runsvdir作为主进程,会检测它所启动的4个进程状态,如果任何一个进程退出,runsvdir会尝试重启它,所以也可以达成一个类似Pod的效果,因此在此方面,在同一个容器启动多个进程是可以接受的,不用考虑重启和高可用的问题。
具体四个进程:
Felix: Calico项目的核心(是Calico独有的组件)
管理Calico相关的网卡;包括接受Pod发送的API请求,并将WorkNode的MAC地址返回,类似ARP Relay功能,为当前WorkNode上的网卡提供转发功能,检测网卡的状态,并且在网卡上线或下线时进行相应的配置。
*管理Calico相关网卡
*配置WorkerNode上的路由表
*配置WorkerNode上相应的Network Policy
*上报当前节点状态
Bird: 是独立于Calico的BGP项目,实现了BGP协议。在Worker Node上通常会运行两个进程,一个是IPv4,一个是IPv6。Calico同时对Bird进行了修改,提供了对于IP-IP Tunnel的支持。
Confd: 也是独立于Calico的项目,用来确保配置文件与数据库etcd之间的同步,并且会重启相关的进程,以应用更新了的配置文件。
检测、同步etcd进程的变化,并更新BGP配置,在重启Bird进程。Confd结合Bird后呢,相当于自动化了BGP的配置。
4.2 Calico 安装
4.3 BGP(略)
4.4 Pure BGP
是Calico 支持的两种网络方案之一。
Docker的网络实现方式:
Docker, K8s Kubenet, Flannel 的网络实现底层是基于LinuxBridge,在本地做一个二层桥接,在WorkerNode之间(每一个WorkerNode都是一个独立的三层网络),通过Docker、Kubenet、Flannel构建的路由器,来连接不同Worker Node Pod上的不同子网。
Calico的网络实现方式:
Calico实现Pod网络:
Calico 解决方案中没有Linux bridge
Calico在WokerNode 上有四个进程组成,最核心的是Felix,然后有bird(ipv4,ipv6)和confd进程。confd是用来读取etcd的配置,并将这些配置用运在felix和bird上去,让他们生效。
bird进程之间,通过BGP来连接和交换每个WorkerNode上Pod的子网信息,Pod收到远端的路由信息后,会在本端路由表下发路由。
Pod内的路由:
在Calico解决方案中,没有LinuxBridge, 所有Pod内的网络转发都走三层转发。
Pod内的ARP:
同一个WorkerNode上两个Pod之间通信,
没有LinuxBridge来连接veth设备的情况,所有转发要依赖内核路由表来查找,转发本地Pod,转发远端Pod。
Calico网络方案中,没有Linux Bridge, Pod内的路由,都是通过默认路由来转发的:
但是169.254.1.1是个保留地址,一般用在内网里,也是不存在一个网络设备是配置169.254.1.1地址的,最终Pod内的数据包是如何传输出来的呢?
因为默认路由的下一跳,指向了169.254.1.1,那么网络数据在Pod里封装的时候,它的目的MAC必然是169.254.1.1的MAC地址,因此协议栈首先会发ARP请求,去查询169.254.1.1的MAC地址,这个ARP在Calico中,Calico会配置Pod的veth远端设备(Pod内的网卡还是通过veth对来实现的),而此时Pod的veth对一端是插在Pod里的,另一端是悬空的,接在主机的网络空间。对于悬空的veth, Calico会配置ARP-Proxy,其中Proxy_delay=0(立刻返回proxy应答),另外打开Proxy_arp
在Calico的实现中,所有的与Pod配对的veth设备,它们的MAC地址都是ee:ee:ee:ee:ee:ee。
同Worker Node Pod间的通信
基础条件是:打开ARP Forwarding 功能
所以,如果要访问10.10.166.151,可以通过送到cali1来实现,cali1因为打开了ARP Forwarding的功能,它会接收发来的数据包,并且它是Pod2的veth对(cali1与eth0之间的veth对),因此数据包从cali1收到后,就送到Pod2上的eth0,Pod2就收到了Pod1的数据请求。
跨Worker Node Pod间的通信
因此,在同WorkerNode 中两个不同的Pod访问是通过查找明细路由来实现的。明细路由是由Brid通过BGP学习到的。
“bird”说明这条路由是BGP学习到的。通过路由Host1将数据转发到Host2,Host2要匹配精确路由,由eth0送到cali0,cali0再送到Pod3.
总结,在Calico中,Worker Node不关心网路数据包是从当前发出,还是其他地点发出,都是通过主机网络空间的明细路由,转发到相应的Pod。
4.5 Pure BGP 演示
4.6 IP in IP
IPinIP是Calico的第二种网络方案
4.6.1解决问题:
Pure BGP的问题:Pod的IP地址是直接在WorkNode上做传递,Pod的IP地址不能与WorkNode重复,要求IP地址唯一性。WorkNode域中的网卡,会出现多Pod,多源IP地址,而PureBGP是直接将Pod的IP地址宣告出去,所以在WorkNode的网卡上会看到多个源IP地址,所以给跨WorkNode和跨AS通信带来问题,所以Calico提供了IPinIP的解决方案,将原始Pod网络的IP地址封装在WorkNode IP地址中。
IP 隧道协议,RFC2003, 将一个IP Packet 封装在另一个IP Packet中;外层IP Header 协议号是4。
对应的是GRE(Generic Routing Encapsulation) , RFC2784, 也是将一个IP Packet 封装在另一个IP Packet中,外层IP Header协议号是47。不同与IPinIP,GRE有一个“GRE”层(4bytes),可以携带“属性”;而IPinIP没有中间层,只是一个隧道协议,所以不能实现多租户。
4.6.2 实现
step1: 新增一个IPinIP 类型netdev设备(就是本机)
step2: 远端worker node 的路由指向IPinIP设备
跨WorkNode的Pod间通信依靠tunnel构建的隧道实现。
4.7 IP in IP 演示
4.8 Network Policy
在默认情况下,在一个Kubenetes 集群里,任意个Pod都可以访问到其他Pod,不管这个Pod是属于一个用户,还是多个用户。这在安全上是由风险的。K8S通过定义Network Policy来定义网络服务访问的策略,支持Network Policy的CNI是Calico, Weave等。
默认情况下,WorkNode没有定义Netwrok Policy, 所有Pod的网络是不受限制的,是可以互相访问的。
Calico 使用IP Tables来实现 Network Policy,
用iptables Filter Table 来实现,iptables Filter是iptables中的多个表之一,也是默认表,对网络数据包的包头做处理:Forward, Input, Output,等。