CNI (容器网络接口)是一种操作容器网络规范,包含方法规范,参数规范等。 CNI 只关心容器的网络连接,在容器创建时分配网络资源,并在删除容器时删除分配的资源。因为这个焦点, CNI 有广泛的支持,规格易于实现。 CNI 接口只需要实现两个方法,一个创建容器时调用,一个删除容器时调用。
kubernetes 首先以插件的形式完成(pod)容器的网络资源设置。内置的插件包括:cni,kubenet,hostport 等。这里简单说说 kubenet 。这是一个简单的网络插件,每台机器上创建一个 br0 网桥,根据 PodCIDR 为每个 pod 设置 ip 连接到 br0 网桥上。次方式可结合一些网络路由工具完成一个小规模的集群网络 pod 互联。我们主要讲 CNI 插件。 kubernetes 以 cni 插件来支持 cni 规范,调用其他厂商和个人开发的遵循 cni 规范的各种网络插件,例如Calico
,Flannel
等。 k8s 默认情况下 cni 模式不支持端口映射等。 k8s 将容器网络设置 none,完全交给插件去管理容器网络资源。
容器网络资源包括:虚拟网卡,IP 地址, DNS,网络路由等等。容器使用独立的网络命名空间,可以具有自己的网络资源信息。这些信息数据由不同的 CNI 插件根据不同的 SDN 网络的实现给容器配置。
MidoNet 是由日本的 SDN 公司 Midkura 研发的一款网络虚拟化软件,其基于底层物理设施来实现网络虚拟化,具有分布式、分散、多层次的特点,主要作为 OpenStack 中的默认网络组件,可以让虚拟网络解决方案,特别是专为网络基础设施设计的方案,为云平台如 OpenStack 服务,并且将其网络存贮栈虚拟化。 MidoNet 为每个租户分配一个逻辑 router,租户与租户之间是相互隔离的,租户内部之间是能够相互通讯的, Midonet 支持 L2 交换、 L3 路由、 L4 负载均衡
有状态和无状态 NAT ,逻辑和分布式防火墙, BGP 与 ECMP 支持。其架构主要包含以下组件:
Agent 安装在各个计算节点,负责建立网络流量控制和提供分布式 Midonet 网络服务,路由, NAT 等他把相关的虚拟网络信息存放到 NSDB 。
Database(NSDB):存储网络配置和状态,网络拓扑,路由, Midonet 不集中处理网络功能,由 Midonet Agent 处理, Midonet Agent 会跟 NSDBs 做实时同步当有变化时候会及时同步并且更新 NSDB MidoNet 支持大规模 SDN 集群,其架构理论上支持上万节点。我们可以使用 MidoNet 完成 k8s 集群内租户内 Pod 网络互联。
SDN(软件定义网络), Midonet 软件定义你所熟知的网络组件。以下简单介绍几个核心的软件定义概念:
192.168.0.0/24
,最多可以有 253 个虚拟设备连接到本 Bridge 。Midonet 数据交换工作在三层,但是其本身不提供 IP 地址管理(IPAM),因此基于 Midonet 的 cni 插件需要完成以下工作: IPAM,租户 Router 、 Bridge 创建,容器网卡创建,以及所有端到端连接和路由过滤规则创建。
需要完成两个层面的 IP 管理, Router 级别的地址管理,每一个 Router 具有一个 IP 地址,且全局唯一不冲突。每一个 Bridge 具有一个唯一网段,连接的虚拟网卡具有全局唯一 IP 。
IPAM 有很多实现方式, CNI 插件是无状态应用,或许你需要一个守护进程来完成 IPAM 工作。基于简化架构的思路,我们使用 ETCD 来存储 IP 数据,直接由插件来操作 ETCD 。完成 IP 的使用和释放。
当新租户第一次创建容器时进行租户虚拟设备的初始化创建,上文我们已经介绍了一个租户需要创建的虚拟设备有哪些,这里我讲讲细节。
Midonet 提供了 Rest-API 来操作虚拟设备。这里注意,根据使用的不同版本的 Midonet 使用不同版本的 API 。
https://github.com/barnettZQG/golang-midonetclient
封装了 golang 版的 Midonet api 操作方法,支持 1.*和 5.*API 版本。
创建步骤如下:
简称 veth pair,是一个成对的端口,所有从这对端口一 端进入的数据包都将从另一端出来,反之也是一样.其两端可存在于不同的网络空间( Network Namespace )。容器创建成功后具有一个网络空间, k8s 此时调用 CNI 插件 ADD 方法进行网络设置。插件首先创建一对 Veth pair 。将其一端置于宿主机网络空间,调用 Midonet 绑定 API 将其与 Bridge 一个 Port 绑定。另一端在容器内并赋予 IP 地址,根据当前使用的 Bridge 网段。 与 Docker0 网卡部分原理一致。
将默认路由设置到上文创建的网卡上。例如上文创建的网卡命名为 eth0 。
根据需要设置一些 DNS 信息。
1.使用 shell 命令。
ip link *
ip netns *
ip address *
ip route *
以上命令详细使用方法网上很多了,这里不再描述。
https://github.com/vishvananda/netlink 定义了关于网卡相关与 linux 内核通信的用户空间的相关接口。
好雨云开源基于 ETCD 版的的 midonet cni 插件具有上文提到的所有功能和特性。 github:https://github.com/goodrain/midonet-cni