文章目录

  • 容器网络之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等。

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: flanneltier: nodename: kube-flannel-cfgnamespace: kube-systemresourceVersion: "406"selfLink: /api/v1/namespaces/kube-system/configmaps/kube-flannel-cfguid: 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这些类型的后端机制进行转发。

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

4)创建虚拟网卡

在Node节点上,会创建一个名为flannel.1的虚拟网卡。

$ ip addr show flannel.1

5)创建Docker网桥

并为容器配置名为docker0的网桥,实际是通过修改Docker的启动参数–bip来实现的。通过这种方式,为每个节点的Docker0网桥设置在整个集群范围内唯一的网段,从保证创建出来的Pod的IP地址是唯一。

$ ip addr show docker0

6)修改路由表

flannel会对路由表进行修改,从而能够实现容器跨主机的通信。

$ route -n

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创建了相应的路由规则,并通过这些规则来处理进出各个容器、虚拟机和主机的流量。

  • 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插件来提供。

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内核,以实现安全性、网络和可见性逻辑。

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配置不同类型的网络。

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网络的工作流程

容器网络之Kubernetes CNI相关推荐

  1. Kubernetes — CNI 规范

    目录 文章目录 目录 容器网络的发展趋势 CNI Flannel Callico Weave Macvlan ServiceMesh + CNI CNI 的使用示例 容器网络的发展趋势 容器常见的网络 ...

  2. K8S中的容器网络概述(编写中)

    目录 参考资料 一.什么是容器网络 1.1 网络命名空间 1.2 veth设备对 二.K8S中节点间通信 2.1 不同Node中的Pod之间通信 三.xx实现概述 参考资料 K8s网络模型 - 腾讯云 ...

  3. Kubernetes Docker 容器网络终极之战(十四)

    与 Docker 默认的网络模型不同,Kubernetes 形成了一套自己的网络模型,该网络模型更加适应传统的网络模式,应用能够平滑的从非容器环境迁移到 Kubernetes 环境中. 自从 Dock ...

  4. Kubernetes容器网络及网络模型

    1.Docker 网络模型 在讨论Kubernetes网络之前,让我们先来看一下Docker网络.Docker采用插件化的网络模式,默认提供bridge.host.none.overlay.macla ...

  5. 深入理解Kubernetes容器网络

    在Kubernetes中要保证容器之间网络互通,网络至关重要.而Kubernetes本身并没有自己实现容器网络,而是通过插件化的方式自由接入进来.在容器网络接入进来需要满足如下基本原则: Pod无论运 ...

  6. Kubernetes学习总结(18)—— Kubernetes 容器网络

    前言 在 Kubernetes 中要保证容器之间网络互通网络至关重要.Kubernetes 本身并没有实现容器网络而是通过插件化的方式自由接入,容器网络接入需要满足如下基本原则: pod 无论运行在任 ...

  7. Kubernetes — CNI 网络插件规范

    目录 文章目录 目录 CNI CNI 规范 CNI Plugin Main 插件 Bridge 插件 HOST-DEVICE MACVLAN 第三方网络插件 CNI 使用的 I/O 接口虚拟化 CNI ...

  8. 容器网络规范CNM vs. CNI

    CNM 1 由Docker公司提出,在docker项目下的libnetwork项目中被采用. 2 工作流程 CNI 1 CNI是由CoreOS提出的容器组网规范,被K8s.Mesos.Cloud Fo ...

  9. 容器编排技术 -- Kubernetes 声明网络策略

    容器编排技术 -- Kubernetes 声明网络策略 1 Before you begin 2 创建一个nginx deployment 并且通过服务将其暴露 3 测试服务能够被其它的 pod 访问 ...

  10. Kubernetes容器网络(一):Flannel网络原理

    前言 本文主要分享Flannel如何解决跨主机容器之间通信问题的,如果你对主机内容器之间通信流程还不了解,建议先看下这篇文章:Docker网络原理 1.前置网络知识 1).tun/tap设备 tun/ ...

最新文章

  1. apktoolkit apk反编译没有文件_重新编译mono——修改apk中Assembly-CSharp.dll并重新打包...
  2. ASP.NET Core Web Razor Pages系列教程六:添加搜索功能
  3. 当退出python时是否释放全部内存_Python面试题:高级特性考察
  4. 用户操作-用户详情服务器端代码实现
  5. 学机械也想转嵌入式?
  6. FreeCAD v0.19源码编译与VS2017+Qt5环境搭建
  7. 调研Android的开发环境的发展演变
  8. eureka-7-多网卡下的ip选择
  9. Oracle常用的日期函数
  10. k8s 和 Docker 到底是什么关系?
  11. 使用自动补全功能- MATLAB
  12. java公寓报修管理系统,基于jsp的公寓报修管理系统-JavaEE实现公寓报修管理系统 - java项目源码...
  13. dll文件删不掉怎么办
  14. chronyd同步windows时钟源问题
  15. linux中opt是啥文件夹,linux根目录的各文件夹里装了什么
  16. 21世纪十大热门编程语言大集合,看你适合哪一种?
  17. linux下登录ftp使用lftp命令详解
  18. 哪一件事让你忽然意识到打工永无出路?
  19. 合数 java_java问题:素数,合数,其它
  20. 指向数组的指针的理解

热门文章

  1. 把手机上的新浪微博客户端卸载了
  2. ios7下弹出新浪微博界面,一出现就消失的问题
  3. 华为网络设备-DHCP基础配置实验
  4. 大学计算机思维导论第七讲答案,中国大学MOOC计算思维导论网课答案
  5. MT6573芯片资料集锦芯片MTK6573_环境搭建
  6. 压力传感器的封装形式
  7. 换硬币 (20 分)
  8. shal+php,学习笔记---PHP中几种加密算法(MD5,shal,base64_encode等)
  9. [GW-CTF2019] babyvm
  10. 如何查找一篇论文的源代码