【原创】kubernetes之CNI理解
一、什么是CNI?
CNI-容器网络接口,CNI(容器网络接口)是Cloud Native Computing Foundation项目,由一个规范和库(用于编写用于在Linux容器中配置网络接口的插件)以及许多受支持的插件组成。CNI仅涉及容器的网络连接以及删除容器时删除分配的资源。由于这种关注,CNI具有广泛的支持,并且该规范易于实现。
除规范外,此存储库还包含一个Go语言源代码库,该库用于将CNI集成到应用程序中,以及一个示例命令行工具,用于执行CNI插件。一个单独的存储库包含参考插件和用于制作新插件的模板。
模板代码可以直接为现有的容器网络项目创建CNI插件。CNI还为从头创建新的容器网络项目提供了一个良好的框架。
二、为什么开发CNI?
Linux上的应用程序容器是一个快速发展的领域,在该领域内,由于高度特定于环境,因此无法很好地解决网络问题。我们相信,许多容器运行时和协调器将寻求解决使网络层可插入的相同问题。
为避免重复,我们认为在网络插件和容器执行之间定义一个通用接口是谨慎的:因此,我们提出了该规范,以及Go库和一组插件。
三、谁在使用CNI?
容器运行时
- rkt-集装箱发动机
- Kubernetes-一个简化容器操作的系统
- OpenShift-具有其他企业功能的Kubernetes
- Cloud Foundry-云应用程序平台
- Apache Mesos-分布式系统内核
- Amazon ECS-高度可扩展的高性能容器管理服务
- 奇异性-针对HPC,EPC和AI优化的容器平台
- OpenSVC-用于遗留和容器化应用程序堆栈的协调器
第三方插件
- Calico项目-第3层虚拟网络
- Weave-多主机Docker网络
- Contiv Networking-各种用例的策略网络
- SR-IOV
- Cilium-容器的BPF和XDP
- Infoblox-容器的企业IP地址管理
- Multus-一个多插件
- Romana-支持Kubernetes的第3层CNI插件支持网络策略
- CNI-Genie-通用CNI网络插件
- Nuage CNI-用于网络策略kubernetes支持的Nuage Networks SDN插件
- Silk-为Cloud Foundry设计的CNI插件
- 亚麻-用于开放式vSwitch的覆盖网络的CNI插件,适用于SDN / OpenFlow网络环境
- Vhostuser-一个Dataplane网络插件-支持OVS-DPDK和VPP
- Amazon ECS CNI插件-用于配置具有Amazon EC2弹性网络接口(ENI)的容器的CNI插件的集合
- 绑定CNI-用于解决故障转移和高可用性网络的链接聚合插件
- ovn-kubernetes-基于Open vSwitch(OVS)和Open Virtual Networking(OVN)构建的容器网络插件,同时支持Linux和Windows
- Juniper Contrail / TungstenFabric-提供覆盖SDN解决方案,提供多云网络,混合云网络,同时支持覆盖层,网络策略实施,网络隔离,服务链和灵活的负载平衡
- Knitter-一个支持Kubernetes多个网络的CNI插件
- DANM-适用于Kubernetes上的TelCo工作负载的CNI兼容网络解决方案
- VMware NSX –一个CNI插件,可实现自动NSX L2 / L3网络和L4 / L7负载平衡;Pod,节点和群集级别的网络隔离;Kubernetes集群的零信任安全策略。
四、接口参数
网络插件是独立的可执行文件,被上层的容器管理平台调用。网络插件只有两件事情要做:把容器加入到网络以及把容器从网络中删除。调用插件的数据通过两种方式传递:环境变量和标准输入。一般插件需要三种类型的数据:容器相关的信息,比如 ns 的文件、容器 id 等;网络配置的信息,包括网段、网关、DNS 以及插件额外的信息等;还有就是 CNI 本身的信息,比如 CNI 插件的位置、添加网络还是删除网络。
我们来看一下为容器添加网络是怎么工作的,删除网络和它过程一样。
把容器加入到网络
调用插件的时候,这些参数会通过环境变量进行传递:
CNI_COMMAND
:要执行的操作,可以是ADD
(把容器加入到某个网络)、DEL
(把容器从某个网络中删除)CNI_CONTAINERID
:容器的 ID,比如 ipam 会把容器 ID 和分配的 IP 地址保存下来。可选的参数,但是推荐传递过去。需要保证在管理平台上是唯一的,如果容器被删除后可以循环使用CNI_NETNS
:容器的 network namespace 文件,访问这个文件可以在容器的网络 namespace 中操作CNI_IFNAME
:要配置的 interface 名字,比如eth0
CNI_ARGS
:额外的参数,是由分号;
分割的键值对,比如 “FOO=BAR;hello=world”CNI_PATH
:CNI 二进制查找的路径列表,多个路径用分隔符:
分隔
网络信息主要通过标准输入,作为 JSON 字符串传递给插件,必须的参数包括:
cniVersion
:CNI 标准的版本号。因为 CNI 在演化过程中,不同的版本有不同的要求name
:网络的名字,在集群中应该保持唯一type
:网络插件的类型,也就是 CNI 可执行文件的名称args
:额外的信息,类型为字典ipMasq
:是否在主机上为该网络配置 IP masqueradeipam
:IP 分配相关的信息,类型为字典dns
:DNS 相关的信息,类型为字典
插件接到这些数据,从输入和环境变量解析到需要的信息,根据这些信息执行程序逻辑,然后把结果返回给调用者,返回的结果中一般包括这些参数:
- IPs assigned to the interface:网络接口被分配的 ip,可以是 IPv4、IPv6 或者都有
- DNS 信息:包含 nameservers、domain、search domains 和其他选项的字典
CNI 协议的内容还在不断更新,请到官方文档获取当前的信息。
五、kubernets中的使用
CNI 目前已经在 kubernetes 中开始使用,也是目前官方推荐的网络方案,具体的配置方法可以参考kubernetes 官方文档。
kubernetes 使用了 CNI 网络插件之后,工作过程是这样的:
- kubernetes 先创建 pause 容器生成对应的 network namespace
- 调用网络 driver(因为配置的是 CNI,所以会调用 CNI 相关代码)
- CNI driver 根据配置调用具体的 cni 插件
- cni 插件给 pause 容器配置正确的网络
- pod 中其他的容器都是用 pause 的网络