容器网络之Kubernetes CNI 系统管理员 2022-12-12 02:22 356阅读 0赞 ### 文章目录 ### * 容器网络之Kubernetes CNI * * 前言 * 1、Flannel * * 1.1、Flannel 在 K8S 中运行的整体过程 * 1.2、数据传递过程 * 1.3、实操通信链路抓包确认(未完成) * 2、Calico * 3、Weave Net * 4、Contiv * 5、CNI-Genie * 6、Cilium * 7、Contrail * 8、Multus # 容器网络之Kubernetes CNI # ## 前言 ## 容器网络发展到现在,形成了Docker的CNM以及由Google、CoreOS、Kuberenetes主导的CNI两大阵营。需要明确的是,CNM和CNI只是容器网络的规范,并不是网络实现,它们只是容器网络的规范,从开发者的角度看,就是一堆接口,底层用Flannel也好,用Calico也罢,他们并不关心。 Kubernetes作为容器的编排框架,在网络层面,并没有进入更底层的具体容器互通互联的网络解决方案的设计中,而是将网络功能一分为二,主要关注Kubernetes服务在网络中的暴露以及Pod自身网络的配置,至于Pod具体需要配置的网络参数以及Service、Pod之间的互通互联,则交给CNI来解决。这样Kubernetes本身不用具有太复杂的网络功能,从而能够将更多的精力放在Kubernetes服务和容器的管理上,最终能够对外呈现一个易于管理、可用性高的应用服务集群。 CNI于2015年4月由CoreOS公司推出,优势是兼容其他容器技术及上层编排系统,如Kubernetes与Mesos。CNI的目的在于定义一个标准的接口规范,使得Kubernetes在增删Pod的时候,能够按照规范向CNI实例提供标准的输入并获取标准的输出,再将输出作为Kubernetes管理Pod网络的参考。在满足输入输出以及调用标准的CNI规范下,Kubernetes委托CNI实例管理Pod的网络资源并为Pod建立互通能力。 CNI本身实现了一些基本的插件,比如Bridge、IPvlan、MACvlan、Loopback、vlan等网络接口管理插件,还有dhcp、host-local等IP管理插件,并且主流的容器网络解决方案都有对应CNI的支持能力,比如Flannel、Calico、Weave、Contiv、SR-IOV、Amazon ECS CNI Plugins等。 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xMODQ1ODc2NDI1_size_16_color_FFFFFF_t_70_pic_center][] CNI的接口主要包括以下几种方法:添加网络、删除网络、添加网络列表和删除网络列表。每个CNI插件只需要实现两类方法,一类是配置网络,用于创建容器时调用,一类是清理网络,用于删除容器时调用(以及一个可选的VERSION查看版本操作)。所以,CNI的实现确实非常简单,把复杂的逻辑交给具体的Network Plugin实现。CNI插件必须实现为一个可执行文件,这个文件被容器编排管理系统(例如Kubernetes)调用。CNI插件负责将网络接口插入容器网络命名空间(例如veth pair的一端),并在主机上进行任何必要的改变(例如将veth的另一端连接到网桥),然后将IP分配给接口,并通过调用适当的IPAM(IP Address Management)插件来设置路由。 用户通过使用参数`--network-plugin=cni`来运行kubelet,从而运行对应的CNI插件。kubelet会从参数`--cni-conf-dir`确定的目录(默认值为`/etc/cni/net.d`)读取文件,并使用该文件中的CNI配置来设置每个Pod的网络。CNI配置文件必须与CNI规范相匹配,并且配置中所引用的任何所需的CNI插件必须存在于`--cni-bin-dir`参数确定的目录中(默认值为`/opt/cni/bin`)。如果目录中存在多个CNI配置文件,则按照文件名的词典顺序排序并选取顺序排第一的CNI配置文件。除CNI配置文件指定的CNI插件外,Kubernetes还需要标准的CNI lo插件,并且最低版本为0.2.0。 [root@master ~]# ll /etc/cni/net.d/ 总用量 4 -rw-r--r-- 1 root root 94 9月 12 18:04 00-galaxy.conf [root@master ~]# [root@master ~]# cat /etc/cni/net.d/00-galaxy.conf { "type": "galaxy-sdn", "capabilities": { "portMappings": true}, "cniVersion": "0.2.0" } [root@master ~]# ll /opt/cni/bin/ 总用量 77964 -rwxr-xr-x 1 root root 4159253 1月 23 2020 bandwidth -rwxr-xr-x 1 root root 4671350 1月 23 2020 bridge -rwxr-xr-x 1 root root 12116044 1月 23 2020 dhcp -rwxr-xr-x 1 root root 5945760 1月 23 2020 firewall -rwxr-xr-x 1 root root 3069556 1月 23 2020 flannel -rwxr-xr-x 1 root root 7861170 5月 21 19:39 galaxy-sdn -rwxr-xr-x 1 root root 4153025 1月 23 2020 host-device -rwxr-xr-x 1 root root 3614305 1月 23 2020 host-local -rwxr-xr-x 1 root root 4314508 1月 23 2020 ipvlan -rwxr-xr-x 1 root root 3026388 8月 18 2017 loopback -rwxr-xr-x 1 root root 4389532 1月 23 2020 macvlan -rwxr-xr-x 1 root root 3939867 1月 23 2020 portmap -rwxr-xr-x 1 root root 4590104 1月 23 2020 ptp -rwxr-xr-x 1 root root 3392736 1月 23 2020 sbr -rwxr-xr-x 1 root root 2885430 1月 23 2020 static -rwxr-xr-x 1 root root 3356497 1月 23 2020 tuning -rwxr-xr-x 1 root root 4314356 1月 23 2020 vlan [root@master ~]# ps -efww | grep kubelet | grep -v grep root 33734 1 31 7月09 ? 26-14:29:25 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet .conf --config=/var/lib/kubelet/config.yaml --cgroup-driver=cgroupfs --hostname-override=10.25.0.10 --network-plugin=cni --pod-infra-container-image=registry.tce.com /library/pause:3.1 root 73234 73216 0 9月12 ? 00:00:04 /csi-node-driver-registrar --v=5 --csi-address=/csi/csi.sock --kubelet-registration-path=/var/lib/kubelet/plugins/loop device.csi.infra.tce.io/csi.sock [root@master ~]# kubectl get pod --all-namespaces | grep galaxy kube-system galaxy-daemonset-6br6w 1/1 Running 0 64d kube-system galaxy-daemonset-7dqhd 1/1 Running 4 100d kube-system galaxy-daemonset-7zk92 1/1 Running 0 100d kube-system galaxy-daemonset-8qnbk 1/1 Running 0 100d kube-system galaxy-daemonset-9z7lh 1/1 Running 2 65d kube-system galaxy-daemonset-bnjr5 1/1 Running 2 37d [root@master ~]# kubectl -n kube-system get pod flannel-6sr6r -o yaml [root@master ~]# kubectl get configmap/kube-flannel-cfg -n kube-system -o yaml | grep -i type "type": "flannel", "type": "portmap", "Type": "vxlan" [root@master ~]# kubectl get configmap/kube-flannel-cfg -n kube-system -o yaml apiVersion: v1 data: cni-conf.json: | { "name": "cbr0", "plugins": [ { "type": "flannel", "delegate": { "hairpinMode": true, "isDefaultGateway": true } }, { "type": "portmap", "capabilities": { "portMappings": true } } ] } net-conf.json: | { "Network": "192.168.0.0/16", "Backend": { "Type": "vxlan" } } kind: ConfigMap metadata: creationTimestamp: "2020-04-16T11:25:30Z" labels: app: flannel tier: node name: kube-flannel-cfg namespace: kube-system resourceVersion: "406" selfLink: /api/v1/namespaces/kube-system/configmaps/kube-flannel-cfg uid: dd954170-1e7e-459c-b5b0-441be1d7b3b0 [root@master ~]# 以下是一些常见的CNI插件。 ## 1、Flannel ## https://github.com/coreos/flannel/blob/master/Documentation/backends.md Flannel是CoreOS开源的网络方案,负责为Kubernetes集群中的多个Node间提供层3的IPv4网络。容器如何与主机联网不在Flannel的考虑范围,Flannel只控制如何在主机之间传输流量。Flannel为Kubernetes提供了一个CNI插件,并提供了与Docker集成的指导。 Flannel在集群的每个主机上运行一个名为flanneld的小型代理,负责从一个预先配置的地址空间中向每个主机分配子网;使用Kubernetes API或etcd来存储网络配置、分配的子网和任何辅助数据(如主机的公共IP);数据包则通过VXLAN、UDP或host-gw这些类型的后端机制进行转发。 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xMODQ1ODc2NDI1_size_16_color_FFFFFF_t_70_pic_center 1][] Flannel的底层通信协议可以有很多选择,比如UDP、VxLAN、AWS VPC等,不同协议实现下的网络通信效率相差较多,默认为使用UDP协议,部署和管理相对简单。 * UDP封包使用了Flannel自定义的一种包头协议,数据是在Linux的用户态进行封包和解包的,因此当数据进入主机后,需要经历两次内核态到用户态的切换。网络通信效率低且存在不可靠的因素。- * VxLAN封包采用的是内置在Linux内核里的标准协议,因此虽然它的封包结构比UDP模式复杂,但由于所有数据封装、解包过程均在内核中完成,实际的传输速度要比UDP模式快许多。VxLAN方案在做大规模应用时复杂度会提升,故障定位分析复杂。 ### 1.1、Flannel 在 K8S 中运行的整体过程 ### 1)设置集群网络 flannel默认使用etcd作为配置和协调中心,首先使用etcd设置集群的整体网络。通过如下的命令能够查询网络配置信息: $ etcdctl ls /coreos.com/network/config 2)设置 Node 节点上的子网 基于在 etcd 中设置的网络,flannel 为每一个 Node 分配 IP 子网。 获取子网列表 $ etcdctl ls /coreos.com/network/subnets 获取子网信息 $ etcdctl ls /coreos.com/network/subnets/{IP网段} 3)在每个 Node 上启动 flanneld flannel 在每个 Node 上启动了一个 flanneld 的服务,在flanneld启动后,将从etcd中读取配置信息,并请求获取子网的租约。 所有 Node 上的 flanneld 都依赖 etcd cluster 来做集中配置服务,etcd 保证了所有node 上 flanned 所看到的配置是一致的。同时每个 node 上的 flanned 监听etcd上的数据变化,实时感知集群中node的变化。flanneld一旦获取子网租约、配置后端后,会将一些信息写入/run/flannel/subnet.env文件。 $ cat /var/run/flannel/subnet.env ![20201005143624716.png_pic_center][] 4)创建虚拟网卡 在Node节点上,会创建一个名为flannel.1的虚拟网卡。 $ ip addr show flannel.1 ![20201005143638814.png_pic_center][] 5)创建Docker网桥 并为容器配置名为docker0的网桥,实际是通过修改Docker的启动参数–bip来实现的。通过这种方式,为每个节点的Docker0网桥设置在整个集群范围内唯一的网段,从保证创建出来的Pod的IP地址是唯一。 $ ip addr show docker0 ![2020100514365947.png_pic_center][] 6)修改路由表 flannel会对路由表进行修改,从而能够实现容器跨主机的通信。 $ route -n ![2020100514371259.png_pic_center][] ### 1.2、数据传递过程 ### 在源容器宿主机中的数据传递过程: **1)源容器向目标容器发送数据,数据首先发送给 docker0 网桥** 在源容器内容查看路由信息: $ kubectl exec -it -p {Podid} -c {ContainerId} -- ip route **2)docker0 网桥接受到数据后,将其转交给 flannel.1 虚拟网卡处理** docker0 收到数据包后,docker0的内核栈处理程序会读取这个数据包的目标地址,根据目标地址将数据包发送给下一个路由节点: 查看源容器所在Node的路由信息: $ ip route **3)flannel.1 接受到数据后,对数据进行封装,并发给宿主机的 eth0** flannel.1收到数据后,flannelid会将数据包封装成二层以太包。 Ethernet Header的信息: * From:\{源容器flannel.1虚拟网卡的MAC地址\} * To:\{目录容器flannel.1虚拟网卡的MAC地址\} **4)对在flannel路由节点封装后的数据,进行再封装后,转发给目标容器 Node 的 eth0** 由于目前的数据包只是vxlan tunnel上的数据包,因此还不能在物理网络上进行传输。因此,需要将上述数据包再次进行封装,才能源容器节点传输到目标容器节点,这项工作在由linux内核来完成。 Ethernet Header 的信息: * From: \{源容器 Node 节点网卡的 MAC 地址\} * To: \{目录容器 Node 节点网卡的 MAC 地址\} IP Header的信息: * From:\{源容器Node节点网卡的IP地址\} * To:\{目录容器Node节点网卡的IP地址\} 通过此次封装,就可以通过物理网络发送数据包。 在目标容器宿主机中的数据传递过程: **5)目标容器宿主机的eth0接收到数据后,对数据包进行拆封,并转发给flannel.1虚拟网卡;** **6)flannel.1 虚拟网卡接受到数据,将数据发送给docker0网桥;** **7)最后,数据到达目标容器,完成容器之间的数据通信。** ### 1.3、实操通信链路抓包确认(未完成) ### ## 2、Calico ## Calico是一个基于BGP的纯三层的数据中心网络方案,与OpenStack、Kubernetes、AWS、GCE等IaaS和容器平台都有良好的集成。 如下图所示为Calico架构,Calico在每一个计算节点基于Linux内核实现了一个高效的vRouter来负责数据转发,基于iptables创建了相应的路由规则,并通过这些规则来处理进出各个容器、虚拟机和主机的流量。 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xMODQ1ODc2NDI1_size_16_color_FFFFFF_t_70_pic_center 2][] * calicoctl:Calico提供的命令行工具。 * orchestrator插件:提供与Kubernetes等的紧密集成和同步。 * key/value store:用于存储Calico的策略和网络配置状态。 * calico/node:运行在每个主机上,从key/value store读取相关的策略和网络配置信息,并在Linux内核中进行实现。 * Dikastes/Envoy:可选的Kubernetes sidecar,通过相互TLS身份验证保护工作负载到工作负载的通信,并实施应用层策略。 ## 3、Weave Net ## Weave Net能够简化用户对Kubernetes网络的配置。它可以作为CNI插件运行或独立运行。在这两种模式下,运行Weave Net均不需要任何额外的配置或代码。同时,两种模式都遵循了标准的“IP-per-Pod”模型。 ## 4、Contiv ## Contiv由思科开源,兼容CNI模型及CNM模型,能够为多种不同用例提供可配置的网络(比如原生L3网络使用BGP,overlay网络使用VxLAN)。Contiv带来的方便是用户可以根据容器实例IP地址直接进行访问。 ## 5、CNI-Genie ## 如图所示,CNI-Genie使Kubernetes能够在运行时同时访问Kubernetes网络模型的不同实现,例如Flannel、Calico、Romana和Weave-net等。CNI-Genie还支持为一个Pod分配多个IP地址,每个IP地址由不同的CNI插件来提供。 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xMODQ1ODc2NDI1_size_16_color_FFFFFF_t_70_pic_center 3][] ## 6、Cilium ## https://sourcegraph.com/github.com/cilium/cilium@v1.6.4/-/blob/api/v1/server/restapi/cilium\_api.go\#L593:21 https://sourcegraph.com/github.com/torvalds/linux@v4.16/-/blob/include/uapi/linux/bpf.h\#L289 Cilium是一款开源软件,它以一种不干涉运行在容器中的应用程序的方式,提供了安全的网络连接和负载均衡。Cilium在层3和层4运行,提供传统的网络和安全服务;同时,Cilium也在层7运行,以保护HTTP、gRPC和Kafka等应用协议的使用。 Cilium架构如图所示。Cilium已经集成到Kubernetes和Mesos等编排框架之中。一种名为BPF(Berkeley Packet Filter,伯克利包过滤器,于4.9内核开始支持)的Linux内核技术是Cilium的基础。它支持在各种集成点(如网络I/O、应用程序套接字和跟踪点)将BPF字节码动态地插入Linux内核,以实现安全性、网络和可见性逻辑。 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xMODQ1ODc2NDI1_size_16_color_FFFFFF_t_70_pic_center 4][] ## 7、Contrail ## 基于OpenContrail的Contrail是一个真正开放的多云网络虚拟化和策略管理平台。Contrail和OpenContrail已经与各种编排系统集成,如Kubernetes、OpenShift、OpenStack和Mesos,并为容器或Pod、虚拟机和裸机的工作负载提供了不同的隔离模式。 ## 8、Multus ## 在生产环境下,为了保证安全和性能,不同功能的网络进行隔离是一个必要的措施,如管理网络、控制网络和数据网络的隔离。这种隔离对于物理机和虚拟机来说很容易实现。但是在Pod里面,如果使用Kubernetes,则会面临一些限制,尤其是现Kubernetes的Pod默认还不支持多网卡设置。 在这种背景下,Intel的multuscni借助CNI在一定程度上满足了这个需求。如图所示,Multus可以为运行在Kubernetes的Pod提供多个网络接口,它可以将多个CNI插件组合在一起为Pod配置不同类型的网络。 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xMODQ1ODc2NDI1_size_16_color_FFFFFF_t_70_pic_center 5][] Multus能够支持几乎所有的CNI插件,包括Flannel、DHCP和Macvlan,以及Calico、Weave、Cilium和Contiv等第三方插件。Multus使用“delegates”的概念将多个CNI插件组合起来,并且指定一个master plugin作为Pod的主网络并且被Kubernetes感知。 Multus自己不会进行任何网络设置,而是调用其他插件(如Flannel、Calico)来完成真正的网络配置。它重用了Flannel中调用代理的方式,通过将多个插件分组,再按照CNI配置文件的顺序来调用它们。默认的网络接口名称为“eth0”,而Pod中的网络接口名称为net0、net1、……、netX。Multus也支持自动的网络接口名称。如图所示为Multus网络的工作流程 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xMODQ1ODc2NDI1_size_16_color_FFFFFF_t_70_pic_center 6][] [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xMODQ1ODc2NDI1_size_16_color_FFFFFF_t_70_pic_center]: /images/20221123/3a5930a946ff4d3ca4ebf503ae6f62b6.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xMODQ1ODc2NDI1_size_16_color_FFFFFF_t_70_pic_center 1]: /images/20221123/c6c05b90259c48299c121aaa02eb3086.png [20201005143624716.png_pic_center]: /images/20221123/5da2203e50ad4bb497b92f3d20159ce3.png [20201005143638814.png_pic_center]: /images/20221123/6a56e9824c924df48f5588882367878d.png [2020100514365947.png_pic_center]: /images/20221123/09e8e75c1760449286bbf140518995bf.png [2020100514371259.png_pic_center]: /images/20221123/5806c806c9f5467bbc9cb36d1108d002.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xMODQ1ODc2NDI1_size_16_color_FFFFFF_t_70_pic_center 2]: /images/20221123/499e4b49f18d4fcca45c04380b2e8573.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xMODQ1ODc2NDI1_size_16_color_FFFFFF_t_70_pic_center 3]: /images/20221123/0e760d59251b4fd9be57e6190d038011.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xMODQ1ODc2NDI1_size_16_color_FFFFFF_t_70_pic_center 4]: /images/20221123/256f1779a666479684824f77ed9ee3ed.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xMODQ1ODc2NDI1_size_16_color_FFFFFF_t_70_pic_center 5]: /images/20221123/83207ed423b84247b0fd3d5e149a21ae.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xMODQ1ODc2NDI1_size_16_color_FFFFFF_t_70_pic_center 6]: /images/20221123/d0ea0c2b952d4b7aa02f488ff5fe1f9d.png
还没有评论,来说两句吧...